Cheat sheet · Checked Oct 28, 2026

Claude Agent SDK cheat sheet

Everything you need to run the Claude Agent SDK in Python or TypeScript, from the first install to production: which Claude tool to pick, the options that matter, the defaults that changed this year, nine recipes with code, and what an agent costs. Checked against the official docs and package registries on Oct 28, 2026.

Python · released Oct 24, 2026
claude-agent-sdk 0.2.174
TypeScript · released Oct 27, 2026
@anthropic-ai/claude-agent-sdk 0.3.312
A glowing tile travels around a circular track past a magnifying glass, a robot arm with a wrench and a check stamp while a small robot watches from the centre

Explore with AI

Browse by topic

Topic 1 of 8

Get started

Install it, pick the right tool, run one call.

Start in three steps

STEP 1

Install

Python needs 3.10 or newer and TypeScript needs Node 18.14 or newer. Claude Code is bundled, so you do not install it separately in the normal case.

STEP 2

Set a key

The SDK reads ANTHROPIC_API_KEY from the environment of the process that runs your agent. It does not load .env files for you.

STEP 3

Run one call

query() returns a stream of messages. The ResultMessage (type result in TypeScript) ends the loop and carries the outcome, the session id and an estimated cost. Read the stream to the end, because a few trailing events can follow it.

$ pip install claude-agent-sdk
$ export ANTHROPIC_API_KEY=your-api-key
import anyio
from claude_agent_sdk import query

async def main():
    async for message in query(prompt="What is 2 + 2?"):
        print(message)

anyio.run(main)

When the bundled CLI is missing

  • Python platform wheels bundle the Claude Code CLI. If pip falls back to the source distribution (for example on ARM64 Windows), install Claude Code natively and the SDK finds it on your PATH.
  • TypeScript bundles a native binary through per platform optional dependencies. If your install skips optional dependencies (for example npm ci with the omit optional flag), the SDK throws "Native CLI binary for <platform>-<arch> not found". Point pathToClaudeCodeExecutable at a separate install.
  • In TypeScript the SDK version tracks the bundled Claude Code version, so a feature that needs a Claude Code version needs the SDK release with the same patch number or later. Python does not follow that numbering.

Other providers

Set one of these in the process environment instead of an API key.

Anthropic API
ANTHROPIC_API_KEY=your-api-key
Amazon Bedrock
CLAUDE_CODE_USE_BEDROCK=1, plus AWS credentials
Claude Platform on AWS
CLAUDE_CODE_USE_ANTHROPIC_AWS=1 and ANTHROPIC_AWS_WORKSPACE_ID, plus AWS credentials
Google Cloud Agent Platform (Vertex)
CLAUDE_CODE_USE_VERTEX=1, plus Google Cloud credentials
Microsoft Foundry
CLAUDE_CODE_USE_FOUNDRY=1, plus Azure credentials

Sources: Agent SDK quickstart · Python SDK reference · TypeScript SDK reference · claude-agent-sdk on PyPI · @anthropic-ai/claude-agent-sdk on npm

Pick the right Claude tool

Anthropic ships four ways to work with Claude. They differ in who runs the agent and what comes built in. Find the row that matches how you want to build and run yours.

  • This sheet

    Embed the Claude Code agent in your own Python or TypeScript app, in a process you run

    Agent SDK

    A library that runs the Claude Code binary, with built in tools, permissions, sessions and hooks.

  • Work interactively or run one off tasks from a terminal

    Claude Code CLI

    The terminal interface, built for daily interactive use.

  • Call the Claude API directly from your own code

    Client SDK

    Direct access to the API. You write the tool loop yourself, or let the beta tool runner drive it.

  • Have Anthropic host the agent, configured through the Claude API

    Managed Agents

    A hosted agent harness that runs the loop, with sessions in an Anthropic managed sandbox or one you host.

To drive the same agent loop from another language, run the CLI as a subprocess with the -p flag and --output-format json.

What the Agent SDK gives you

Sources: Agent SDK overview

Take it with you

PDF · 18 pages · 1.5 MB

Get the PDF and infographics

The whole sheet in one file: four infographics, every option in both languages, all nine recipes with Python and TypeScript side by side, and the sources.

Enter your email and the PDF arrives in your inbox.

A fan of four infographic pages from the cheat sheet

Topic 2 of 8

Core concepts

The loop, the options and the defaults that bite.

The loop and where the knobs sit

