Build autonomous AI agents in Python using the Claude Agent SDK. Covers the GTVR execution pattern (gather, take action, verify, repeat), stateless query() and stateful ClaudeSDKClient APIs, streaming versus batch modes, custom tool creation with @tool decorator, MCP server integration, hook-based execution control, permission boundaries, API key and OAuth token management, multi-agent coordination, and production deployment strategies. Suited for programmatic agents, tool chains, and multi-agent systems. Not designed for basic chat interfaces.
Builds autonomous AI agents in Python using the Claude Agent SDK with custom tools and execution hooks.
npx claudepluginhub aeyeops/aeo-skill-marketplaceThis skill inherits all available tools. When active, it can use any tool Claude has access to.
examples/basic_query.pyexamples/custom_tools.pyexamples/extended_thinking.pyexamples/stateful_client.pyexamples/streaming_events.pyreferences/architecture-patterns.mdreferences/authentication.mdreferences/python-sdk.mdreferences/streaming.mdreferences/tools-mcp.mdBuild production-ready AI agents using Anthropic's Claude Agent SDK.
from claude_agent_sdk import query, ClaudeAgentOptions
import asyncio
async def main():
options = ClaudeAgentOptions(
allowed_tools=["Read", "Write", "Bash"],
permission_mode="acceptEdits"
)
async for message in query(prompt="Create hello.py", options=options):
print(message)
asyncio.run(main())
All Claude agents follow this pattern:
For detailed patterns: See architecture-patterns.md
| Pattern | Use Case | State |
|---|---|---|
query() | One-shot tasks, serverless | Stateless |
ClaudeSDKClient | Multi-turn conversations | Stateful |
from claude_agent_sdk import query, ClaudeAgentOptions, ResultMessage
async for message in query(
prompt="Analyze this codebase",
options=ClaudeAgentOptions(
allowed_tools=["Read", "Grep"],
max_turns=5
)
):
if isinstance(message, ResultMessage):
print(f"Cost: ${message.total_cost_usd:.4f}")
from claude_agent_sdk import ClaudeSDKClient
async with ClaudeSDKClient() as client:
await client.query("What's in this repo?")
async for msg in client.receive_response():
print(msg)
# Follow-up with preserved context
await client.query("Show me the main entry point")
async for msg in client.receive_response():
print(msg)
For complete API reference: See python-sdk.md
| Aspect | Streaming | Single |
|---|---|---|
| Use Case | Interactive sessions | Serverless, one-shot |
| Feedback | Real-time | Final only |
| Interruption | Supported | Not available |
| Hooks | Full support | Not available |
For patterns and examples: See streaming.md
from claude_agent_sdk import tool, create_sdk_mcp_server, ClaudeAgentOptions
from typing import Any
@tool("greet", "Greet a user", {"name": str})
async def greet(args: dict[str, Any]) -> dict[str, Any]:
return {
"content": [{"type": "text", "text": f"Hello, {args['name']}!"}]
}
server = create_sdk_mcp_server(name="tools", tools=[greet])
options = ClaudeAgentOptions(
mcp_servers={"tools": server},
allowed_tools=["mcp__tools__greet"]
)
For tool design and MCP integration: See tools-mcp.md
Intercept tool execution for validation, logging, or blocking:
from claude_agent_sdk import ClaudeAgentOptions, HookMatcher, HookContext
from typing import Any
async def validate_bash(
input_data: dict[str, Any],
tool_use_id: str | None,
context: HookContext
) -> dict[str, Any]:
command = input_data.get("tool_input", {}).get("command", "")
if "rm -rf" in command:
return {
"hookSpecificOutput": {
"hookEventName": "PreToolUse",
"permissionDecision": "deny",
"permissionDecisionReason": "Dangerous command blocked"
}
}
return {}
options = ClaudeAgentOptions(
hooks={"PreToolUse": [HookMatcher(matcher="Bash", hooks=[validate_bash])]}
)
Hook events: PreToolUse, PostToolUse, UserPromptSubmit, Stop, SubagentStop, PreCompact
| Mode | Behavior |
|---|---|
default | Prompt for each action |
acceptEdits | Auto-approve file edits |
bypassPermissions | Fully autonomous |
Two authentication methods are supported:
| Method | Billing | Use Case |
|---|---|---|
| API Key | Per-token | Serverless, CI/CD, production |
| Subscription | Flat rate | Development, interactive sessions |
options = ClaudeAgentOptions(
env={"ANTHROPIC_API_KEY": "sk-ant-api..."},
)
First authenticate via CLI: claude setup-token
Then force OAuth by clearing any inherited API key:
options = ClaudeAgentOptions(
env={"ANTHROPIC_API_KEY": ""}, # Empty string forces OAuth
)
The SDK spawns a persistent Claude CLI subprocess that:
~/.claude/.credentials.json once at startupFor complete auth patterns and token lifecycle: See authentication.md
Key configuration fields:
ClaudeAgentOptions(
allowed_tools=["Read", "Write", "Bash"],
permission_mode="acceptEdits",
system_prompt="You are a coding assistant.",
max_turns=10,
max_budget_usd=5.0,
cwd="/path/to/project",
mcp_servers={"tools": server},
hooks={"PreToolUse": [...]},
setting_sources=["project"] # Load CLAUDE.md
)
| Tool | Purpose |
|---|---|
Read | Read file contents |
Write | Write file contents |
Edit | Edit existing files |
Bash | Execute shell commands |
Glob | Find files by pattern |
Grep | Search file contents |
WebSearch | Search the web |
WebFetch | Fetch URL content |
Task | Spawn subagents |
from claude_agent_sdk import (
AssistantMessage, # Claude's response
UserMessage, # User input
SystemMessage, # System events
ResultMessage, # Completion with cost
TextBlock, # Text content
ToolUseBlock, # Tool invocation
ToolResultBlock # Tool output
)
from claude_agent_sdk import (
ClaudeSDKError, # Base exception
CLINotFoundError, # SDK not installed
ProcessError, # Process failure
CLIJSONDecodeError # Parse error
)
max_turns and max_budget_usd limitspermission_mode="acceptEdits" for developmentFor deployment checklist: See architecture-patterns.md
Complete, runnable scripts demonstrating SDK patterns:
| Example | Purpose | Key Patterns |
|---|---|---|
| basic_query.py | Simplest working agent | query(), message handling, error handling |
| custom_tools.py | Custom MCP tools | @tool decorator, create_sdk_mcp_server |
| stateful_client.py | Production patterns | ClaudeSDKClient, hooks, multi-turn |
| extended_thinking.py | Extended thinking | ThinkingBlock, max_thinking_tokens |
| streaming_events.py | Real-time streaming | StreamEvent, include_partial_messages |
All examples require claude-agent-sdk>=0.1.20 and the Claude Code CLI.
mcp__context7__get-library-docs with /anthropics/claude-agent-sdk-pythonrag_search_knowledge_base(query="Claude Agent SDK")Use for:
Not for:
Activates when the user asks about AI prompts, needs prompt templates, wants to search for prompts, or mentions prompts.chat. Use for discovering, retrieving, and improving prompts.
Search, retrieve, and install Agent Skills from the prompts.chat registry using MCP tools. Use when the user asks to find skills, browse skill catalogs, install a skill for Claude, or extend Claude's capabilities with reusable AI agent components.
Creating algorithmic art using p5.js with seeded randomness and interactive parameter exploration. Use this when users request creating art using code, generative art, algorithmic art, flow fields, or particle systems. Create original algorithmic art rather than copying existing artists' work to avoid copyright violations.