INTEGRATION

Claude Agent SDK + Actae.

The Claude Agent SDK owns the conversation and its tool use. Actae implements the SessionStore that backs those transcripts, so a session survives a process restart, resumes with full context, and can be forked.

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.append event.
  • 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

bash
pip 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

FieldMeaning
entriesThe transcript messages (type, uuid, timestamp, …)
mtimeStorage write time in epoch-ms, strictly monotonic
subkeysRegistered subagent transcripts, on their own channels
  • Subkeys (subagent transcripts) live on their own channels and are registered in the main transcript’s subkeys list. Deleting a main transcript cascades to its subkeys.
  • The project index tracks per-session mtime plus 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.

python
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.

python
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

typescript
import { 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-sdk installed, but constructing the store raises ImportError with 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.