Anthropic describes the feedback loop Claude Code runs, and offers it as a way to think about agents you build with the SDK: gather context -> take action -> verify work -> repeat. Every option on this sheet changes one of the four steps, so it helps to know which.

  1. 01

    Gather context

    What the agent can see before it acts.

    • cwd
    • tools
    • mcp_servers
    • setting_sources
    • system_prompt
  2. 02

    Take action

    Which calls run, and who approves them.

    • allowed_tools
    • permission_mode
    • can_use_tool
    • hooks
  3. 03

    Verify work

    Checks that catch a wrong result before it ships.

    • PostToolUse hooks
    • output_format
    • agents
  4. 04

    Repeat or stop

    How the loop ends, and how you tell why.

    • max_turns
    • max_budget_usd
    • ResultMessage.subtype
A glowing tile travels around a circular track past a magnifying glass, a robot arm with a wrench and a check stamp while a small robot watches from the centre
One lap of the loop

Sources: Building agents with the Claude Agent SDK · How the agent loop works

The options that matter

Python has 49 option fields and the TypeScript docs list 66. These are the ones that change behavior in practice.

PythonTypeScriptWhat it does
allowed_toolsallowedToolsPre approves tools so they run without a prompt. It does not limit what Claude can use.
toolstoolsSets which built in tools exist at all. An empty list removes every built in tool.
disallowed_toolsdisallowedToolsA bare name removes the tool. A scoped rule such as Bash(rm *) denies matching calls in every mode, bypassPermissions included.
permission_modepermissionModeHow approvals work for the whole session. See the permission modes table.
can_use_toolcanUseToolYour approval callback. It runs only when a call falls through to a prompt.
system_promptsystemPromptOmit it and you get a minimal prompt. Use the claude_code preset, with an optional append, to get the Claude Code prompt.
setting_sourcessettingSourcesOmit it and user, project and local settings load, including CLAUDE.md and skills. Pass an empty list to skip those three. Managed policy settings and auto memory still apply.
mcp_serversmcpServersServers by name. The key you choose becomes the tool prefix, mcp__<key>__<tool>.
agentsagentsSubagents defined in code, by name.
hookshooksCallbacks on events such as PreToolUse, grouped by matcher.
max_turnsmaxTurnsCap on agent turns. Nothing is capped by default.
max_budget_usdmaxBudgetUsdStops the run when the client side cost estimate reaches this value. It can overshoot, so leave headroom.
modelmodelAn alias such as sonnet or opus, or a full model ID.
fallback_modelfallbackModelA backup if the primary is overloaded, unavailable or returns a non retryable server error. Accepts a comma separated list. Rate limit errors do not trigger it.
output_formatoutputFormatA JSON Schema the final answer must match. The data arrives in structured_output.
resume, fork_sessionresume, forkSessionContinue a session by id, or branch it into a new id.
envenvEnvironment for the Claude Code subprocess. Python merges it over the parent environment. TypeScript replaces it.
skillsskillsTurns on skills: "all" or a list of exact skill names. It adds the Skill tool for you.
pluginspluginsLoads local plugins by path. A plugin can bundle skills, agents, hooks and MCP servers.
enable_file_checkpointingenableFileCheckpointingTracks file changes so you can rewind them later.
sandboxsandboxIsolates command execution. It is off by default.
include_partial_messagesincludePartialMessagesEmit partial stream events while Claude writes.

Sources: Python SDK reference · TypeScript SDK reference

Defaults that bite

