Claude Agent SDK: Subagents and Session Store
The Claude Agent SDK is the Claude Code harness packaged as a library: built-in tools, subagents for context isolation, hooks, W3C trace propagation, and a session store. Claude Managed Agents is the hosted alternative for long-running async work.
Learning Objectives
- Explain the difference between the Anthropic Client SDK (raw API) and the Claude Agent SDK (harness shape).
- Describe subagents — parallelization and context isolation — and when to reach for them.
- Name the Python SDK's session store surface (`append`, `load`, `list_sessions`, `delete`, `list_subkeys`) and the role of `--session-mirror`.
- Implement a stdlib harness with built-in tools, subagent spawning with isolated context, lifecycle hooks, and a session store.
The Problem
The Claude Agent SDK is the harness behind Claude Code, exposed as a library so you can build your own agents on it. It handles tool execution, MCP servers, lifecycle hooks, subagent spawning, session persistence, and trace propagation.
You need that because a raw LLM API gives you one round-trip and nothing else. A production agent needs all of the above, and without the SDK you build each piece yourself.
The Concept
Client SDK vs Agent SDK
The two SDKs sit at different layers:
- Client SDK (
anthropic). The raw Messages API. You own the loop, the tools, and the state. - Agent SDK (
claude-agent-sdk). The Claude Code loop as a library, with built-in tool execution, MCP connections, hooks, subagent spawning, and a session store.
Pick the Client SDK when you want full control of the loop. Pick the Agent SDK when you want that loop already built.
Built-in tools
The SDK ships with 10+ built-in tools: file read/write, shell, grep, glob, web fetch, and more. Custom tools register through the standard tool-schema interface. The toy harness in Build It implements only three of them (read_file, write_file, list_dir), enough to show the registry pattern.
Subagents
A subagent is a separate agent run, spawned by an orchestrator, with its own context window. Only its result returns to the orchestrator. Anthropic documents two reasons to use one:
- Parallelization. Independent work runs concurrently. "Find the test file for each of these 20 modules" becomes 20 parallel subagent tasks.
- Context isolation. Because the subagent works in its own window, the orchestrator's context budget stays intact.
The Python SDK recently added list_subagents() and get_subagent_messages() for reading subagent transcripts.
Session store
The session store persists conversations. The Python surface has parity with TypeScript:
append(session_id, message)adds a turn.load(session_id)restores a conversation.list_sessions()enumerates sessions.delete(session_id)removes one, cascading to its subagent sessions.list_subkeys(session_id)lists the subagent keys.
The --session-mirror CLI flag mirrors the transcript to an external file as it streams, which is handy for debugging.
Hooks
Hooks are lifecycle callbacks you register to run your own code at fixed points in a run:
PreToolUseandPostToolUsegate or audit tool calls.SessionStartandSessionEndhandle setup and teardown.UserPromptSubmitacts on user input before the model sees it.PreCompactruns before context compaction.Stophandles cleanup when the agent exits.Notificationsends side-channel alerts.
Hooks are how extensions to the harness add cross-cutting behavior such as auditing, rate limits, and rule enforcement without touching the loop itself.
W3C trace context
OTel spans active on the caller propagate into the CLI subprocess through W3C trace context headers, so the whole multi-process run shows up as one trace in your backend.
Claude Managed Agents
Managed Agents is the hosted alternative, enabled with the beta header managed-agents-2026-04-01. It targets long-running async work and comes with prompt caching and compaction built in. You give up control and get managed infrastructure in return.
Where this pattern goes wrong
- Subagent over-spawn. Spawning 100 subagents for 100 tiny tasks lets overhead dominate. Batch the tasks instead.
- Hook creep. Every team adds hooks, and startup time balloons. Review them quarterly.
- Session bloat. Sessions accumulate and the store grows. Use
list_sessionswith an expiry policy.
Build It
code/main.py implements the SDK's shape in stdlib Python:
ToolandToolRegistry, with built-inread_file,write_file, andlist_dir.Subagent, which runs with a private context and returns only its results.SessionStorewith append, load, list, delete, and list_subkeys.Hooksforpre_tool_use,post_tool_use,session_start, andsession_end.- A demo where the main agent spawns 3 isolated subagents in parallel, aggregates their results, and persists the session.
Run it:
python3 code/main.py
The trace shows three things: subagent context isolation (the orchestrator's context size stays bounded), hook execution, and session persistence.
Use It
Match the tool to the job:
- Claude Agent SDK for Claude-first products that want the Claude Code harness shape.
- Claude Managed Agents for hosted, long-running async work.
- OpenAI Agents SDK (Lesson 16) if you're building OpenAI-first.
- LangGraph plus custom tools if you'd rather have a graph-shaped state machine.
Ship It
outputs/skill-claude-agent-scaffold.md scaffolds a Claude Agent SDK app with subagents, hooks, a session store, MCP server attachment, and W3C trace propagation.
Spawn a subagent when you can name what it buys you: work that can run in parallel, or a noisy task whose intermediate output you don't want in the orchestrator's context. If you can't, keep the work in the main agent. Over-spawn is the first failure mode in this lesson for a reason, and batching small tasks is almost always the better default.
Treat hooks and sessions the same way. Both pile up quietly, so give each hook a clear reason to exist and put an expiry policy on sessions from day one rather than after the store gets heavy.
Exercises
- Add a subagent spawner that batches 20 tasks into groups of 5 parallel subagents. Measure orchestrator context size vs one-per-task.
- Implement a
PreToolUsehook that rate-limitswrite_filecalls (5 per minute per session). Trace the behavior. - Wire
list_subkeysto render a subagent tree. What does deep nesting look like? - Port the toy to the real
claude-agent-sdkPython package. What changes about tool registration? - Read the Claude Managed Agents docs. When would you switch from self-hosted to managed?
Key Terms
| Term | What people say | What it actually means |
|---|---|---|
| Agent SDK | "Claude Code as a library" | Harness shape: tools, MCP, hooks, subagents, session store |
| Subagent | "Child agent" | Separate context, own budget; results bubble up |
| Session store | "Conversation DB" | Persist, load, list, delete turns with subagent cascade |
| Hook | "Lifecycle callback" | Pre/post tool, session, prompt submit, compact, stop |
| W3C trace context | "Cross-process trace" | Parent span propagates into CLI subprocess |
| Managed Agents | "Hosted harness" | Anthropic-hosted long-running async work |
--session-mirror | "Transcript mirror" | Writes session turns to an external file as they stream |
| MCP server | "Tool surface" | External tool/resource source attached to the agent |
Further Reading
- Claude Agent SDK overview: the library form of Claude Code
- Anthropic, Building agents with the Claude Agent SDK: production patterns
- Claude Managed Agents overview: hosted alternative
- OpenAI Agents SDK: counterpart
Code
- main.py (python, 219 lines)