Overview
The Agent SDK gives you the same tools, agent loop, and context management that power Claude Code, programmable in Python and TypeScript; claude -p is the same engine from the command line. Use it to embed an agent in an application you operate. For interactive work use the Claude Code CLI; to write the tool loop yourself against the raw API use the Client SDK; to have Anthropic host the agent use Managed Agents.
Start with query()
Install claude-agent-sdk (Python 3.10 or later) or @anthropic-ai/claude-agent-sdk (Node 18 or later). Both bundle a native Claude Code binary. query() returns an async iterator of messages as Claude plans, calls tools, and finishes.
from claude_agent_sdk import query, ClaudeAgentOptions, ResultMessage
async for message in query(
prompt="Review utils.py for crashes and fix them.",
options=ClaudeAgentOptions(
allowed_tools=["Read", "Edit", "Glob"], # auto-approved
permission_mode="acceptEdits",
),
):
if isinstance(message, ResultMessage):
print(message.subtype)The TypeScript form takes the same options in camelCase (allowedTools, permissionMode). Set ANTHROPIC_API_KEY in the process environment; the SDK does not read .env files. Bedrock, Claude Platform on AWS, Vertex, and Foundry use CLAUDE_CODE_USE_BEDROCK=1 and its siblings. Unless previously approved, Anthropic does not allow third-party products to offer claude.ai login for SDK agents, so use API keys.
Pass tools and permissions explicitly
Give the agent the narrowest tool set: Read, Glob, Grep for analysis; add Edit to modify; add Bash for full automation. Choose the permission mode in code, because the starting mode can differ by version and plan; see claude-code-permissions. For programmatic control use a canUseTool callback or hook callbacks: a PreToolUse callback that returns permissionDecision: "deny" blocks a call and sends the reason to Claude.
Decide what loads from disk
When settingSources is omitted, query() reads user, project, and local settings, CLAUDE.md files, and .claude/ skills, agents, and commands, as the CLI does. Pass settingSources: [] to run only on what you configure in code. Managed policy settings, ~/.claude.json, auto memory, and claude.ai MCP connectors load regardless. For multi-tenant servers, give each tenant its own filesystem, set settingSources: [], and set CLAUDE_CODE_DISABLE_AUTO_MEMORY=1.
Extend the agent through agents (subagents; include Agent in allowedTools), mcpServers, hooks, and skills. Skills must exist as .claude/skills/ files; there is no registration API. See claude-code-subagents, claude-code-mcp, and claude-code-hooks.
Script it with claude -p
claude --bare -p "Summarize README.md" --allowedTools "Read" --output-format json--output-formatistext,json(includesresult, session ID, andtotal_cost_usd, a client-side estimate), orstream-json(add--verbose --include-partial-messagesfor tokens).--json-schema '<schema>'withjsonoutput returns the validated object instructured_output.--bareskips hooks, skills, plugins, MCP servers, auto memory, andCLAUDE.md, so a script behaves the same on every machine; it never reads OAuth or keychain credentials, so setANTHROPIC_API_KEY(or anapiKeyHelper), and it is the recommended mode for scripted calls. Without it,claude -pruns a repository’s project hooks and.mcp.jsonservers even in a folder you never trusted, so use--bareon untrusted pull requests.- Pass
--permission-modeexplicitly (dontAskwith exact--allowedToolsfor locked-down CI). Exit code is 0 on success and nonzero on failure. - Continue with
--continue, or capturesession_idand pass--resume <id>. Piped stdin is capped at 10MB.
For GitHub workflows see github-actions. Harden any unattended agent with the checklist in reliable-agents-in-production.