Eight behaviors that surprise people, with the one line fix for each. Python names are shown. TypeScript spells them in camelCase: allowed_tools is allowedTools, mcp_servers is mcpServers, can_use_tool is canUseTool, fork_session is forkSession, max_turns is maxTurns and max_budget_usd is maxBudgetUsd.

  1. Python and TypeScript

    allowed_tools is not a whitelist

    It only pre approves. Tools you leave out stay available and fall through to your permission mode and callback.

    Do thisTo remove a tool, use tools or disallowed_tools. Keep allowed_tools for skipping prompts.

    Python SDK reference

  2. Python and TypeScript

    Settings load by default

    Leave setting_sources unset and user, project and local settings load, including CLAUDE.md, skills and slash commands. If you also set skills, only user and project load. An empty list skips those three sources, but managed policy settings and auto memory still apply. Early 0.1.0 notes say the opposite, but the migration guide records that default as reverted.

    Do thisPass setting_sources=[] (settingSources: [] in TypeScript) for a clean, repeatable run.

    Migration guide · Python SDK reference

  3. Python and TypeScript

    The system prompt is minimal

    With no system_prompt you get a short prompt that covers tool calling and leaves out the rest of the Claude Code preset, including its safety instructions.

    Do thisAsk for the claude_code preset, and use append for your own rules.

    Modifying system prompts

  4. Python and TypeScriptChanged Oct 16

    The permission default is deny

    From Claude Code v2.1.302, an app with no permission mode, and no permissions.defaultMode in its settings files, starts in default mode, which denies any call that needs approval unless a rule, hook or callback approves it. TypeScript 0.3.286 to 0.3.301 started in auto mode in some setups, then reversed.

    Do thisSet permission_mode on purpose, or supply a can_use_tool callback.

    Permissions · TypeScript SDK changelog

  5. Python and TypeScript

    Cost fields are estimates

    total_cost_usd comes from a price table inside the SDK. Parallel tool calls share one message id, so count each id once. usage leaves out subagents. A resumed session already includes its earlier spend.

    Do thisBill from the Usage and Cost API or the Console. Never add results across a resume.

    Cost tracking

  6. Python and TypeScript

    A single call raises after an error result

    When a query() call ends in an error result such as hitting max_turns, the SDK yields that result, then raises. Streaming input sessions stay alive after an error result.

    Do thisWrap the loop in try and catch, and read the result subtype.

    How the agent loop works · Python SDK reference

  7. Python

    In Python, drain the stream after interrupt()

    On ClaudeSDKClient, interrupt() does not clear buffered messages. The old messages, including the interrupted ResultMessage, are still waiting. The docs also warn that a break inside the iteration loop can cause asyncio cleanup problems.

    Do thisRead receive_response() to its result before you send the next query.

    Python SDK reference

  8. Python and TypeScript

    env merges in Python and replaces in TypeScript

    In Python, env is merged over the inherited environment. In TypeScript, env replaces it, so the subprocess loses PATH and your key unless you pass them.

    Do thisIn TypeScript, always spread process.env: env: { ...process.env, MY_VAR: "1" }.

    Python SDK reference · TypeScript SDK reference

Topic 3 of 8

Input and output

Entry points, the message stream and structured answers.

Entry points and the message stream

query()ClaudeSDKClient (Python)
SessionNew session by defaultReuses the same session
ConversationSingle exchangeMany exchanges, shared context
InterruptsNot supportedSupported
Hooks and custom toolsSupportedSupported
Best forOne off tasksChat interfaces, or when the next step depends on the answer

TypeScript has one function. Pass an async iterable as the prompt to enter streaming input mode, which keeps the session open and unlocks interrupt(), setModel() and setPermissionMode() on the returned Query.

import asyncio
from claude_agent_sdk import ClaudeSDKClient, AssistantMessage, TextBlock

async def ask(client, question):
    await client.query(question)
    async for message in client.receive_response():
        if isinstance(message, AssistantMessage):
            for block in message.content:
                if isinstance(block, TextBlock):
                    print(block.text)

async def main():
    async with ClaudeSDKClient() as client:
        await ask(client, "What's the capital of France?")
        # Same session, so the follow up keeps the context
        await ask(client, "What's the population of that city?")

asyncio.run(main())

Read the stream

import asyncio
from claude_agent_sdk import (
    query, ClaudeAgentOptions, AssistantMessage, TextBlock, ResultMessage,
)

async def main():
    options = ClaudeAgentOptions(allowed_tools=["Read", "Glob"])
    async for message in query(prompt="List the Python files here", options=options):
        if isinstance(message, AssistantMessage):
            for block in message.content:
                if isinstance(block, TextBlock):
                    print(block.text)
        elif isinstance(message, ResultMessage):
            print(message.subtype, message.num_turns, message.session_id)

asyncio.run(main())
AssistantMessage
Claude output. Its content holds blocks such as TextBlock, ToolUseBlock and ThinkingBlock.
ResultMessage
The message that ends the loop. Has subtype, num_turns, session_id, total_cost_usd and usage. The result text exists only when subtype is success.
SystemMessage
Housekeeping such as the init message that lists tools and the session id.
StreamEvent
Partial output, only when include_partial_messages is on.

Result subtypes: success, error_max_turns, error_max_budget_usd, error_during_execution, error_max_structured_output_retries.

Sources: Python SDK reference · TypeScript SDK reference · How the agent loop works

Recipe 4

Get structured output

Give a JSON Schema and read validated data from the result.

import asyncio
from claude_agent_sdk import query, ClaudeAgentOptions, ResultMessage

schema = {
    "type": "object",
    "properties": {
        "title": {"type": "string"},
        "severity": {"type": "string", "enum": ["low", "medium", "high"]},
    },
    "required": ["title", "severity"],
}

