What this integration is
ActaeClaudeSessionStore is a drop-in implementation of the Claude Agent SDK’s SessionStore protocol. The SDK still runs the agent, decides when to append, and reconstructs context on resume; Actae is the durable backend. There is also an optional hooks adapter that forwards tool events as Actae events for observability.
- Durable transcripts. Every append is a cursor-aligned, versioned snapshot, plus a
claude.session.appendevent. - Cross-process resume. A new process with the same project key and session id loads the full transcript and continues.
- Fork a session. Copy the transcript into a new session and refine a later turn without re-running the earlier ones.
- Full protocol coverage.
append,load,delete,list_sessions,list_subkeys,list_session_summaries.
Durable, resumable sessions
bashpip install 'actae-client[claude]'python
from actae_client import Actae
from claude_agent_sdk import ClaudeAgentOptions, query
actae = Actae.from_env()
store = actae.claude.session_store()
async for message in query(
prompt="Refactor this module",
options=ClaudeAgentOptions(session_store=store),
):
...
# New process, same Actae: continue the same conversation.
async for message in query(
prompt="Now run the tests",
options=ClaudeAgentOptions(session_store=store, resume=True),
):
...Each append writes a versioned snapshot of the transcript through transition(), so the event and the snapshot commit atomically. load returns the full transcript, which is what lets the SDK rebuild conversation context on resume=True.
Deterministic channels
Sessions map to channels deterministically, so any process computes the same channel for the same session. Use channel_for_session() to inspect it directly:
claude:<sha256(project_key + NUL + session_id)[:16]> # main transcript claude:<sha256(project_key + NUL + session_id + NUL + sub)[:16]> # subagent transcript claude:idx:<sha256(project_key)[:16]> # project index
What is stored
entriesThe transcript messages (type, uuid, timestamp, …)mtimeStorage write time in epoch-ms, strictly monotonicsubkeysRegistered subagent transcripts, on their own channels- Subkeys (subagent transcripts) live on their own channels and are registered in the main transcript’s
subkeyslist. Deleting a main transcript cascades to its subkeys. - The project index tracks per-session
mtimeplus the SDK-owned summary sidecar. The summary is stored verbatim and never interpreted by Actae — the SDK owns its format.
Forward tool events with hooks
The optional hooks adapter forwards each tool lifecycle occurrence as a claude.hook.<event> event. This is event streaming for observability; persistence comes from the session store.
from claude_agent_sdk import ClaudeAgentOptions, query
hook = actae.claude.hook() # channel prefix defaults to "claude-hooks"
async for message in query(
prompt="Hello",
options=ClaudeAgentOptions(hooks=hook.hooks),
):
...The adapter builds PreToolUse, PostToolUse, PostToolUseFailure, UserPromptSubmit, and Stop matchers, forwarding each occurrence on claude-hooks:<sha256(session_id)[:16]>. Hook failures are caught and logged; they never break the agent run.
Fork a session and refine a later turn
ActaeClaudeSessionStore.fork_session copies the full transcript into a new session and registers it in the project index, so resume=True on the new session continues from the inherited conversation.
new_key = await store.fork_session(
project_key, session_id="sess-1", new_session_id="sess-1-fix",
reason="refine the last turn",
)
# Continue the fork with the modified prompt/config.
async for message in query(
prompt="Try a different approach for step 6",
options=ClaudeAgentOptions(session_store=store, resume=True),
):
...This is the Claude-SDK counterpart of LangGraph’s fork_thread and AgentSession.resume(fork_at_step=…): fork the conversation, then refine a later turn against inherited context. See forking & recovery.
TypeScript
typescriptimport { Actae } from '@actae/sdk';
const actae = Actae.fromEnv();
const options = { sessionStore: actae.claude.sessionStore() };Limitations, stated plainly
- The extra is optional. The module imports without
claude-agent-sdkinstalled, but constructing the store raisesImportErrorwith the install command. - Hooks are best-effort. A hook failure is logged, not propagated; use the session store when you need durable state.
- Summaries are opaque. Actae stores the SDK’s session summary sidecar verbatim and does not interpret it.
Related: sessions & adapters and the Python SDK.