Skip to main content
An agent that forgets everything the moment a request ends is not very useful in production. Tasks need to survive restarts. Conversation history needs to be retrievable. Artifacts need to be stored and served back to callers. Without a storage layer, every agent interaction is stateless and ephemeral. That is fine for a quick local test. It breaks the moment you need reliability, resumability, or multi-turn conversations.

Why Storage Matters

Bindu’s task-first architecture depends on persistent state. Tasks move through states — submitted, working, input-required, completed — and that state needs to live somewhere durable.
Without storageWith Bindu storage
Tasks are lost on restartTasks persist across restarts
No conversation historyFull message history per task
Artifacts disappear after responseArtifacts stored and retrievable
Multi-turn conversations breakContext preserved across turns
Fine for local scriptsRequired for production agents
That is the shift: storage turns a stateless agent into a reliable, resumable service.
Bindu defaults to in-memory storage for local development. Switch to PostgreSQL for production. The storage backend is configured in agent_config.json — your agent code does not change.

How Bindu Storage Works

Bindu abstracts storage behind a consistent interface. You choose the backend in config; the rest of the system — TaskManager, workers, context handling — works the same regardless.

The Storage Model

Bindu stores three categories of data:
  • Tasks — state, messages, metadata, and lifecycle history
  • Contexts — shared conversation context across multiple tasks
  • Artifacts — outputs produced by the agent (text, files, structured data)

Tasks

Every task and its full state history, messages, and metadata.

Contexts

Shared context that spans multiple tasks in a conversation.

Artifacts

Agent outputs stored and retrievable by task ID.

Backends

Bindu supports two storage backends:
MemoryPostgreSQL
SetupNoneRequires PostgreSQL instance
PersistenceLost on restartSurvives restarts
ScalabilitySingle processMulti-instance, distributed
Use caseLocal developmentProduction
Config"type": "memory""type": "postgres"

Configuration

Storage is configured in agent_config.json. No changes to your agent code are needed when switching backends.

Memory (Development)

{
  "storage": {
    "type": "memory"
  }
}
Memory storage is the default. Tasks, contexts, and artifacts live in process memory and are gone when the agent stops. Use this for local development and testing.

PostgreSQL (Production)

{
  "storage": {
    "type": "postgres",
    "url": "postgresql://user:password@localhost:5432/bindu"
  }
}
Or via environment variable:
STORAGE__TYPE=postgres
STORAGE__URL=postgresql://user:password@localhost:5432/bindu
Bindu creates the required tables automatically on first run. No manual schema setup needed.
The STORAGE__URL environment variable takes precedence over the value in agent_config.json. Use environment variables in production to keep credentials out of your config files.

The Storage Lifecycle

Storage is used throughout the task lifecycle. Here is how it fits into a complete request: Every state transition is written to storage. If the agent restarts mid-task, the task can be recovered and resumed from its last known state.

Working with Tasks

Tasks are the primary unit of storage. Each task has a unique ID and carries its full history.

Retrieving a Task

curl -X POST http://localhost:3773/ \
  -H "Content-Type: application/json" \
  -d '{
    "jsonrpc": "2.0",
    "method": "tasks/get",
    "params": {
      "id": "task_abc123"
    },
    "id": 1
  }'
{
  "jsonrpc": "2.0",
  "result": {
    "id": "task_abc123",
    "status": {
      "state": "completed",
      "timestamp": "2026-03-30T12:00:00Z"
    },
    "history": [
      {"role": "user", "parts": [{"text": "Summarize this document"}]},
      {"role": "agent", "parts": [{"text": "Here is the summary..."}]}
    ],
    "artifacts": [
      {
        "name": "summary",
        "parts": [{"text": "The document covers..."}]
      }
    ]
  },
  "id": 1
}

Listing Tasks

curl -X POST http://localhost:3773/ \
  -H "Content-Type: application/json" \
  -d '{
    "jsonrpc": "2.0",
    "method": "tasks/list",
    "params": {},
    "id": 1
  }'

Contexts

Contexts allow multiple tasks to share a common conversation thread. When a caller provides a contextId, Bindu links the task to that context and preserves the shared history.
# First task in a context
response = await agent.send_message(
    "I am researching climate change",
    context_id="research-session-001"
)

# Follow-up task in the same context
response = await agent.send_message(
    "What were the key findings from the last IPCC report?",
    context_id="research-session-001"  # same context
)
# Agent has access to the full prior conversation
Contexts are stored alongside tasks and retrieved by contextId. They survive restarts when using PostgreSQL.

PostgreSQL Setup

For production deployments, you need a running PostgreSQL instance.

Docker (Quick Start)

docker run -d \
  --name bindu-postgres \
  -e POSTGRES_USER=bindu \
  -e POSTGRES_PASSWORD=secret \
  -e POSTGRES_DB=bindu \
  -p 5432:5432 \
  postgres:16

Environment Variables

STORAGE__TYPE=postgres
STORAGE__URL=postgresql://bindu:secret@localhost:5432/bindu

Schema

Bindu manages its own schema. On first startup with PostgreSQL configured, it creates the necessary tables:
bindu_tasks       — task state, metadata, and message history
bindu_contexts    — shared conversation contexts
bindu_artifacts   — agent output artifacts
No manual migration steps are needed for initial setup.

Real-World Use Cases

A user starts a research task, the agent asks a clarifying question, and the user responds. With persistent storage, the task resumes from input-required state with full context intact — even if the agent restarted between turns.
A data analysis task that takes several minutes. The client submits the task, gets a task_id immediately, and polls for completion. Storage keeps the task alive across the entire execution window.
Every task stores its full message history and state transitions. You can retrieve any past task by ID and inspect exactly what happened, when, and what the agent produced.
With PostgreSQL, multiple instances of the same agent share a single storage backend. Any instance can pick up a task from the queue and write results back to the same store.

Security Best Practices

Use Environment Variables

Never put database credentials in agent_config.json. Use STORAGE__URL as an environment variable and keep it out of version control.

Restrict Database Access

The Bindu agent only needs read/write access to its own tables. Use a dedicated database user with minimal permissions.

Sunflower LogoStorage is what turns a stateless script into an agent that remembers — every task, every turn, every result.