options = ClaudeAgentOptions(
    output_format={"type": "json_schema", "schema": schema},
)

async def main():
    async for message in query(prompt="Triage: login page returns 500", options=options):
        if isinstance(message, ResultMessage) and message.subtype == "success":
            print(message.structured_output)   # a dict that matches the schema

asyncio.run(main())
  • The SDK validates against your schema and asks Claude again on a mismatch. Past the retry limit the result is error_max_structured_output_retries.
  • With Zod 4 in TypeScript, convert with z.toJSONSchema(schema, { target: "draft-7" }). The schema must be draft 7.

Sources: Structured outputs · Python SDK reference

Topic 4 of 8

Extend with tools

Custom tools, MCP servers and subagents.

Custom tools, MCP and subagents

Three ways to widen what Claude can do: your own functions, servers you connect, and specialist agents you hand work to.

Recipe 1

Give Claude your own tool

A custom tool is a function wrapped in an in process MCP server.

A small robot connects a gear shaped tool module to a console by a cable while three indicator lights turn green one after another
Plugging in a tool
import asyncio
from claude_agent_sdk import (
    tool, create_sdk_mcp_server, query, ClaudeAgentOptions, ResultMessage,
)

@tool("add", "Add two numbers", {"a": float, "b": float})
async def add(args):
    return {"content": [{"type": "text", "text": f"Sum: {args['a'] + args['b']}"}]}

calculator = create_sdk_mcp_server(name="calculator", version="1.0.0", tools=[add])

options = ClaudeAgentOptions(
    mcp_servers={"calc": calculator},          # the key sets the tool prefix
    allowed_tools=["mcp__calc__add"],          # pre-approves the call
)

async def main():
    async for message in query(prompt="What is 12.5 plus 30?", options=options):
        if isinstance(message, ResultMessage) and message.subtype == "success":
            print(message.result)

asyncio.run(main())
  • The key in mcp_servers sets the prefix. Key calc and tool add give mcp__calc__add. Dots and spaces in the key become underscores.
  • The handler must be async and return a dict with a content list. Set is_error (isError in TypeScript) to report a failure. An uncaught exception comes back to Claude as an error and the loop continues.
  • Mark a tool read only (readOnlyHint) and Claude can run it in parallel. Custom tools run one at a time otherwise.
  • TypeScript tools take a Zod schema, so install zod alongside the SDK.

Sources: Custom tools · Python SDK reference · TypeScript SDK reference

Recipe 2

Connect an MCP server

Point the SDK at a local process or a remote server, then allow its tools by prefix.

import os
from claude_agent_sdk import query, ClaudeAgentOptions

options = ClaudeAgentOptions(
    mcp_servers={
        # A local process: the SDK starts it and talks to it over stdio
        "docs": {"command": "node", "args": ["./my-mcp-server.js"]},
        # A remote server over HTTP
        "search": {
            "type": "http",
            "url": "https://example.com/mcp",
            "headers": {"Authorization": f"Bearer {os.environ.get('MCP_TOKEN', '')}"},
        },
    },
    # The key becomes the prefix, so mcp__docs__* allows every tool from that server
    allowed_tools=["mcp__docs__*", "mcp__search__*"],
)
  • The key in mcp_servers becomes the tool prefix, so mcp__docs__* allows every tool from the docs server.
  • A local server needs a command, with optional args and env. A remote one needs a url, with type set to http or sse, and optional headers.
  • strict_mcp_config (strictMcpConfig in TypeScript) makes the SDK use only the servers you pass. It ignores .mcp.json, user settings, plugin servers and claude.ai connectors.
  • In the TypeScript SDK, MCP servers connect in the background by default since 0.3.142 in mid May 2026. Set MCP_CONNECTION_NONBLOCKING=0 to wait up to 5 seconds before the first query again.

Sources: Connect to external tools with MCP · Custom tools · Python SDK reference · TypeScript SDK reference · TypeScript SDK changelog

Recipe 3

Hand work to a subagent

Define a specialist in code and Claude delegates to it through the Agent tool.

Pulses of light travel down cables from a large robot to three smaller robots that wave in turn
Delegating to subagents
import asyncio
from claude_agent_sdk import query, ClaudeAgentOptions, AgentDefinition

async def main():
    async for message in query(
        prompt="Review the authentication module for security issues",
        options=ClaudeAgentOptions(
            allowed_tools=["Read", "Grep", "Glob", "Agent"],
            agents={
                "code-reviewer": AgentDefinition(
                    description="Expert code review specialist. Use for security and quality reviews.",
                    prompt="You are a code review specialist. Report issues with file and line.",
                    tools=["Read", "Grep", "Glob"],   # read only
                    model="sonnet",
                ),
            },
        ),
    ):
        if hasattr(message, "result"):
            print(message.result)

