Claude Agent SDK gives you Claude Code's agent loop, built-in tools, permissions, sessions and hooks as a library — in Python (claude-agent-sdk) and TypeScript (@anthropic-ai/claude-agent-sdk). If you want the same loop from another language, run the claude -p ... --output-format json subprocess.
19.1 Difference between Claude's 4 tools
You need
Use
A Claude Code-like agent in your own Python/TS app, in your own process
Agent SDK
Interactive development in the terminal
Claude Code CLI
Direct Claude API calls, with your own loop or Tool Runner
Client SDK (anthropic)
Anthropic hosts the agent (cloud sandbox)
Managed Agents
19.2 ClaudeAgentOptions — main fields
Field
What it does
allowed_tools / disallowed_tools
Which tools run without asking / never run
permission_mode
default, acceptEdits, plan, dontAsk, bypassPermissions, auto
can_use_tool
Permission callback — when it is time to prompt
system_prompt
Custom or the Claude Code preset
mcp_servers
External or in-process MCP servers
hooks
Callbacks on lifecycle events
agents
Programmatic subagents (AgentDefinition)
model, max_turns, max_budget_usd
Model and limits (stop at the budget)
cwd, setting_sources
Working dir; whether to load .claude/ settings, CLAUDE.md, skills
Only in the TypeScript SDK (in Python via settings-file hooks)
19.5 Multi-turn client and subagents
import asyncio
from claude_agent_sdk import (ClaudeSDKClient, ClaudeAgentOptions, AgentDefinition,
AssistantMessage, TextBlock)
options = ClaudeAgentOptions(
allowed_tools=["Read", "Grep", "Glob"],
agents={
"code-reviewer": AgentDefinition(
description="Reviews code changes",
prompt="You are a code reviewer. Report issues in the diff.",
),
},
)
async def main():
async with ClaudeSDKClient(options=options) as client:
await client.query("Explain the auth flow in the src/ folder")
async for msg in client.receive_response():
if isinstance(msg, AssistantMessage):
for b in msg.content:
if isinstance(b, TextBlock): print(b.text)
await client.query("Now have the code-reviewer review it") # the context is remembered
async for msg in client.receive_response():
print(msg)
asyncio.run(main())