The Claude Agent SDK gives you the same agent loop, tools and context handling that power Claude Code, as a library for Python and TypeScript. You write a prompt and a few options, and Claude reads files, runs commands and edits code on its own.
This guide walks through install, your first agent, tools, MCP, permissions, hooks, sessions, subagents, costs and deployment, with code in both languages.
- Install with
pip install claude-agent-sdk(Python 3.10+) ornpm install @anthropic-ai/claude-agent-sdk(Node.js 18.14+). - Set
ANTHROPIC_API_KEY. The SDK does not load.envfiles by itself. - The main entry point is
query(). It streams messages and ends with a result message that holdstotal_cost_usd. - Control tools with
allowed_tools,disallowed_tools, a permission mode and hooks. - Latest versions as of November 7, 2026: Python 0.2.179 and TypeScript 0.3.319. Recent releases added
onFailure: "block"for hook callbacks.
What the Claude Agent SDK Is
An agent plans its own steps and calls tools until a task is done. The Agent SDK runs the Claude Code binary under the hood and gives you a clean API on top.
Both SDKs bundle a native Claude Code binary, so most installs need nothing else.
Anthropic offers four ways to build with Claude. Here is how they differ.
| Option | Who runs the agent | Best for |
|---|---|---|
| Agent SDK | You, in your own process | Embedding a full coding or task agent in your app |
| Claude Code CLI | You, in a terminal | Daily interactive development |
Client SDK (anthropic) |
You write the tool loop | Direct Messages API calls and custom logic |
| Managed Agents | Anthropic hosts the loop | Agents you do not want to run on your own servers |
The SDK gets the same features as Claude Code: built-in tools, hooks, subagents, MCP, permissions, sessions, skills and plugins. It also reads your project’s .claude/ folder and CLAUDE.md by default.
Warning: unless Anthropic has approved it, third-party apps built on the Agent SDK may not offer claude.ai login or use claude.ai plan limits. Use API key authentication instead.
What’s New (Late October to November 2026)
The SDKs ship almost daily and each release bundles a matching Claude Code version. The notable changes from the official changelogs:
- Hook failures can block (TS 0.3.317, Python 0.2.177): set
onFailure: "block"oron_failure="block"on a hook matcher. A callback that throws, returns nothing or returns invalid output then blocks the action. - Disk-full warning (TS 0.3.317): a new
session_writes_lostsystem message tells you when a full disk stopped the transcript from saving. - Sign-in expiry (TS 0.3.318): result messages can carry
credential_expires_at. - MCP tasks (TS 0.3.319): with streaming input and
CLAUDE_AUTO_BACKGROUND_TASKS=1, an MCP task can run in the background.
Install the SDK (Step by Step)
- Check your runtime. You need Python 3.10 or newer, or Node.js 18.14 or newer.
- Make a project folder. Run
mkdir my-agent && cd my-agent. The agent can read files in this folder and its subfolders by default. - Install for Python. Use
uv initthenuv add claude-agent-sdk, or create a virtual environment and runpip install claude-agent-sdk. - Or install for TypeScript. Run
npm init -y,npm pkg set type=module,npm install @anthropic-ai/claude-agent-sdkandnpm install -D tsx. - Get an API key. Create one in the Claude Console at platform.claude.com.
- Set the key. Run
export ANTHROPIC_API_KEY=your-api-keyon macOS or Linux, or$env:ANTHROPIC_API_KEY = "your-api-key"in PowerShell. - Optional cloud providers. Set
CLAUDE_CODE_USE_BEDROCK=1,CLAUDE_CODE_USE_VERTEX=1orCLAUDE_CODE_USE_FOUNDRY=1and configure that cloud’s credentials.
Note: the TypeScript SDK gets its binary through npm optional dependencies. If you install with npm ci --omit=optional, no binary arrives. Reinstall without that flag, or install Claude Code and set pathToClaudeCodeExecutable.
Build Your First Agent
This is the official quickstart agent. It reviews utils.py for bugs and fixes them. Save it as agent.py.
import asyncio
from claude_agent_sdk import query, ClaudeAgentOptions, AssistantMessage, ResultMessage
async def main():
async for message in query(
prompt="Review utils.py for bugs that would cause crashes. Fix any issues you find.",
options=ClaudeAgentOptions(
allowed_tools=["Read", "Edit", "Glob"], # auto-approve these
permission_mode="acceptEdits", # auto-approve file edits
),
):
if isinstance(message, AssistantMessage):
for block in message.content:
if hasattr(block, "text"):
print(block.text)
elif hasattr(block, "name"):
print(f"Tool: {block.name}")
elif isinstance(message, ResultMessage):
print(f"Done: {message.subtype}")
asyncio.run(main())
The TypeScript version is almost the same. Save it as agent.ts and run npx tsx agent.ts.
import { query } from "@anthropic-ai/claude-agent-sdk";
for await (const message of query({
prompt: "Review utils.py for bugs that would cause crashes. Fix any issues you find.",
options: { allowedTools: ["Read", "Edit", "Glob"], permissionMode: "acceptEdits" }
})) {
if (message.type === "assistant" && message.message?.content) {
for (const block of message.message.content) {
if ("text" in block) console.log(block.text);
else if ("name" in block) console.log(`Tool: ${block.name}`);
}
} else if (message.type === "result") {
console.log(`Done: ${message.subtype}`);
}
}
What each part does
query(): starts the agent loop and returns an async iterator of messages.prompt: the task. Claude picks the tools it needs.options: tools, permission mode,system_prompt,model,mcp_servers,max_turnsand more.
A good run ends with Done: success. To pick a model, pass model="claude-sonnet-5-5" or model="claude-opus-5-5". You can also set fallback_model for when the main model is overloaded.
Built-in Tools and Custom Tools
The SDK ships with Claude Code’s built-in tools. The common ones are listed below.
- Files:
Read,Write,Edit,Glob,Grep. - Shell:
Bash(or PowerShell on Windows). - Web:
WebSearchandWebFetch. - Delegation:
Agent, which starts subagents.
Add your own tool
A custom tool has a name, a description, an input schema and an async handler. In Python you use the @tool decorator. You then wrap the tool in an in-process MCP server.
from typing import Annotated, Any
from claude_agent_sdk import tool, create_sdk_mcp_server, ClaudeAgentOptions
@tool("get_order_status", "Look up the status of an order", {"order_id": Annotated[str, "Order ID"]})
async def get_order_status(args: dict[str, Any]) -> dict[str, Any]:
status = "shipped" # call your real API here
return {"content": [{"type": "text", "text": f"Order {args['order_id']}: {status}"}]}
shop = create_sdk_mcp_server(name="shop", version="1.0.0", tools=[get_order_status])
options = ClaudeAgentOptions(
mcp_servers={"shop": shop},
allowed_tools=["mcp__shop__get_order_status"],
)
In TypeScript, use tool() with a Zod schema and createSdkMcpServer(). The full tool name is always mcp__{server}__{tool}. Return isError: true from the handler when something fails, so Claude can react.
Connect MCP Servers
MCP servers give your agent outside tools like GitHub, databases or browsers. The SDK supports three transports.
- stdio: a local process, set with
commandandargs. - HTTP or SSE: a remote server, set with
typeandurlplus optional headers. - SDK servers: in-process tools like the custom tool above.
options = ClaudeAgentOptions(
mcp_servers={
"claude-code-docs": {"type": "http", "url": "https://code.claude.com/docs/mcp"},
"filesystem": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-filesystem", "/Users/me/projects"],
},
},
allowed_tools=["mcp__claude-code-docs__*", "mcp__filesystem__read_file"],
)
Allow rules accept a wildcard only after a full server prefix, as in mcp__github__*. A bare "mcp__*" in allowed_tools is ignored. Need ideas? See our list of the best MCP servers.
Permissions and Permission Modes
Every tool call goes through a fixed order of checks: hooks, deny rules, ask rules, the permission mode, allow rules, and finally your canUseTool callback.
| Mode | What it does |
|---|---|
default |
No automatic approvals. Calls that need approval and match no allow rule go to canUseTool. |
dontAsk |
Anything that would prompt is denied. Good for locked-down agents. |
acceptEdits |
File edits and file operations inside the working directories are approved. |
bypassPermissions |
Tools run without prompts, apart from a few protected actions. |
plan |
Claude explores and plans. Edits go to your callback. |
auto |
A model classifier approves or blocks each action it reviews. |
allowed_tools=["Read", "Grep"]: auto-approves those tools. Other tools still exist.disallowed_tools=["Bash"]: removes the tool so Claude never sees it.disallowed_tools=["Bash(rm *)"]: keeps Bash but denies matching calls in every mode.
Warning: allowed_tools does not limit bypassPermissions. With bypass on, unlisted tools like Bash and Write still run. Use disallowed_tools to block them.
For a safe read-only agent, pair allowedTools: ["Read", "Glob", "Grep"] with permissionMode: "dontAsk".
Hooks in the SDK
SDK hooks are async callbacks, not shell scripts. They use the same events as Claude Code, such as PreToolUse, PostToolUse and Stop. This one blocks writes to .env.
from claude_agent_sdk import ClaudeAgentOptions, HookMatcher
async def protect_env(input_data, tool_use_id, context):
path = input_data["tool_input"].get("file_path", "")
if path.split("/")[-1].lower() == ".env":
return {"hookSpecificOutput": {
"hookEventName": input_data["hook_event_name"],
"permissionDecision": "deny",
"permissionDecisionReason": "Cannot modify .env files",
}}
return {} # no opinion
options = ClaudeAgentOptions(hooks={
"PreToolUse": [HookMatcher(matcher="Write|Edit", hooks=[protect_env], on_failure="block")]
})
Return {} when the hook has no opinion. With on_failure="block", a callback that raises or forgets to return blocks the action instead of letting it through.
Sessions: Continue, Resume and Fork
Inside one query() call the agent already takes as many turns as it needs. Sessions matter when you send several prompts that should share context.
| You want to | Use |
|---|---|
| Chat over many turns in one process | ClaudeSDKClient (Python) or continue: true (TypeScript) |
| Pick up the latest session after a restart | continue_conversation=True / continue: true |
| Return to a specific session | Save session_id from the result, then pass it as resume |
| Try another approach without losing the first | Fork the session |
| Write nothing to disk | persistSession: false (TypeScript only) |
A fork copies the chat history, not your files. If a forked agent edits files, those edits are real. Use file checkpointing when you need to roll file changes back.
Subagents
Subagents are helpers with their own prompt, tools and model. Claude starts them through the Agent tool, so include "Agent" in allowed_tools.
from claude_agent_sdk import ClaudeAgentOptions, AgentDefinition
options = ClaudeAgentOptions(
allowed_tools=["Read", "Grep", "Glob", "Agent"],
agents={
"code-reviewer": AgentDefinition(
description="Expert code reviewer. Use for quality and security reviews.",
prompt="You are a code review specialist. Find bugs and security issues.",
tools=["Read", "Grep", "Glob"], # read-only
model="sonnet",
),
},
)
The description tells Claude when to use the helper. The model field accepts aliases like opus, sonnet, haiku or inherit, or a full model ID.
Limit runaway agent trees
- Depth:
CLAUDE_CODE_MAX_SUBAGENT_SPAWN_DEPTH, default 3 layers. - Concurrency:
CLAUDE_CODE_MAX_CONCURRENT_SUBAGENTS, default 20 at once. - Spend:
max_budget_usd, no limit by default.
Set the first two through the env option. In TypeScript, env replaces the whole environment, so spread process.env into it.
Costs and Budget Limits
Installing the SDK costs nothing. You pay normal Claude API token prices for every request the agent makes, including subagent requests. Current prices are on our Claude API pricing page.
total_cost_usd: on the result message. It includes subagents.model_usage/modelUsage: cost and tokens split by model.usage: top-level loop only. It undercounts once subagents run.max_budget_usdandmax_turns: hard stops. The run ends witherror_max_budget_usdorerror_max_turns.
Tip: the SDK cost fields are local estimates from a bundled price table. Use them for budgets, not billing, and check the Console for real spend. Prompt caching cuts repeat costs; see our prompt caching guide.
Deploying to Production
Each query() starts a claude subprocess that owns a shell, a working directory and session files on local disk. So hosting an agent is not like hosting a stateless API wrapper.
Pick a session pattern
- Ephemeral: one container per task, deleted at the end. Good for bug fixes and document jobs.
- Long-running: persistent containers that keep sessions warm. Good for chat bots and email agents.
- Hybrid: short-lived containers that load and save sessions through a
SessionStore. Good for work that pauses for hours.
Size and secure it
- Start at: 1 GiB RAM, 5 GiB disk and 1 CPU per agent, then measure peak memory.
- Separate users: give each tenant its own
cwdand config folder, and setCLAUDE_CODE_DISABLE_AUTO_MEMORY=1. - Cost reality: Anthropic says a small container costs about $0.05 per hour, while tokens usually cost far more.
If you would rather not run the loop yourself, Anthropic’s Managed Agents host it for you.
Troubleshooting: Common Problems and Fixes
- “Not logged in” or “Invalid API key”:
ANTHROPIC_API_KEYis not set in the shell that runs the agent. Load your.envyourself with dotenv. - CLI binary not found: an install skipped optional dependencies, or pip built from source. Install Claude Code and point the SDK at it.
- Top-level await error in TypeScript: set
"type": "module"in package.json or name the file.mts. - canUseTool never fires: the tool is in
allowed_toolsor the mode auto-approves it. Use aPreToolUsehook to check every call. - MCP tools are not called: check the exact
mcp__server__toolname inallowed_toolsand that the server status is not “failed”. - Run stops with error_max_turns: raise
max_turnsand resume the same session ID. - Claude does not use your subagent: make the
descriptionclear about when to use it, or name the subagent in the prompt.
Frequently Asked Questions
Is the Claude Agent SDK free?
The SDK packages are free to install. You pay standard Claude API token prices for the requests your agent makes.
What is the difference between the Agent SDK and the anthropic SDK?
The anthropic client SDK calls the Messages API, and you write the tool loop. The Agent SDK runs the full Claude Code loop with built-in tools, permissions, sessions and hooks.
Can I use my Claude Pro or Max subscription with the Agent SDK?
For apps you ship to others, Anthropic’s docs say not to offer claude.ai login unless approved. Use an API key, or Bedrock, Vertex or Foundry credentials.
Which models work with the Agent SDK?
Any current Claude model, such as claude-opus-5-5, claude-sonnet-5-5 or claude-haiku-5-5. Set it with the model option or leave it on Claude Code’s default.
Does the Agent SDK read CLAUDE.md and skills?
Yes. By default it loads settings, skills, commands and memory from the project’s .claude/ folder and ~/.claude/. See our Claude Skills guide.
How do I stop an agent from spending too much?
Set max_budget_usd and max_turns, and cap subagents with the depth and concurrency environment variables.
What was the Claude Code SDK?
It is the old name. Anthropic renamed it to the Claude Agent SDK and publishes a migration guide for the package change.
Sources
- Claude Code Docs: Agent SDK overview
- Claude Code Docs: Agent SDK quickstart
- Claude Code Docs: Configure permissions
- Claude Code Docs: Subagents in the SDK
- Claude Code Docs: Track cost and usage
- Claude Code Docs: Hosting the Agent SDK
- Agent SDK TypeScript changelog
- Agent SDK Python changelog
- claude-agent-sdk on PyPI