asyncio.run(main())
  • The description tells Claude when to use the agent. The tools list limits what it can do. Leave tools out and it inherits every tool a subagent can use.
  • Every docs example puts Agent in allowed_tools. A subagent starts with a fresh context and receives only the prompt Claude writes for it, unless Claude starts a fork.
  • A programmatic agent wins over a same named file in .claude/agents. In Python, AgentDefinition fields are camelCase, and a snake_case keyword raises a TypeError.
  • Agents spawn up to depth 3 and 20 at once by default (CLAUDE_CODE_MAX_SUBAGENT_SPAWN_DEPTH and CLAUDE_CODE_MAX_CONCURRENT_SUBAGENTS).

Sources: Subagents · Python SDK reference · TypeScript SDK reference

Topic 5 of 8

Customize behavior

System prompt, settings, skills and plugins.

System prompt, settings and environment

Recipe 5

Set the prompt, settings and environment

Decide what Claude starts with, instead of inheriting whatever is on the machine.

from claude_agent_sdk import ClaudeAgentOptions

options = ClaudeAgentOptions(
    system_prompt={
        "type": "preset",
        "preset": "claude_code",                # restores the Claude Code prompt
        "append": "Answer in two sentences.",   # your own rules go on top
    },
    setting_sources=["project"],                # [] loads no filesystem settings
    env={"ENABLE_PROMPT_CACHING_1H": "1"},      # merged over the parent environment
)
  • ENABLE_PROMPT_CACHING_1H=1 in env asks for the one hour cache TTL. The default is 5 minutes on API keys and the cloud providers.
  • For many tenants on one host, the docs recommend setting setting_sources to an empty list and CLAUDE_CODE_DISABLE_AUTO_MEMORY=1, with a separate CLAUDE_CONFIG_DIR and working directory for each tenant.

Sources: Modifying system prompts · Cost tracking · Hosting the Agent SDK

Skills, commands and memory

Load automatically from your project .claude/ folder and from ~/.claude/, the same as Claude Code.

Plugins

Package skills, agents, hooks and MCP servers and load them by local path.

Sources: Agent SDK overview · Python SDK reference · TypeScript SDK reference

Topic 6 of 8

Control and observability

Permissions, hooks, sessions and cost.

Permissions

ModeWhat happens
defaultNo automatic approvals. A call that needs approval goes to your callback. With no callback it is denied.
acceptEditsFile edits and filesystem operations such as mkdir, rm and mv are approved automatically inside the working directory and any additional directories.
planClaude explores and plans without editing source files. Edits are never auto approved.
dontAskAnything that would prompt is denied without calling your callback. Calls approved by allowed_tools or allow rules still run.
autoA model classifier reviews actions such as shell commands and network requests, then allows or blocks each. It needs a model and provider that support it.
bypassPermissionsTools run without prompts, except actions no mode approves. Explicit ask rules still prompt. TypeScript also needs allowDangerouslySkipPermissions.
  • Order of checks: hooks, then deny rules, then ask rules, then the permission mode, then allow rules, then your callback.
  • A main session in plan, acceptEdits, auto or bypassPermissions passes that mode to its subagents.
  • client.set_permission_mode() and setPermissionMode() change the mode mid session, in streaming mode only.

Sources: Permissions · Python SDK reference

Recipe 6

Ask before risky calls

A permission callback sees each call that is not already approved and answers allow or deny.

A barrier arm at a stone gate lifts as a green lamp brightens while a small robot raises a pass card
The approval gate
import asyncio
from claude_agent_sdk import (
    query, ClaudeAgentOptions, PermissionResultAllow, PermissionResultDeny,
    ToolPermissionContext,
)

async def gate(tool_name: str, tool_input: dict, context: ToolPermissionContext):
    command = tool_input.get("command", "")
    if tool_name == "Bash" and "rm " in command:
        return PermissionResultDeny(message="Deletes are not allowed here")
    return PermissionResultAllow()

# Do not also list Bash in allowed_tools: allow rules run before the callback
options = ClaudeAgentOptions(can_use_tool=gate)

async def main():
    async for message in query(prompt="Clean up the temp files", options=options):
        print(message)

