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 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
asyncdefmain():
asyncfor message inquery(prompt="What is 2 + 2?"):
print(message)
anyio.run(main)
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
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.
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.
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.
Python has 49 option fields and the TypeScript docs list 66. These are the ones that change behavior in practice.
Python
TypeScript
What it does
allowed_tools
allowedTools
Pre approves tools so they run without a prompt. It does not limit what Claude can use.
tools
tools
Sets which built in tools exist at all. An empty list removes every built in tool.
disallowed_tools
disallowedTools
A bare name removes the tool. A scoped rule such as Bash(rm *) denies matching calls in every mode, bypassPermissions included.
permission_mode
permissionMode
How approvals work for the whole session. See the permission modes table.
can_use_tool
canUseTool
Your approval callback. It runs only when a call falls through to a prompt.
system_prompt
systemPrompt
Omit it and you get a minimal prompt. Use the claude_code preset, with an optional append, to get the Claude Code prompt.
setting_sources
settingSources
Omit 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_servers
mcpServers
Servers by name. The key you choose becomes the tool prefix, mcp__<key>__<tool>.
agents
agents
Subagents defined in code, by name.
hooks
hooks
Callbacks on events such as PreToolUse, grouped by matcher.
max_turns
maxTurns
Cap on agent turns. Nothing is capped by default.
max_budget_usd
maxBudgetUsd
Stops the run when the client side cost estimate reaches this value. It can overshoot, so leave headroom.
model
model
An alias such as sonnet or opus, or a full model ID.
fallback_model
fallbackModel
A 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_format
outputFormat
A JSON Schema the final answer must match. The data arrives in structured_output.
resume, fork_session
resume, forkSession
Continue a session by id, or branch it into a new id.
env
env
Environment for the Claude Code subprocess. Python merges it over the parent environment. TypeScript replaces it.
skills
skills
Turns on skills: "all" or a list of exact skill names. It adds the Skill tool for you.
plugins
plugins
Loads local plugins by path. A plugin can bundle skills, agents, hooks and MCP servers.
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.
Python and TypeScript
01
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.
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.
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.
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.
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.
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.
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.
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.
Entry points, the message stream and structured answers.
Entry points and the message stream
query()
ClaudeSDKClient (Python)
Session
New session by default
Reuses the same session
Conversation
Single exchange
Many exchanges, shared context
Interrupts
Not supported
Supported
Hooks and custom tools
Supported
Supported
Best for
One off tasks
Chat 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
asyncdefask(client, question):
await client.query(question)
asyncfor message in client.receive_response():
ifisinstance(message, AssistantMessage):
for block in message.content:
ifisinstance(block, TextBlock):
print(block.text)
asyncdefmain():
asyncwithClaudeSDKClient() as client:
awaitask(client, "What's the capital of France?")
# Same session, so the follow up keeps the contextawaitask(client, "What's the population of that city?")
asyncio.run(main())
import { query } from"@anthropic-ai/claude-agent-sdk";
// Streaming input mode: the prompt is an async iterable, so the session stays openasyncfunction* userTurns() {
yield {
type: "user"asconst,
message: { role: "user"asconst, content: "What's the capital of France?" },
parent_tool_use_id: null,
};
// await the first answer here, then yield the follow up
}
const session = query({ prompt: userTurns() });
forawait (const message of session) {
if (message.type === "result" && message.subtype === "success") {
console.log(message.result);
}
}
// While it runs, session.interrupt() and session.setPermissionMode() are available
Read the stream
import asyncio
from claude_agent_sdk import (
query, ClaudeAgentOptions, AssistantMessage, TextBlock, ResultMessage,
)
asyncdefmain():
options = ClaudeAgentOptions(allowed_tools=["Read", "Glob"])
asyncfor message inquery(prompt="List the Python files here", options=options):
ifisinstance(message, AssistantMessage):
for block in message.content:
ifisinstance(block, TextBlock):
print(block.text)
elifisinstance(message, ResultMessage):
print(message.subtype, message.num_turns, message.session_id)
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.
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__*"],
)
import { query } from"@anthropic-ai/claude-agent-sdk";
forawait (const message ofquery({
prompt: "Find the deployment guide",
options: {
mcpServers: {
// 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: `Bearer ${process.env.MCP_TOKEN ?? ""}` },
},
},
// The key becomes the prefix, so mcp__docs__* allows every tool from that server
allowedTools: ["mcp__docs__*", "mcp__search__*"],
},
})) {
if ("result"in message) console.log(message.result);
}
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.
Define a specialist in code and Claude delegates to it through the Agent tool.
Delegating to subagents
import asyncio
from claude_agent_sdk import query, ClaudeAgentOptions, AgentDefinition
asyncdefmain():
asyncfor message inquery(
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",
),
},
),
):
ifhasattr(message, "result"):
print(message.result)
asyncio.run(main())
import { query } from"@anthropic-ai/claude-agent-sdk";
forawait (const message ofquery({
prompt: "Review the authentication module for security issues",
options: {
allowedTools: ["Read", "Grep", "Glob", "Agent"],
agents: {
"code-reviewer": {
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 ("result"in message) console.log(message.result);
}
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).
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
)
import { query } from"@anthropic-ai/claude-agent-sdk";
forawait (const message ofquery({
prompt: "Explain what this repo does",
options: {
systemPrompt: {
type: "preset",
preset: "claude_code", // restores the Claude Code prompt
append: "Answer in two sentences.", // your own rules go on top
},
settingSources: ["project"], // [] loads no filesystem settings// TypeScript replaces the environment, so spread process.env yourself
env: { ...process.env, ENABLE_PROMPT_CACHING_1H: "1" },
},
})) {
if ("result"in message) console.log(message.result);
}
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.
No automatic approvals. A call that needs approval goes to your callback. With no callback it is denied.
acceptEdits
File edits and filesystem operations such as mkdir, rm and mv are approved automatically inside the working directory and any additional directories.
plan
Claude explores and plans without editing source files. Edits are never auto approved.
dontAsk
Anything that would prompt is denied without calling your callback. Calls approved by allowed_tools or allow rules still run.
auto
A 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.
bypassPermissions
Tools 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.
A permission callback sees each call that is not already approved and answers allow or deny.
The approval gate
import asyncio
from claude_agent_sdk import (
query, ClaudeAgentOptions, PermissionResultAllow, PermissionResultDeny,
ToolPermissionContext,
)
asyncdefgate(tool_name: str, tool_input: dict, context: ToolPermissionContext):
command = tool_input.get("command", "")
if tool_name == "Bash"and"rm "in command:
returnPermissionResultDeny(message="Deletes are not allowed here")
returnPermissionResultAllow()
# Do not also list Bash in allowed_tools: allow rules run before the callback
options = ClaudeAgentOptions(can_use_tool=gate)
asyncdefmain():
asyncfor message inquery(prompt="Clean up the temp files", options=options):
print(message)
asyncio.run(main())
import { query } from"@anthropic-ai/claude-agent-sdk";
forawait (const message ofquery({
prompt: "Clean up the temp files",
options: {
// Do not also list Bash in allowedTools: allow rules run before the callback
canUseTool: async (toolName, input) => {
const command = String(input.command ?? "");
if (toolName === "Bash" && command.includes("rm ")) {
return { behavior: "deny", message: "Deletes are not allowed here" };
}
return { behavior: "allow", updatedInput: input };
},
},
})) {
if ("result"in message) console.log(message.result);
}
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.
Before a tool runs. Can allow, deny, ask, defer or rewrite input.
PostToolUse
After a tool runs. Can add context or replace the tool output.
PostToolUseFailure
When a tool call fails.
UserPromptSubmit
When a prompt is submitted.
Stop
When the agent is about to stop. Ignores matchers.
SubagentStart
When a subagent starts.
SubagentStop
When a subagent stops.
PreCompact
Before the conversation is compacted.
Notification
On notification events.
PermissionRequest
When 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.
Set both limits on every production agent, then read why a run stopped.
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
)
asyncdefmain():
try:
asyncfor message inquery(prompt="Summarize the README", options=options):
ifisinstance(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 resultprint("stopped:", err)
asyncio.run(main())
import { query } from"@anthropic-ai/claude-agent-sdk";
try {
forawait (const message ofquery({
prompt: "Summarize the README",
options: {
allowedTools: ["Read", "Glob", "Grep"],
maxTurns: 8,
maxBudgetUsd: 0.5, // a client side estimate; it can overshoot
},
})) {
if (message.type === "result") {
console.log(message.subtype, message.num_turns, message.total_cost_usd);
}
}
} catch (err) {
// A single call throws after it yields the error result
console.log("stopped:", err);
}
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.
Fastest. $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.
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.
One 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.
Size
Start 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.
Timeouts
No top level session timeout exists. Use max_turns, and AgentDefinitionmaxTurns for a subagent.
State
Transcripts live in ~/.claude/projects and vanish on restart. Mirror them with a SessionStore adapter if you scale down or move hosts.
Network
Outbound HTTPS to api.anthropic.com or your cloud endpoint, plus your MCP servers. The subprocess does not listen on a port.
Isolation
The 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 tenants
Empty setting_sources, CLAUDE_CODE_DISABLE_AUTO_MEMORY=1, a CLAUDE_CONFIG_DIR and a working directory per tenant, and per tenant egress rules.
Observability
Set CLAUDE_CODE_ENABLE_TELEMETRY=1 and OpenTelemetry exporters. Traces need CLAUDE_CODE_ENHANCED_TELEMETRY_BETA=1.
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.
Breaking. Skill names are validated, so wildcards raise ValueError. Use skills="all" or a Skill rule in allowed_tools.Python SDK changelog
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
New smaller entry point, @anthropic-ai/claude-agent-sdk/core, and an alpha prewarm().TypeScript SDK changelog
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
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.