# Resume ClaudeAgent sessions on any replica from the database

> Agno's `ClaudeAgent` saves the Claude session id and every Claude Code transcript line to Postgres or SQLite, so a restart or a turn on a different worker continues the same Claude conversation.

- Published: 2026-10-12
- Author: Yash Pratap Solanky
- Categories: Changelog
- Canonical: https://www.agno.com/blog/resume-claudeagent-sessions-on-any-replica-from-the-database
- Markdown: https://www.agno.com/blog/resume-claudeagent-sessions-on-any-replica-from-the-database.md

With `PostgresDb`, `AsyncPostgresDb`, `SqliteDb` or `AsyncSqliteDb` as its `db`, Agno's `ClaudeAgent` hands Claude Code a transcript store. Each line Claude Code appends to its local transcript also becomes a row in the new `agno_transcripts` table, and the Claude session id sits in `session_data["claude_sdk_session_id"]`. A replica that never ran the session passes that id to Claude Code as `resume`, and Claude Code loads the conversation from the rows.

Claude Code keeps every conversation as a transcript file on the disk of the machine that ran it. Earlier releases kept the session id only in process memory, so after a restart, or when a turn reached another AgentOS worker, Claude quietly began a new conversation while the AgentOS UI still showed the full history.

![Two replicas and one shared database. Replica A runs turn 1 with ClaudeAgent and appends every transcript line Claude Code writes to the database. The database, PostgresDb or SqliteDb in sync or async form, holds claude_sdk_session_id in agno_sessions and one row per transcript line in agno_transcripts. Replica B runs turn 2 from another working directory, loads the stored lines and resumes the same Claude session. When a stored session can no longer resume, Claude starts fresh with the Agno history.](https://www.agno.com/images/v3-1-3-claude-transcripts-replicas.png)

Give the agent a supported database and the same `id` on every replica:

```python
from agno.agents.claude import ClaudeAgent
from agno.db.postgres import PostgresDb

agent = ClaudeAgent(
    id="support-agent",  # also the transcript project_key, keep it stable across replicas
    db=PostgresDb(db_url="postgresql+psycopg://ai:ai@localhost:5532/ai"),
)
agent.run("When is the deploy window?", session_id="agno-session-1")
```

Transcripts are keyed by `project_key`, which defaults to the agent id. Set your own stable, tenant-specific key when several agents share one database. The store keeps append order across processes and skips entries whose uuid it already holds.

### What the table holds

We ran two replicas as separate Python processes against one SQLite file, each with its own working directory. A stand-in replaced Claude Code and the model: like the real SDK, it resumes a session only from a transcript it can find, and here the only place to find one is the store Agno attaches. On the previous release, replica B started a new Claude session (`resume=None`) and nothing was stored. The output below is real, from this release.

```text
[replica-a] session_data.claude_sdk_session_id=a33d4c0a-0022-4734-883c-0cc0b5eaab62
[replica-b] SDK asked to resume=a33d4c0a-0022-4734-883c-0cc0b5eaab62 prompt='When is the deploy window?'
[replica-b] status=COMPLETED content='Earlier you told me: Remember this: the deploy window is Tuesday 14:00'

agno_transcripts
project_key   | session_id                           | subpath | position | type      | agno_session_id
support-agent | a33d4c0a-0022-4734-883c-0cc0b5eaab62 |         | 1        | user      | agno-session-1
support-agent | a33d4c0a-0022-4734-883c-0cc0b5eaab62 |         | 2        | assistant | agno-session-1
support-agent | a33d4c0a-0022-4734-883c-0cc0b5eaab62 |         | 3        | user      | agno-session-1
support-agent | a33d4c0a-0022-4734-883c-0cc0b5eaab62 |         | 4        | assistant | agno-session-1
```

Each row also carries `framework` (`claude-agent-sdk`), the line's `entry_uuid`, the raw JSON `entry` and `created_at`. The stand-in sent a project key derived from each replica's working directory, and the store wrote `support-agent` for both, which is why replica B finds replica A's lines.

### When the session cannot resume

If Claude Code reports the stored session as missing before it sends any message, Agno logs a warning, forgets the id and starts a new Claude session with the Agno history written into the prompt. Deleting the rows and running a third replica showed it:

```text
WARNING Claude SDK: could not resume session a33d4c0a-0022-4734-883c-0cc0b5eaab62 for session agno-session-1: Command failed with exit code 1. Starting a new one.
[replica-c] SDK asked to resume=None prompt='Previous conversation (for context, do not repeat it):\nuser: Remember this: the deploy window is Tuesday 14:00\nassistant: OK\nuser: When is the deploy window?\nassistant: Earlier you told me: Remember this: the deploy window is Tuesday 14:00\n\nCurrent message:\nWhen is the deploy window?'
[replica-c] session_data.claude_sdk_session_id=f97dfb7c-aee3-4fce-9b8a-8bf4976e0f39
```

Errors that arrive after Claude has started streaming still fail the run, so no output is duplicated, and an API error on resume keeps the stored id. If mirroring a line keeps failing, the run still completes and records a `transcript_persistence_failed` warning in `RunOutput.metadata["warnings"]`.

Agno skips the store when the database has no transcript support, when you pass your own `session_store`, or when `enable_file_checkpointing` is on, and logs which case applies. Claude and Codex runs without streaming now also keep their tool calls and results in the stored run history. The release's own tests pass against this setup, with 19 store tests on SQLite and async SQLite, including the Claude SDK's session store conformance suite, and 17 `ClaudeAgent` persistence, resume and fallback tests against their fake SDK.

See the [cookbook](https://github.com/agno-agi/agno/blob/main/cookbook/frameworks/claude-agent-sdk/transcript_store.py), and learn more about [Claude native transcripts](https://docs.agno.com/agent-os/multi-framework/sessions#claude-native-transcripts) in the documentation.