asyncio.run(main())
  • The callback runs only when the permission flow falls through to a prompt. Calls approved by allowed_tools, allow rules or the mode never reach it.
  • Do not also list the gated tool in allowed_tools. Allow rules approve the call before your callback runs, and the SDK warns about the overlap.
  • In default mode with no callback, anything that needs approval is denied.

Sources: Permissions · Python SDK reference

Hooks

Python hook eventFires
PreToolUseBefore a tool runs. Can allow, deny, ask, defer or rewrite input.
PostToolUseAfter a tool runs. Can add context or replace the tool output.
PostToolUseFailureWhen a tool call fails.
UserPromptSubmitWhen a prompt is submitted.
StopWhen the agent is about to stop. Ignores matchers.
SubagentStartWhen a subagent starts.
SubagentStopWhen a subagent stops.
PreCompactBefore the conversation is compacted.
NotificationOn notification events.
PermissionRequestWhen a permission decision is needed.
  • TypeScript supports 33 hook events and Python supports the 10 above. SessionStart and SessionEnd are TypeScript only. In Python they exist only as shell command hooks in settings files.
  • A matcher of *, an empty string or no matcher matches everything. Letters, digits, underscores, pipes and commas make an exact list such as Edit|Write. Anything else is treated as a regular expression, such as mcp__memory__.*.
  • Python spells the reserved words continue_ and async_ with a trailing underscore. The SDK converts them.
  • Default timeout is 600 seconds for most events and 30 for UserPromptSubmit, per the docs. The source comment still says 60, so set timeout yourself if it matters.

Sources: Hooks · Python SDK reference · TypeScript SDK reference

Recipe 7

Block a command with a hook

A PreToolUse hook runs before the tool and can deny it with a reason Claude sees.

Parcels slide along a conveyor through a scanner arch whose lamp flashes while a small robot inspector checks a clipboard
A hook at the scanner
import asyncio
from claude_agent_sdk import query, ClaudeAgentOptions, HookMatcher

async def block_rm_rf(input_data, tool_use_id, context):
    command = input_data["tool_input"].get("command", "")
    if "rm -rf" in command:
        return {
            "hookSpecificOutput": {
                "hookEventName": "PreToolUse",
                "permissionDecision": "deny",
                "permissionDecisionReason": "Dangerous command blocked",
            }
        }
    return {}  # allow, no changes

options = ClaudeAgentOptions(
    allowed_tools=["Bash"],
    hooks={"PreToolUse": [HookMatcher(matcher="Bash", hooks=[block_rm_rf])]},
)

async def main():
    async for message in query(prompt="Remove the build folder", options=options):
        print(message)

asyncio.run(main())
  • Return an empty dict to allow with no changes.
  • If several hooks disagree, deny beats defer, defer beats ask, and ask beats allow.
  • A matcher filters on the tool name only, not on file paths. Check paths inside the callback.
  • Hooks may not fire when the agent stops at max_turns.

Sources: Hooks · Python SDK reference

Sessions and file checkpoints

Recipe 8

Resume or fork a session

Capture the session id from any result, then continue it or branch it.

A pulse of light runs along a path and splits at an orange flag into two branches while a small robot watches
Resume or fork
import asyncio
from claude_agent_sdk import query, ClaudeAgentOptions, ResultMessage

async def main():
    session_id = None
    async for message in query(prompt="Analyze the auth module"):
        if isinstance(message, ResultMessage):
            session_id = message.session_id      # present on every result

    # Resume: same session, history intact
    async for message in query(
        prompt="Now suggest a refactor",
        options=ClaudeAgentOptions(resume=session_id),
    ):
        pass

    # Fork: new session ID, original untouched
    async for message in query(
        prompt="Instead of JWT, outline OAuth2",
        options=ClaudeAgentOptions(resume=session_id, fork_session=True),
    ):
        if isinstance(message, ResultMessage):
            forked_id = message.session_id

asyncio.run(main())
  • The session_id is on every result, success or error.
  • Forking branches the conversation history, not the filesystem. Use file checkpointing if you need files restored.
  • In Python you can set CLAUDE_CODE_SKIP_PROMPT_HISTORY in env to avoid writing transcripts. TypeScript has persistSession: false.

Sources: Sessions · Python SDK reference

Cost and limits

Recipe 9

Cap turns and spend

Set both limits on every production agent, then read why a run stopped.

A gauge needle sweeps from the green zone toward red and back while sand runs in an hourglass beside a small robot
Watching the meter
import asyncio
from claude_agent_sdk import query, ClaudeAgentOptions, ResultMessage, ResultError

options = ClaudeAgentOptions(
    allowed_tools=["Read", "Glob", "Grep"],
    max_turns=8,
    max_budget_usd=0.50,    # a client side estimate; it can overshoot
)

