| name | claude-agent-sdk |
| description | Comprehensive guide for building production-ready agents with the Claude Agent SDK. Use when creating agents, designing tools, implementing subagents, managing sessions, integrating MCP servers, or understanding SDK-native features. Emphasizes documentation-first approach and using only SDK native capabilities. |
| license | MIT |
Claude Agent SDK Builder
Documentation-First Agent Development
🚨 THE CRITICAL PRINCIPLE
USE ONLY THE SDK'S NATIVE CAPABILITIES
❌ NEVER implement custom logic for functionality the SDK already handles
✅ ALWAYS check documentation BEFORE writing any code
✅ Every line of code must be justified by the official documentation
Why this matters:
- 70% of agents fail due to poor design
- Custom implementations of SDK features create technical debt
- The SDK evolves - your custom code becomes obsolete
- SDK features are battle-tested and optimized
Documentation resources:
- Main docs: https://docs.claude.com/en/api/agent-sdk/python
- Engineering guide: https://www.anthropic.com/engineering/building-agents-with-the-claude-agent-sdk
Quick Start Checklist
Before writing ANY code:
- Read relevant SDK documentation sections
- Confirm SDK doesn't provide this feature natively
- Check Tool Design Framework if creating tools
- Review Subagent Patterns if using subagents
- Understand the agent feedback loop: gather context → take action → verify work
The Agent Feedback Loop
Every agent operates in this cycle:
1. GATHER CONTEXT
↓
2. TAKE ACTION
↓
3. VERIFY WORK
↓
(repeat)
Design your agent's capabilities around this loop.
Agent Creation Workflow
Phase 1: Define Requirements
Essential questions:
- What user intention does this agent serve?
- What tools and capabilities does it need?
- Does it need session persistence? Subagents? MCP integration?
- What are security and performance requirements?
Map requirements to SDK features:
# Before coding, identify needed features:
FEATURES_NEEDED = {
"session_management": True, # Resume conversations
"streaming_mode": True, # Responsive UX
"permissions": True, # Control tool access
"mcp_integration": False, # External data sources
"subagents": "evaluate", # Complex workflows
"custom_tools": True, # Domain-specific actions
"cost_tracking": True, # User billing
"task_tracking": True # Multi-step workflows
}
# Read documentation for each True/evaluate feature BEFORE coding
Phase 2: Tool Design
CRITICAL: Read references/tool-design-framework.md for complete tool design guidance.
Quick tool design checklist:
- Tool models clear user intention (not API wrapper)
- Multi-step workflows consolidated in tool
- Parameters are natural language concepts
- Uses SDK's
@Tool.registerdecorator - Returns
ToolResultobjects - Error handling uses
ToolError
SDK-native tool pattern:
from anthropic_sdk import Tool, ToolResult, ToolError
@Tool.register
def intention_based_name(
natural_param: str,
optional_param: str = "sensible_default"
) -> ToolResult:
"""
Clear description of USER INTENTION this serves.
NOT what the API does.
"""
if not natural_param:
raise ToolError(
"Parameter required",
recoverable=True,
suggestion="Provide valid parameter"
)
# Tool consolidates ALL workflow steps
result = complete_workflow(natural_param)
return ToolResult(
content=result,
metadata={"confidence": 0.95},
suggestions=["Try narrowing scope"]
)
Phase 3: Configure Agent
Choose input mode:
from anthropic_sdk import Agent, InputMode
# Streaming for interactive agents (SDK-native)
agent = Agent(
model="claude-sonnet-4-20250514",
input_mode=InputMode.STREAMING,
tools=[tool1, tool2]
)
# Single for batch/deterministic workflows (SDK-native)
agent = Agent(
model="claude-sonnet-4-20250514",
input_mode=InputMode.SINGLE,
tools=[tool1, tool2]
)
Configure system prompt (SDK-native methods):
# Method 1: CLAUDE.md file (recommended)
# Create CLAUDE.md in project root
# SDK automatically loads it
# Method 2: Append instructions
agent = Agent(
model="claude-sonnet-4-20250514",
system_prompt_append="Additional instructions...",
tools=[...]
)
# Method 3: Output style presets
agent = Agent(
model="claude-sonnet-4-20250514",
output_style="concise", # SDK presets
tools=[...]
)
Configure permissions (SDK-native):
from anthropic_sdk import PermissionMode
agent = Agent(
model="claude-sonnet-4-20250514",
tools=[tool1, tool2, tool3],
permission_mode=PermissionMode.ASK, # Ask before tool use
# OR PermissionMode.AUTO # Automatic
# OR PermissionMode.RESTRICTED with allowed_tools
)
Phase 4: Session Management (SDK-Native)
# ❌ NEVER implement custom session storage
# ✅ SDK handles it natively
# Create session
session = agent.create_session(user_id="user_123")
session_id = session.id # Track this ID
# Resume session
session = agent.resume_session(session_id)
# Fork session for branching
new_session = session.fork()
# SDK handles:
# - Session persistence
# - Conversation history
# - Context management
Phase 5: MCP Integration (When Needed)
Use MCP for:
- External data sources
- Third-party API integrations
- Dynamic resource exposure
from anthropic_sdk import MCPServer
agent = Agent(
model="claude-sonnet-4-20250514",
mcp_servers=[
MCPServer(
name="database",
command="uvx",
args=["mcp-server-sqlite", "--db-path", "data.db"]
),
MCPServer(
name="github",
command="npx",
args=["-y", "@modelcontextprotocol/server-github"],
env={"GITHUB_TOKEN": os.getenv("GITHUB_TOKEN")}
)
]
)
# SDK manages server lifecycle, auth, tool registration
Phase 6: Subagent Architecture (When Needed)
IMPORTANT: Read references/subagent-patterns.md for complete patterns.
Use subagents for:
- Specialized agents for different domains
- Parallel processing of independent tasks
- Context isolation (sift through large data)
- Restricted tool access by task type
from anthropic_sdk import Subagent
main_agent = Agent(
model="claude-sonnet-4-20250514",
tools=[coordination_tool]
)
# SDK-native subagent
research_subagent = Subagent(
name="researcher",
model="claude-sonnet-4-20250514",
tools=[web_search, document_fetch],
system_prompt="Research specialist instructions...",
parent_agent=main_agent
)
# SDK handles orchestration, context isolation, result aggregation
Phase 7: Built-in Features (SDK-Native)
Slash commands:
# Built-in commands:
# /clear - Clear conversation history
# /compact - Compress context
# /session - Session management
# /usage - Token usage
# Custom commands
from anthropic_sdk import SlashCommand
@SlashCommand.register("summarize")
def summarize_conversation(agent: Agent, session: Session):
return agent.summarize(session)
Cost tracking:
result = agent.run("User message")
# SDK provides accurate metrics
print(f"Tokens: {result.usage.total_tokens}")
print(f"Cost: ${result.usage.estimated_cost}")
# Per-step metrics
for step in result.steps:
print(f"{step.type}: {step.usage.total_tokens} tokens")
Task tracking:
agent = Agent(
model="claude-sonnet-4-20250514",
enable_todos=True, # SDK-native
tools=[...]
)
result = agent.run("Plan and execute market analysis")
# SDK tracks tasks automatically
for task in result.todos:
print(f"{task.description}: {task.status} ({task.progress}%)")
Context Gathering Strategies
Agentic search (recommended):
- Use file system and bash for context gathering
- Claude uses grep, tail, etc. to load context intelligently
- More accurate and transparent than semantic search
Semantic search (when needed):
- Faster but less accurate
- Use only if agentic search is too slow
- Start with agentic, add semantic if necessary
Subagents for context:
- Spin up subagents to sift through large data
- Return only relevant excerpts to orchestrator
- Keeps main agent's context lean
Context compaction (SDK-native):
agent = Agent(
model="claude-sonnet-4-20250514",
auto_compact=True, # SDK automatically summarizes old messages
tools=[...]
)
Action Strategies
Tools (primary actions):
- Tools are prominent in context window
- Design as primary actions agent should take
- See references/tool-design-framework.md
Bash & scripts:
- General-purpose flexibility
- Let agent write and execute code
- Useful for data processing, API calls
Code generation:
- Precise, composable, reusable
- Consider: which tasks benefit from code?
- Example: Excel/PowerPoint generation via Python
MCPs:
- Standardized external integrations
- Handles auth and API calls automatically
- Growing ecosystem of pre-built servers
Work Verification Strategies
1. Define rules:
@Tool.register
def send_email(to: str, body: str) -> ToolResult:
# Rule-based validation
if not is_valid_email(to):
raise ToolError("Invalid email address")
if not has_sent_to_before(to):
return ToolResult(
content="Email sent",
metadata={"warning": "First contact with this address"}
)
2. Visual feedback:
- Screenshot rendered output
- Use Playwright MCP for automation
- Agent verifies visual correctness
3. LLM as judge:
- Another model evaluates output
- Heavy latency cost
- Use only when performance boost justifies cost
Common Anti-Patterns
❌ Custom session storage:
# WRONG
def save_session(data):
with open(f"session_{id}.json", "w") as f:
json.dump(data, f)
# CORRECT
session = agent.create_session(user_id="user_123")
❌ Manual streaming:
# WRONG
def custom_stream(prompt):
for chunk in api.stream(prompt):
yield chunk
# CORRECT
agent = Agent(input_mode=InputMode.STREAMING)
❌ Custom permissions:
# WRONG
if check_user_permission(user_id, tool_name):
result = agent.run(message)
# CORRECT
agent = Agent(
permission_mode=PermissionMode.RESTRICTED,
allowed_tools=get_user_tools(user_id)
)
❌ Custom token counting:
# WRONG
tokens = count_tokens_manually(text)
# CORRECT
result = agent.run(message)
tokens = result.usage.total_tokens
SDK Feature Decision Tree
User Need?
├─ Session management? → create_session/resume_session
├─ Streaming? → InputMode.STREAMING
├─ Permissions? → PermissionMode + allowed_tools
├─ System prompt? → CLAUDE.md or system_prompt_append
├─ Cost tracking? → result.usage
├─ Task tracking? → enable_todos=True
├─ External APIs? → MCP servers
├─ Multi-agent? → Subagent feature
├─ Custom commands? → SlashCommand.register
├─ Tool creation? → Tool.register with ToolResult
└─ Something else? → Re-read docs, likely SDK handles it
Pre-Production Checklist
SDK usage:
- All features use SDK-native implementations
- No custom code duplicating SDK functionality
- Latest SDK version installed
Tool design:
- Tools reviewed against Tool Design Framework
- Clear user intentions modeled
- SDK's Tool.register and ToolResult used
Documentation:
- All SDK features confirmed in official docs
- No assumptions about capabilities
Performance & security:
- Permission modes configured
- Cost tracking enabled
- Session management defined
- Error handling comprehensive
Examples
Customer support agent:
from anthropic_sdk import Agent, Tool, ToolResult, PermissionMode, InputMode
@Tool.register
def search_knowledge_base(query: str, category: str = None) -> ToolResult:
results = kb_search(query, category)
return ToolResult(
content=results,
metadata={"source": "kb", "confidence": 0.85}
)
@Tool.register
def create_support_ticket(issue: str, priority: str = "medium") -> ToolResult:
ticket = ticket_system.create(issue, priority)
return ToolResult(
content=f"Ticket #{ticket.id} created",
metadata={"ticket_id": ticket.id}
)
agent = Agent(
model="claude-sonnet-4-20250514",
input_mode=InputMode.STREAMING,
permission_mode=PermissionMode.AUTO,
tools=[search_knowledge_base, create_support_ticket],
enable_todos=True,
output_style="helpful"
)
def handle_chat(customer_id: str, message: str):
session = agent.resume_session(f"customer_{customer_id}") or \
agent.create_session(user_id=f"customer_{customer_id}")
for chunk in agent.stream(message, session=session):
yield chunk
Additional Resources
- Tool Design Framework: references/tool-design-framework.md
- Subagent Patterns: references/subagent-patterns.md
- SDK Capabilities: references/sdk-capabilities.md
- Agent Initialization Script: scripts/init_agent.py
- Tool Validation Script: scripts/validate_tool.py
Key Reminders
- Documentation first: Read SDK docs before coding
- SDK-native: Use built-in features, don't reinvent
- Tool design: Follow framework for effective tools
- Test thoroughly: Use real scenarios to validate
- Iterate: Improve based on actual usage
The SDK is your friend. Use it fully, trust it completely, read the documentation religiously.