Claude Agent SDK in production 2026: building agents on the Claude Code harness
How the Claude Agent SDK turned the Claude Code harness into a library, and what teams ship with it in 2026. Core primitives, hooks, subagents, sessions, MCP, the Dynamic Workflows release, self-hosted sandboxes, MCP tunnels, the Spotify Honk case study, and a clear-eyed comparison with the OpenAI Agents SDK, Pydantic AI, and LangGraph.
In September 2025 Anthropic quietly renamed a library it had been shipping for a year. The Claude Code SDK became the Claude Agent SDK, and the rename was the loudest thing about the release: the team had realized the harness that drives Claude Code, the same agent loop, the same tool runner, the same context management, was useful for a lot more than coding. By April 2026, monthly search demand for “claude agent sdk” had gone from roughly 50 to 14,800, Spotify was merging 650 agent-authored pull requests a month off a single deployment built on it, and Anthropic had shipped enough production features (Dynamic Workflows, self-hosted sandboxes, MCP tunnels) that the SDK had become the default way teams wire Claude into long-running, tool-using workflows.
Why this stack matters now
The Claude Agent SDK is not a thin wrapper around the Messages API. It is the same code path Claude Code runs against, published as a Python library (3.10 or later) and a TypeScript library, with a bundled native binary in the npm package so a Node project does not have to install Claude Code separately. What that buys a production team is the entire harness Anthropic has been hardening on its own engineers and on the million-user-plus Claude Code install base for two years: a tested agent loop, built-in tools for file and shell work, a permission system, a hook surface for deterministic interception, subagents for parallel work in isolated context, sessions on disk, MCP for external integrations, and a filesystem-based configuration story that lets a product manager drop a markdown file into a repo and change the agent’s behavior.
The argument for picking it over a hand-rolled OpenAI or Anthropic client is the same argument the OpenAI Agents SDK makes on the other side of the fence: you do not want to write the agent loop yourself. The argument for picking it over the OpenAI Agents SDK is narrower and more specific: when the workload is a coding agent, a filesystem-first agent, or any long-running agent that has to read and edit a project, the Claude Agent SDK ships the file and shell primitives as first-class tools, and the same code that runs in a developer terminal runs in a CI pipeline or a production service with no rewrite.
The 2026 numbers
- Two language bindings, one harness. claude-agent-sdk on PyPI (Python 3.10+) and @anthropic-ai/claude-agent-sdk on npm. Both wrap the same Claude Code binary; the TypeScript package bundles the binary as an optional dependency so a Node service does not need a separate install.
- 7,400+ GitHub stars and 1,100+ forks on the Python repo by mid-2026, with the TypeScript SDK on a similar trajectory and a healthy community of plugins, skills, and example agents in the anthropics/claude-agent-sdk-demos repo.
- Dynamic Workflows, shipped May 28, 2026, lets one agent plan and run up to 1,000 parallel subagents in a single session. The lead agent decomposes the task, assigns each piece to a specialist with its own model and tools, and synthesizes the results after internal verification. The release is in research preview on Enterprise, Team, and Max plans.
- Self-hosted sandboxes and MCP tunnels, shipped May 19, 2026, moved tool execution off Anthropic’s infrastructure for teams that needed it. Sandboxes run on Cloudflare, Daytona, Modal, Vercel, or your own VPC; MCP tunnels expose private MCP servers without opening inbound firewall holes.
- 650+ pull requests per month, merged. The Spotify Honk agent, built on the Claude Agent SDK and integrated into Spotify’s Fleet Management system, authors more than 650 production pull requests a month and has merged more than 1,500 in total, saving engineers up to 90 percent of the time they would have spent writing migrations by hand.
- Two surfaces for two deployment shapes. The Agent SDK is the library you run inside your own process; Managed Agents is the hosted REST API where Anthropic runs the agent loop and provisions a sandboxed container per session. The two share concepts and most teams pick one or the other per workload, not both.
From Claude Code SDK to Claude Agent SDK
Claude Code launched in February 2025 and reached general availability mid-year. The SDK that shipped alongside it was called the Claude Code SDK, and the framing was that the library let a CI pipeline or a custom UI drive the same harness that ran in a developer terminal. By the third quarter of 2025 the team noticed that the harness was being used for a lot of non-coding work: research agents, customer service workflows, document review, data analysis. The harness is general; the name was misleading. In September 2025 Anthropic renamed it to Claude Agent SDK and the “Claude Code as a library” framing became “agent harness as a library.” The underlying code did not change in the rename; the positioning did, and from late 2025 onward the docs split into two surfaces, the Claude Code product and the Claude Agent SDK that ships the same internals to anyone who wants them.
The split matters because it gave Anthropic permission to ship production features that did not belong in a CLI for developers. Dynamic Workflows is the clearest example: a thousand parallel subagents make sense in a codebase-scale migration that runs overnight, and they do not really make sense in an interactive terminal. The SDK gets the same primitive Claude Code gets, and the CLI happens to be one client of it.
Core concepts: query, ClaudeSDKClient, tools, hooks, subagents, sessions
The SDK exposes a small surface. Six concepts cover almost every production deployment; the rest of the docs is variations on how to wire them up.
The query function is the one-shot entry point. You give it a prompt and a ClaudeAgentOptions object and it returns an async iterator of messages. The agent loop runs until it produces a final result or hits the configured turn limit. This is what a CI job or a webhook handler usually calls.
The ClaudeSDKClient is the bidirectional version. You open a client, send messages, receive responses, and keep the session alive across turns in your own process. This is what a chat UI or a long-running service usually wraps. The client gives you a streaming surface, hook callbacks fire on every tool call, and the session state lives in the same Python or TypeScript object you would already have in application memory.
A tool is something the agent can invoke. Out of the box the SDK ships Read, Write, Edit, Bash, Glob, Grep, Monitor, WebSearch, WebFetch, and AskUserQuestion. None of those need configuration; they just work against the filesystem and shell of the process the SDK is running in. Custom tools are functions you decorate with @tool (Python) or define on an in-process MCP server, and the framework registers them on every run.
A hook is a callback that fires at a specific point in the agent lifecycle. The events are PreToolUse, PostToolUse, Stop, SessionStart, SessionEnd, and UserPromptSubmit. Hooks can return a structured response that approves, denies, or modifies the action the model wanted to take. This is how you ship a production agent that cannot run rm -rf or write to /etc, and how you log every file change to an audit log for compliance.
A subagent is a specialist Claude instance the main agent can spawn. Each subagent gets its own instructions, its own tool list, and its own fresh context window. The parent invokes a subagent through the Agent tool; the subagent runs to completion; only its final message comes back. This is the pattern that keeps long sessions cheap and focused, and it is the same pattern Dynamic Workflows scales to a thousand parallel children.
A session is the persistent conversation state. The SDK writes it as JSONL in your working directory by default. You can capture a session id, resume the same session later with the resume option, or fork it to explore two paths from the same midpoint. Sessions are how the SDK avoids reaching for a vector store on day one: most multi-turn work fits inside the session log, and that log replays cleanly into the next run.
Architecture: how a request flows through the SDK
The mental model is a small stack on top of the Messages API. Your application calls query or ClaudeSDKClient, the harness builds the system prompt and tool definitions, the agent loop sends them to the model, the model returns either a final message or a tool call, the harness runs the tool against the local filesystem or shell, hooks fire on the boundaries, and the loop continues until the model produces an end-of-turn message.
Your application (CLI, web service, CI job, chat UI)
|
| query("fix the bug in auth.py", options)
v
+----------------------------------------------------+
| Claude Agent SDK harness |
| |
| 1. Resolve .claude/ and CLAUDE.md from cwd |
| 2. Build system prompt, tool list, skill index |
| 3. Open session (write JSONL to .claude/sessions) |
+----------------------------------------------------+
|
v
+----------------------------------------------------+
| Agent loop |
| |
| 1. Send messages + tools to the Messages API |
| 2. Receive tool calls |
| - PreToolUse hooks fire (can deny) |
| - Tool runs against local fs / shell / MCP |
| - PostToolUse hooks fire (can log, transform) |
| 3. Receive subagent invocation -> spawn child |
| - Fresh context, isolated tools, own session |
| - Final message returns as Agent tool result |
| 4. Receive final assistant message |
+----------------------------------------------------+
|
v
+----------------------------------------------------+
| Output |
| - Stream of message objects to async iterator |
| - Session log persisted to disk |
| - Audit trail in any hook you wired |
+----------------------------------------------------+
|
v
Result back to your application codeThree things in this flow carry the production work. The session log on disk means a crash mid-run does not lose the conversation; the next process can resume by id. The hooks fire synchronously on the boundaries, so a PreToolUse hook that denies a Bash call halts the action before any side effect reaches the system. And the subagent boundary is a real context boundary: parent and child do not share a context window, the child does not see the parent’s tool history, and only the final message returns. That property is what makes Dynamic Workflows feasible at a thousand children.
Your first agent: query with built-in tools
The simplest useful agent is a few lines. The pattern below reads a directory, finds TODO comments, and writes a summary. No custom tools, no hooks, no MCP, just the built-ins.
import asyncio
from claude_agent_sdk import query, ClaudeAgentOptions
async def main():
options = ClaudeAgentOptions(
allowed_tools=["Read", "Glob", "Grep", "Write"],
permission_mode="acceptEdits",
cwd="./src",
)
async for message in query(
prompt=(
"Find every TODO comment under the current directory. "
"Group them by file. Write the result to TODO_SUMMARY.md."
),
options=options,
):
if hasattr(message, "result"):
print(message.result)
asyncio.run(main())Three things in this snippet are worth pointing at. The allowed_tools list is the security perimeter: the agent cannot run anything outside it, and a request that needs Bash would simply fail. The permission_mode setting auto-approves the writes the agent decides to make; the alternatives are ask (interactive prompt) and deny (no writes allowed at all). The cwd parameter sandboxes the filesystem tools to a specific directory, which is the difference between an agent that operates on a feature branch and an agent that operates on your home directory.
Custom tools: in-process MCP servers
The agent will almost always need to do something the built-ins cannot. The SDK ships an in-process MCP server primitive for exactly that case: you define functions in Python or TypeScript, decorate them, and the framework registers them as MCP tools the model can call. No subprocess, no separate server, no extra binary.
from claude_agent_sdk import (
tool, create_sdk_mcp_server,
ClaudeAgentOptions, ClaudeSDKClient,
)
# 1. Tools are normal Python functions with a typed input schema.
@tool("recent_orders", "Return the most recent orders for a customer", {
"customer_id": int,
"limit": int,
})
async def recent_orders(args):
rows = await db.fetch(
"SELECT id, total_cents, status, placed_at FROM orders "
"WHERE customer_id = $1 ORDER BY placed_at DESC LIMIT $2",
args["customer_id"], args["limit"],
)
return {
"content": [
{"type": "text", "text": str([dict(r) for r in rows])}
]
}
@tool("issue_refund", "Issue a refund for one order", {
"order_id": int,
"amount_cents": int,
})
async def issue_refund(args):
await db.execute(
"INSERT INTO refunds (order_id, amount_cents) VALUES ($1, $2)",
args["order_id"], args["amount_cents"],
)
return {
"content": [
{"type": "text", "text": f"Refunded {args['amount_cents']} on order {args['order_id']}."}
]
}
# 2. Wrap the tools in an in-process MCP server.
support = create_sdk_mcp_server(
name="support",
version="1.0.0",
tools=[recent_orders, issue_refund],
)
# 3. Hand the server to the agent.
options = ClaudeAgentOptions(
mcp_servers={"support": support},
allowed_tools=[
"mcp__support__recent_orders",
"mcp__support__issue_refund",
],
system_prompt=(
"You are a refund agent. Always look up the order before "
"refunding. Refuse refunds on orders older than 30 days."
),
)
async with ClaudeSDKClient(options=options) as client:
await client.query("Please refund order 12345 for customer 42.")
async for msg in client.receive_response():
print(msg)Four things this pattern gets right. The tool schema is derived from the dict you pass to @tool, so editing a Python signature also edits what the model sees. The MCP server runs in the same process the SDK does, so the tool function shares the database pool and config the rest of your service uses; no IPC, no token plumbing. The allowed_tools list uses the mcp__server__tool naming convention the SDK enforces, which keeps the security perimeter explicit even when you have a lot of tools. And the system_prompt is the only place the domain logic lives; the agent definition itself is just glue.
Hooks: the boundary code that keeps the agent honest
Hooks are the deterministic counterpart to the non-deterministic model. They run on the boundaries of the agent loop and they can do anything Python or TypeScript code can do: validate, log, block, transform, prompt the user. The PreToolUse hook is the most consequential one in production because it can deny a tool call before any side effect fires.
from claude_agent_sdk import (
query, ClaudeAgentOptions, HookMatcher,
)
# Block any Bash command that touches secrets or production paths.
async def deny_dangerous_bash(input_data, tool_use_id, context):
if input_data["tool_name"] != "Bash":
return {}
command = input_data["tool_input"].get("command", "")
blocked = (
"rm -rf",
".env",
"/etc/",
"kubectl apply",
"psql prod",
)
if any(token in command for token in blocked):
return {
"hookSpecificOutput": {
"hookEventName": "PreToolUse",
"permissionDecision": "deny",
"permissionDecisionReason": (
f"Refused: command contains a blocked token. "
f"Command was: {command}"
),
}
}
return {}
# Append every Edit and Write to an audit log for compliance.
from datetime import datetime, timezone
async def audit_file_changes(input_data, tool_use_id, context):
if input_data["tool_name"] not in ("Edit", "Write"):
return {}
path = input_data["tool_input"].get("file_path", "?")
with open("./audit.log", "a") as f:
f.write(
f"{datetime.now(timezone.utc).isoformat()} "
f"{tool_use_id} {input_data['tool_name']} {path}\n"
)
return {}
options = ClaudeAgentOptions(
allowed_tools=["Read", "Write", "Edit", "Bash", "Glob", "Grep"],
permission_mode="acceptEdits",
hooks={
"PreToolUse": [
HookMatcher(matcher="Bash", hooks=[deny_dangerous_bash]),
HookMatcher(matcher="Write|Edit", hooks=[audit_file_changes]),
],
},
)The matcher field is a regex against the tool name, so one hook can cover a family of related tools without enumerating them. The hook return value is a structured dict; for a PreToolUse hook, hookSpecificOutput.permissionDecision is the one field that matters, and it gets attached to a reason the model sees in the tool result. A denied call is not a silent failure: the model reads the reason, adjusts the plan, and usually picks a different approach on the next turn.
Subagents and Dynamic Workflows
Subagents are the SDK’s answer to long context. A parent agent that has to read fifty files and reason about each one will burn its context window on intermediate state and lose focus on the task. The pattern that scales is to push exploratory work into a child, let the child finish in its own context, and let only the final answer come back.
from claude_agent_sdk import (
query, ClaudeAgentOptions, AgentDefinition,
)
options = ClaudeAgentOptions(
allowed_tools=["Read", "Glob", "Grep", "WebFetch", "Bash", "Agent"],
agents={
"log-analyst": AgentDefinition(
description="Reads recent error logs and produces a one-paragraph summary.",
prompt=(
"Find the loudest error pattern in the logs under ./logs. "
"Summarize what is failing and where. Two sentences."
),
tools=["Read", "Glob", "Grep"],
),
"deploy-historian": AgentDefinition(
description="Reads deploy history and surfaces the last risky change.",
prompt=(
"Run git log on the deployments repo and surface the last "
"commit that touched the failing service. One sentence."
),
tools=["Bash", "Read"],
),
"ticket-searcher": AgentDefinition(
description="Searches the support tracker for related complaints.",
prompt=(
"Use the support MCP server to find tickets opened in the "
"last 30 minutes that mention the failing endpoint."
),
tools=["mcp__support__search_tickets"],
),
},
)
async for message in query(
prompt=(
"Service 'checkout' is paging. Spawn log-analyst, "
"deploy-historian, and ticket-searcher in parallel. "
"Combine their findings into one incident summary."
),
options=options,
):
if hasattr(message, "result"):
print(message.result)Each subagent runs with its own context, its own tool list, and its own model if you set one. The parent invokes them through the Agent tool, which means Agent has to be in the parent’s allowed_tools list; without it the parent cannot spawn anything. The subagent definitions are a dictionary the SDK indexes by name, and the parent picks one at runtime based on the description string. In production the description is the only thing the parent reads when deciding which child to call, so it is the single highest-leverage prompt in the whole agent.
Dynamic Workflows, the May 2026 release, scales this pattern. The lead agent decomposes a task at runtime, fans out to up to a thousand parallel subagents, lets them work on a shared filesystem, checks in mid-workflow to verify they are on track, and synthesizes results after internal comparison. The mechanics are still subagent invocations under the hood; what is new is the planning loop on top, which the SDK runs for you on the Enterprise, Team, and Max plans, and the cap is one thousand children per session. Codebase-scale work that used to take a week of bespoke scripting (a fleet-wide Spring Boot upgrade, a TypeScript major version bump across every service) is one prompt against the SDK now.
Sessions: resume and fork
A session is a JSONL file in your working directory. The SDK writes one per run. The session id comes back on the first SystemMessage with subtype init; you can store it, hand it to the next process, and pick up where you left off.
from claude_agent_sdk import (
query, ClaudeAgentOptions, SystemMessage, ResultMessage,
)
session_id = None
# Turn 1: walk the auth module.
async for message in query(
prompt="Read everything in src/auth and summarize the public API.",
options=ClaudeAgentOptions(allowed_tools=["Read", "Glob", "Grep"]),
):
if isinstance(message, SystemMessage) and message.subtype == "init":
session_id = message.data["session_id"]
# Turn 2 (could be a different process, hours later): resume.
async for message in query(
prompt="Now find every caller of those functions across the repo.",
options=ClaudeAgentOptions(resume=session_id),
):
if isinstance(message, ResultMessage):
print(message.result)Two patterns we see on engagements. Long-running coding agents store the session id in their tracker (a Linear or Jira ticket field), so a re-run picks up the same context without re-reading the codebase. Customer support agents store the session id keyed by user, so the next message from the same user lands on the same session, and the agent remembers what it already looked up. Fork is the other axis: if you want to explore two paths from a midpoint (try fix A vs fix B), fork the session at that point and run two queries in parallel.
Self-hosted sandboxes and MCP tunnels
The default deployment shape runs the SDK in your own process, which means the tools execute against your own filesystem and your own shell. That is fine for CI pipelines and internal tools. It is not fine for an agent that has to run untrusted code, edit a repository it should not be allowed to break, or touch services in a regulated network. The May 2026 release added two features for those cases.
Self-hosted sandboxes move tool execution off Anthropic’s default container and onto an environment you control. The orchestration layer (the agent loop, the context management, the planning) still runs on Anthropic; only the tools move. Five providers shipped at launch: Cloudflare Workers, Daytona, Modal, Vercel, and your own VPC through a worker the SDK ships. The same Agent definition runs against any of them, and the choice is a one-line change to the environment configuration.
MCP tunnels solved the inverse problem. Internal MCP servers (an internal Jira, an internal database viewer, an internal knowledge base) sit behind a firewall and cannot be reached from Anthropic’s infrastructure. The tunnel deploys a lightweight gateway in your network that makes one outbound connection to Anthropic, and the agent reaches every MCP server behind the gateway over that encrypted tunnel. No inbound firewall rules, no public endpoints, no rebuild of the existing MCP server. The pattern is the same shape Stacklok and other vendors had been shipping out of band; Anthropic made it a first-party primitive.
The two features compose. A regulated workload runs the SDK in a customer-controlled Cloudflare sandbox, reaches its internal MCP servers over a tunnel, and never has any code or data leave the perimeter. Anthropic still drives the loop, which is the part that benefits most from frequent updates and tuning.
Skills, plugins, and filesystem-based configuration
The SDK reads .claude/ in the working directory and ~/.claude/ in the home directory the same way Claude Code does. That means four things travel with a repo and shape the agent’s behavior without any code change: skills, commands, project memory, and plugins.
Skills live in .claude/skills/<name>/SKILL.md and teach the agent a repeatable workflow. Anthropic introduced them in October 2025 and they have become the recommended way to ship reusable agent capabilities. A skill’s description sits in context; the agent loads the full file when the task calls for it. Skills are progressive disclosure for instructions, and they compose: a repo can ship its own skills, a plugin can bundle skills the team installs across many repos.
CLAUDE.md (or .claude/CLAUDE.md) is the project memory file. Anything in it is loaded as part of the system prompt on every run. This is where the project-level context (the architecture, the conventions, the do-not-touch list) lives, and editing it changes the agent’s behavior on the next run.
Plugins are bundles of skills, agents, hooks, and MCP servers a team installs through the SDK’s plugins option. The plugin format is filesystem-based and version-controllable, which means a security team can ship a hooks bundle that blocks dangerous bash commands and an application team can install it as a one-line dependency.
Real-world use cases
Three production stories carry most of the lessons we have seen on engagements.
Spotify built Honk, a background coding agent, on the Claude Agent SDK and wired it into the company’s Fleet Management system. Engineers trigger Honk from Slack or directly from their phones; the agent picks up a transformation task (convert Java AutoValue classes to Records, upgrade a framework with breaking changes, apply a configuration update across a hundred repositories) and opens a pull request when it is done. By mid-2026 the system was producing 650 merged PRs a month and had crossed 1,500 PRs total since its July 2025 rollout. Spotify’s Chief Architect, Niklas Gustavsson, called Claude their model of choice for large-scale code transformation work, and the engineering blog cites a 90 percent reduction in the time engineers spend on migrations the agent handles. The point of the story is not the raw throughput; it is that the SDK absorbed the agent harness so the Spotify team could spend its engineering budget on the Fleet Management integration, not on rebuilding a tool runner.
Incident response is the canonical non-coding use case. The pattern we see is a lead agent that receives the page, then fans out to three or four specialist subagents: a log analyst that grep's the last hour of logs, a deploy historian that walks git history on the deployments repo, a ticket searcher that hits an internal Linear or Jira MCP server, and a metrics reader that pulls from Datadog or Grafana. Each child returns one paragraph; the lead agent stitches them into an incident summary with a probable cause and a suggested next step. The shape is the same Dynamic Workflows scales, just at a smaller fan-out. The win for on-call is that the first page is no longer a context switch; the engineer reads the summary, not the raw logs.
Customer support is the third pattern. A ClaudeSDKClient sits behind a chat surface, holds a session per user, calls in-process MCP tools that touch the orders database and the billing system, and uses hooks for the guardrails: PreToolUse denies refund tools above a configurable dollar amount, PostToolUse writes every refund to an audit log that the compliance team owns. Sessions persist across conversations, so the next message from the same user lands on the same agent state, and the agent remembers what it already looked up. The pattern is the cheapest production agent shape we ship to clients in 2026, and the SDK absorbs the parts (session storage, hook plumbing, MCP) that used to be the largest engineering line items.
Agent SDK vs Managed Agents
Anthropic ships two agent surfaces and the difference is the most common question we get. The Claude Agent SDK is a library you run inside your own process; Managed Agents is a hosted REST API where Anthropic runs the agent loop and provisions a sandboxed container per session.
The split is not about capability; both surfaces share the same harness and most of the same primitives. It is about who runs the compute. With the SDK, the agent loop runs in your process and the tools touch your filesystem. With Managed Agents, the loop runs on Anthropic, the tools run in an Anthropic-managed container, and your code drives it through events streamed back over an HTTP connection. The SDK is the right pick for local prototyping, agents that operate on your filesystem and your services, and any workload where you want the loop in-process for latency or compliance reasons. Managed Agents is the right pick for long-running asynchronous sessions, fan-out work where you do not want to provision sandboxes yourself, and any workload where the agent has to outlive your process.
A common path is to prototype with the Agent SDK locally, keep the same Agent and tool definitions, and move to Managed Agents for production where the sandbox and session management become someone else’s problem. Early users of Managed Agents in production include Notion, Asana, and Sentry; teams that ship the Agent SDK in process include Spotify, the Anthropic internal engineering org, and every Claude Code user by definition.
Claude Agent SDK vs OpenAI Agents SDK, Pydantic AI, LangGraph
Four frameworks own the production agent conversation in 2026. They model the same problem differently and they fit different teams.
The OpenAI Agents SDK is the closest peer. Both are small, opinionated libraries from a frontier-model vendor, both ship sessions, handoffs (or subagents), guardrails (or hooks), and MCP. The line between them is where their built-in tools point. OpenAI’s ship Web Search, Computer Use, File Search, and the Connector Registry out of the box; Anthropic’s ship Read, Write, Edit, Bash, Glob, Grep, Monitor out of the box. For coding agents and filesystem-first workflows the Anthropic SDK pays for itself immediately; for browsing agents and the new OpenAI-hosted MCP ecosystem the OpenAI SDK does. Most teams we work with end up running both, one per workload class.
Pydantic AI is the typed-Python play. It is the right pick when the workload is a typed API that happens to call an LLM, and the team values strict output contracts above everything else. The Claude Agent SDK is the right pick when the workload is an agent that happens to expose an API, and the team values the file and shell primitives, the hook surface, and the subagent model.
LangGraph is the graph-orchestration play. Explicit state machines, cyclic graphs, conditional edges, checkpointers. The Claude Agent SDK does not try to be a state machine framework; the loop is implicit and the subagent boundary carries the structure. For regulated workflows where the auditor wants to see the state diagram, LangGraph still wins. For agentic workflows where the structure is “a lead agent plus a handful of specialists,” the Claude Agent SDK is less code and easier to debug.
A rough decision rule we use on engagements. Coding and filesystem-first work goes to the Claude Agent SDK. Voice, browsing, and the OpenAI-hosted Apps ecosystem go to the OpenAI Agents SDK. Typed Python APIs that wrap an LLM go to Pydantic AI. Long-running stateful workflows that need rollback go to LangGraph. The four compose; we ship systems that use the Claude Agent SDK for the heavy in-process agent and the OpenAI Agents SDK for the voice surface in the same product.
Advantages and limitations
The Claude Agent SDK wins a lot of arguments in 2026, but it is not free. An honest list of the trade-offs.
Strengths. The harness is the same one Claude Code uses, which means it is tested at a scale most agent frameworks will never see. The built-in tools cover the file and shell work that every coding or filesystem agent needs, with no implementation cost. Hooks are a real, synchronous interception surface, not an after-the-fact callback; production safety becomes a code change rather than a prompt engineering exercise. Subagents are first-class and Dynamic Workflows scales them to a thousand parallel children, which is the only practical path we have seen for codebase-scale work. Sessions live on disk as JSONL, which means resume and fork are file operations, not vendor lock-in. Multi-language: Python and TypeScript with the same primitives. And the SDK provider-agnostic in the same way Claude Code is; you can point it at Bedrock, Vertex, or Microsoft Foundry through environment variables.
Trade-offs. The harness is opinionated. Tools, hook event types, permission modes, the agent loop shape: these are decisions Anthropic made and you live with. Teams that want a graph orchestration model find LangGraph a better fit; teams that want a stricter type contract find Pydantic AI a better fit. The SDK is Claude-only in practice: it works against Bedrock and Vertex Claude endpoints but not against other vendors’ models. Dynamic Workflows is in research preview as of mid-2026 and is gated to Enterprise, Team, and Max plans, which puts it out of reach of teams on the standard developer tier. Self-hosted sandboxes ship across five providers, but the provider integration is still maturing and each one has its own quirks. And the in-process MCP server pattern, while elegant, means tool failures take the whole agent process down; out-of-process MCP servers are still the right pick for tools that touch flaky third-party APIs.
When not to use it. A pure chat endpoint with no tools and no filesystem work does not need an agent framework; the anthropic Python client is enough. A workload that needs a state machine with rollback (a regulated approval flow, a financial transaction graph) wants LangGraph. A workload that is primarily a typed API contract wants Pydantic AI. And a workload that mainly drives OpenAI-hosted server tools (Computer Use, Apps SDK, Connector Registry) wants the OpenAI Agents SDK. Above the complexity threshold of one specialist agent plus one tool plus one hook, the Claude Agent SDK starts paying for itself the first time the model picks a wrong tool and you can read the hook source to understand why the action was denied.
Future trends: 2026 and beyond
Four shifts shape the Claude Agent SDK roadmap and the broader Anthropic agent platform for the next year and a half.
Self-hosted sandboxes become the default for regulated workloads. The May 2026 release made it a configuration change, and the early adopters are the teams that could not run agents in shared infrastructure at all. We expect the rest of the agent framework market to catch up by 2027, with Cloudflare Workers and Modal becoming common runtime targets across vendors.
Dynamic Workflows redefine codebase-scale work. A thousand parallel subagents is the difference between a fleet migration that takes a week of bespoke scripting and a fleet migration that runs overnight from one prompt. The pattern is novel enough that most teams have not internalized it yet; the ones who have are already finding work that did not exist before because it was not tractable.
Skills become the cross-vendor agent capability format. Anthropic introduced Skills in October 2025 and they are now the recommended way to ship reusable agent capabilities. The format is markdown plus a directory, which is portable, version-controllable, and compatible with the Apps SDK ecosystem on the OpenAI side. We expect Skills to be a real interoperability story by late 2026, with the same skill running on the Claude Agent SDK, the OpenAI Agents SDK, and the Managed Agents surface.
The SDK and Managed Agents converge. The two surfaces share concepts already (Agent, tool, session, hook). Each Anthropic release ships them in lockstep, and the boundary between “library you run” and “API you call” keeps getting thinner. By 2027 we expect the same Agent definition file to run unchanged in both surfaces, with the deployment shape becoming a configuration choice rather than a code rewrite.
Conclusion: the Anthropic side of the agent stack
The interesting thing about the Claude Agent SDK is that most of it is not new. Typed tools, sessions for memory, hooks on the boundaries, subagents for isolated context, MCP for external integrations, filesystem-based configuration. None of these are Anthropic inventions; the OpenAI Agents SDK, Pydantic AI, and LangGraph all ship their own versions. What Anthropic’s contribution is that the same primitives plug straight into the Claude Code harness, with no glue code, and the filesystem and shell tools that every coding or filesystem-first agent needs ship in the box.
For new agent work in 2026 where Claude is already the default model, the argument against starting on the Claude Agent SDK is thin. The migration cost from a hand-rolled anthropic client is small; the migration cost from Claude Code is essentially zero, since the SDK is the harness the CLI uses. The remaining decisions are how much of the ecosystem to adopt (skills, plugins, Dynamic Workflows, self-hosted sandboxes) and whether to compose with another SDK for surfaces the Anthropic side does not own (the OpenAI Agents SDK for voice and the Apps ecosystem, Pydantic AI for the typed boundary). Both decisions can be made gradually. The first one only has to be made once.
Further reading
- Claude Agent SDK overview (code.claude.com) - the canonical reference for query, ClaudeSDKClient, built-in tools, hooks, subagents, sessions, and MCP integration.
- Building agents with the Claude Agent SDK (anthropic.com) - the engineering team’s framing for why the harness exists, what the primitives are for, and how to structure a production agent.
- anthropics/claude-agent-sdk-python (GitHub) - the Python SDK source, current at v0.2 in mid-2026, with examples for custom tools, hooks, and bidirectional conversations.
- anthropics/claude-agent-sdk-demos (GitHub) - the official demo agents: email assistant, research agent, coding agents, and more.
- Coding Is No Longer the Constraint (Spotify Engineering) - the writeup of the Honk agent built on the Claude Agent SDK, the Fleet Management integration, and the 650-PRs-per-month production deployment.
- Anthropic ships Dynamic Workflows (MarkTechPost) - the May 28, 2026 release notes for Dynamic Workflows, the thousand-subagent cap, and how the planning loop runs on top of the existing subagent primitive.
- Anthropic debuts MCP tunnels and self-hosted sandboxes (The New Stack) - the May 19, 2026 release coverage with the Cloudflare, Daytona, Modal, and Vercel provider list.
- MCP tunnels documentation (platform.claude.com) - the official tunnel architecture, gateway deployment, and the Managed Agents and Messages API integration.
- OpenAI Agents SDK and AgentKit in production 2026 - the OpenAI side of the agent stack and the closest peer to the Claude Agent SDK.
- Pydantic AI in production 2026 - the typed Python alternative that pairs well with the Claude Agent SDK for the typed-boundary half of a service.
- LangGraph in 2026: production AI agents as state machines - the graph-orchestration framework that composes above a Claude Agent SDK loop.
- MCP in production AI integrations 2026 - the deeper read on the Model Context Protocol that the Claude Agent SDK consumes as a first-class integration.
- Multi-agent orchestration in 2026 - the broader pattern of supervisors, specialists, and parallel subagents that Dynamic Workflows scales.
- AI coding agents in production 2026 - the broader coding-agent ecosystem the Claude Agent SDK and Spotify Honk sit inside.