async def main():
    try:
        async for message in query(prompt="Summarize the README", options=options):
            if isinstance(message, ResultMessage):
                print(message.subtype, message.num_turns, message.total_cost_usd)
    except ResultError as err:
        # A single call raises after it yields the error result
        print("stopped:", err)

asyncio.run(main())
  • Neither limit has a default. The docs call a budget a good default for production agents.
  • Spend can pass the budget by up to one response, plus whatever subagents still running spend before they stop. Leave headroom.
  • The cost number is an estimate from a bundled price table. The Usage and Cost API or the Console is the billing record.

Sources: How the agent loop works · Cost tracking

Topic 7 of 8

Deployment

Models, billing, hosting and naming.

Models and prices

ModelAPI IDInputOutputNote
Claude Fable 5.1claude-fable-5-1$10$50Demanding reasoning and long horizon agent work
Claude Opus 5.5claude-opus-5-5$4$20Where Anthropic says to start for most workloads
Claude Sonnet 5.5claude-sonnet-5-5$2$10Fast, for daily work
Claude Haiku 5.5claude-haiku-5-5$0.10$0.50Fastest. $0.50 in and $2.50 out above 100,000 prompt tokens
  • Per million tokens. All four have a 1M token context window and 128K max output, and none is deprecated.
  • Cache pricing: a 5 minute write costs 1.25x base input and a 1 hour write 2x. A cache hit costs 0.1x, except 0.025x on Fable 5.1 and 0.05x on Opus 5.5 and Sonnet 5.5.
  • With no model set, a session uses Claude Code default, which is Opus 5.5 on Pro, Max, Team, Enterprise and the Anthropic API.
  • Each model keeps its own prompt cache, so switching models mid session recomputes the conversation uncached at the new rates.

Aliases for the model option

opus

Latest Opus. Resolves to Opus 5.5 on the Anthropic API.

sonnet

Latest Sonnet. Resolves to Sonnet 5.5 on the Anthropic API.

haiku

Latest Haiku. Resolves to Haiku 5.5 on the Anthropic API.

fable

The Fable model for your provider. Fable 5.1 unless you override it, except in Claude apps gateway sessions, which use Fable 5.

best

The fable model where available to you, otherwise opus.

opusplan

Opus in plan mode, then Sonnet to execute.

sonnet[1m], opus[1m]

The 1M context variants.

Aliases move as new models ship and differ by provider (Bedrock and Google Cloud resolve sonnet to Sonnet 4.5 today). Pin a full ID such as claude-opus-5-5 when you need repeatable behavior.

Sources: Models overview · Pricing · Model configuration · Agent SDK configuration

Auth and billing rules

  • Use API key authentication, or a cloud provider, in anything you ship. Anthropic does not allow third party developers to offer claude.ai login or its rate limits in their products unless previously approved.
  • Anthropic also bars routing requests through Free, Pro or Max plan credentials on behalf of your users, and bars collecting or storing claude.ai credentials or session tokens.
  • Your own scripts are different. When you are signed in with your own plan, the SDK and claude -p still draw from the limits of that plan. On Oct 7, 2026 the Help Center added that Max and Team plans include monthly API credits for the SDK and claude -p when they run with a Console API key.
  • Credential order, simplified: cloud provider variables first, then ANTHROPIC_AUTH_TOKEN, then ANTHROPIC_API_KEY, then other helpers, and subscription login last.

Sources: Legal and compliance · Use the Claude Agent SDK with your Claude plan · Authentication · Agent SDK quickstart · Agent SDK overview

Running it for real

What it isOne session is one Claude Code CLI subprocess that owns a shell, a working directory and session files. Hosting it is not like hosting a stateless API wrapper.
SizeStart at 1 GiB RAM, 5 GiB disk and 1 CPU per agent. The docs call that a floor, and memory grows with session length. In TypeScript, an alpha prewarm() spare process holds about 230 to 260 MB.
TimeoutsNo top level session timeout exists. Use max_turns, and AgentDefinition maxTurns for a subagent.
StateTranscripts live in ~/.claude/projects and vanish on restart. Mirror them with a SessionStore adapter if you scale down or move hosts.
NetworkOutbound HTTPS to api.anthropic.com or your cloud endpoint, plus your MCP servers. The subprocess does not listen on a port.
IsolationThe sandbox option is off by default, and Linux needs bubblewrap and socat for it. The docs say command parsing is a permission gate, not a sandbox. Run untrusted work in a container or VM.
Many tenantsEmpty setting_sources, CLAUDE_CODE_DISABLE_AUTO_MEMORY=1, a CLAUDE_CONFIG_DIR and a working directory per tenant, and per tenant egress rules.
ObservabilitySet CLAUDE_CODE_ENABLE_TELEMETRY=1 and OpenTelemetry exporters. Traces need CLAUDE_CODE_ENHANCED_TELEMETRY_BETA=1.

Sources: Hosting the Agent SDK · Securely deploying agents · Subagents

Naming and license

Using Claude branding is optional. Your product should keep its own branding and not look like Claude Code or any Anthropic product.

Allowed

  • "Claude Agent", preferred for dropdown menus
  • "Claude", inside a menu already labeled "Agents"
  • "{YourAgentName} Powered by Claude", if you already have an agent name

Not permitted

  • "Claude Code" or "Claude Code Agent"
  • Claude Code branded ASCII art, or visual elements that mimic Claude Code

Use of the SDK is governed by Anthropic Commercial Terms of Service, including when it powers products you offer to your own customers, except where a component or dependency carries its own license.

Sources: Agent SDK overview

Topic 8 of 8

Reference

What changed, quick answers and sources.

What changed in 90 days

  1. Aug 4 · Python 0.2.129

    Breaking. Skill names are validated, so wildcards raise ValueError. Use skills="all" or a Skill rule in allowed_tools. Python SDK changelog

  2. Aug 18 · Python 0.2.140

    ResultError added. can_use_tool works with query() and a string prompt. forward_subagent_text added. In process MCP servers support MCP 2.x. Python SDK changelog

  3. Sep 22 to 23 · TypeScript 0.3.280, Python 0.2.158

    verbatim_prompts option: prompts are delivered as written, with no @path expansion or slash command dispatch. TypeScript SDK changelogPython SDK changelog

  4. Sep 24 · TypeScript 0.3.282

    New smaller entry point, @anthropic-ai/claude-agent-sdk/core, and an alpha prewarm(). TypeScript SDK changelog

  5. Sep 29 to 30 · Claude Code 2.1.285, TypeScript 0.3.286

    claude -p and Python SDK sessions with no permission mode started in auto mode on third party providers or with telemetry off. TypeScript followed the next day. Claude Code changelogTypeScript SDK changelog

  6. Oct 7 · Help Center

    Max and Team plans now include monthly API credits that cover the SDK and claude -p when run with a Console API key. Use the Claude Agent SDK with your Claude plan

  7. Oct 9 · Claude Code 2.1.296

    SDK cost estimates price Sonnet 5.5 cache reads at $0.10 per million tokens, down from $0.20. Claude Code changelog

  8. Oct 14 · Python 0.2.166

    Typed hook output classes and a SystemInitData type. Python SDK changelog

  9. Oct 16 · Claude Code 2.1.302

    No permission mode means default mode again, reversing Sep 29. Fork subagents are on by default. Claude Code changelog

  10. Oct 26 · TypeScript 0.3.311

    Minimum Node version raised from 18.0.0 to 18.14.0. TypeScript SDK changelog

All dates are 2026. Both SDKs release almost daily, and most releases only bump the bundled Claude Code version. Read the changelogs before you take a minor release.

Quick answers

Is the Claude Agent SDK the same as the Claude Code SDK?

Yes, it was renamed. The Python package went from claude-code-sdk to claude-agent-sdk, ClaudeCodeOptions became ClaudeAgentOptions, and the TypeScript package moved from @anthropic-ai/claude-code to @anthropic-ai/claude-agent-sdk. The rename shipped in late September 2025.

Do I have to install Claude Code first?

Normally no. Python platform wheels and the TypeScript optional dependencies bundle a native Claude Code build. You only install it yourself when your package manager skips the bundle.

Can my users sign in with their Claude subscription?

Not unless Anthropic has approved it in advance. Products built on the SDK should use API key authentication or a supported cloud provider.

Is total_cost_usd what I will be billed?

No. It is a client side estimate from a price table inside the SDK. The Usage and Cost API and the Console usage page are the billing record.

Python or TypeScript?

The core loop is the same. TypeScript has more hook events (33 against 10), per tool always_ask and always_deny policies for custom tools, and a persistSession option. Choose the language your team already ships in.

Sources

Package versions come from the PyPI and npm registries. Behavior, prices and dates come from Anthropic's official docs and changelogs, all read on Oct 28, 2026. The code examples were checked against the versions at the top of the page.

Your AI agents, built by an AI engineer. No handoffs, no lock in. Start my agent build.