Claude Code Agent SDK: The Complete Beginner's Guide to Building AI Agents (2026)
Update (October 2, 2026): The model names and pricing in this guide reflect the January 2026 state. Anthropic has moved on since then: Claude Sonnet 4.5 had already shipped in September 2025 at unchanged pricing ($3/$15 per million tokens vs Sonnet 4) (Anthropic), and by autumn 2026 Claude Sonnet 4.6 and Opus 4.6 (Opus: $5/$25 per million tokens) are the current generation in the Agent SDK and Claude Code (models overview, plans and models). Before the code samples, check the current model aliases in the docs or with the
/modelcommand in Claude Code.
Want to build your first AI agent but don't know where to start?
The Claude Code Agent SDK from Anthropic makes it possible – even without deep programming knowledge. In this comprehensive guide, we'll show you step by step how to create autonomous AI agents that can independently complete complex tasks.
What You'll Learn in This Guide
- What AI agents are and how they differ from chatbots
- How the Claude Code Agent SDK works
- Practical code examples for your first agent
- Tools, subagents, and MCP integration
- Best practices for production-ready agents
What is an AI Agent? (And Why is it Different from ChatGPT?)
Before we dive into the code, let's clarify a fundamental concept: What distinguishes an AI agent from an ordinary chatbot?
Chatbot vs. Agent
| Feature | Chatbot (e.g., ChatGPT) | AI Agent |
|---|---|---|
| Interaction | Question → Answer | Goal → Autonomous Execution |
| Execution | Single request | Loop until goal achieved |
| Tools | Limited | Infinitely extensible |
| Autonomy | None | Independent decisions |
A chatbot answers your questions. An AI agent works independently toward a goal, using various tools and making its own decisions.
The Agent Loop
Every AI agent follows a fundamental pattern – the so-called Agent Loop:
┌─────────────────────────────────────────────────────────────┐
│ AGENT LOOP PATTERN │
├─────────────────────────────────────────────────────────────┤
│ 1. GATHER CONTEXT │
│ └─▶ Understand the task, read relevant data │
│ │
│ 2. EXECUTE ACTION │
│ └─▶ Use tools, perform operations │
│ │
│ 3. CHECK RESULT │
│ └─▶ Was the action successful? │
│ │
│ 4. REPEAT │
│ └─▶ Until the goal is achieved │
└─────────────────────────────────────────────────────────────┘
Example: You ask an agent to plan a trip. The agent:
- Gathers context: Asks about date, budget, preferences
- Executes actions: Searches for flights, hotels, activities
- Checks: Does everything fit the budget? Are the times compatible?
- Repeats: Until a complete travel plan is ready
What is the Claude Code Agent SDK?
The Claude Code Agent SDK is the same framework that Anthropic uses internally for Claude Code – their powerful coding assistant.
It provides everything you need to create production-ready AI agents:
Core SDK Features
| Feature | Description |
|---|---|
| Automatic Context Compression | Intelligently manages large context windows |
| Tool Ecosystem | File operations, code execution, web search |
| Permission Control | Granular control over agent actions |
| MCP Extensibility | Integration of external services via Model Context Protocol |
| Subagents | Delegation to specialized sub-agents |
| Hooks System | Event-based workflows |
Why Choose Claude Code Agent SDK?
- Production-proven: The same system that powers Claude Code
- Minimal Boilerplate: Less code, more functionality
- Built-in Tools: File operations, Bash, Web out-of-the-box
- MCP-native: Seamless integration with Model Context Protocol
Quick Start: Installation and Setup
Prerequisites
- Python 3.10 or higher
- Anthropic API key (from console.anthropic.com)
Step 1: Install the SDK
# Install with pip
pip install claude-agent-sdk
# Or with uv (recommended for faster installation)
uv pip install claude-agent-sdk
Step 2: Configure API Key
# Set as environment variable
export ANTHROPIC_API_KEY="sk-ant-..."
# Or in a .env file
echo "ANTHROPIC_API_KEY=sk-ant-..." > .env
Step 3: Test the Connection
from claude_agent_sdk import ClaudeSDKClient, ClaudeAgentOptions
async def test_connection():
options = ClaudeAgentOptions(
model="sonnet", # Claude Sonnet 4
system_prompt="You are a helpful assistant."
)
async with ClaudeSDKClient(options=options) as client:
await client.query("Say Hello!")
async for message in client.receive_response():
print(message)
# Run
import asyncio
asyncio.run(test_connection())
Practical Example 1: Simple Q&A Agent
Let's start with the simplest agent – one that answers questions:
from claude_agent_sdk import ClaudeSDKClient, ClaudeAgentOptions
from claude_agent_sdk.types import TextBlock
import asyncio
SYSTEM_PROMPT = """You are a friendly assistant who answers questions.
Be precise and helpful."""
async def simple_qa_agent():
options = ClaudeAgentOptions(
model="sonnet",
system_prompt=SYSTEM_PROMPT,
permission_mode="acceptEdits" # Allows read operations
)
async with ClaudeSDKClient(options=options) as client:
print("🤖 Q&A Agent ready! (Type 'exit' to quit)\n")
while True:
user_input = input("You: ").strip()
if user_input.lower() in ['exit', 'quit']:
print("Goodbye!")
break
await client.query(user_input)
print("Agent: ", end="")
async for message in client.receive_response():
if hasattr(message, 'content'):
for block in message.content:
if isinstance(block, TextBlock):
print(block.text, end="")
print("\n")
if __name__ == "__main__":
asyncio.run(simple_qa_agent())
What this code does:
- Creates a client with a system prompt
- Starts an interactive loop
- Sends user input to Claude
- Streams the response back
Practical Example 2: Agent with Memory
An agent with conversation memory can remember previous messages:
from claude_agent_sdk import ClaudeSDKClient, ClaudeAgentOptions
from claude_agent_sdk.types import TextBlock
import asyncio
SYSTEM_PROMPT = """You are an assistant with memory.
You remember everything said in this conversation.
Refer to earlier statements when relevant."""
async def memory_agent():
options = ClaudeAgentOptions(
model="sonnet",
system_prompt=SYSTEM_PROMPT,
permission_mode="acceptEdits",
# The SDK manages conversation history automatically!
)
async with ClaudeSDKClient(options=options) as client:
print("🧠 Memory Agent ready!\n")
print("Tip: Ask questions that refer to earlier answers.\n")
while True:
user_input = input("You: ").strip()
if not user_input:
continue
if user_input.lower() == 'exit':
break
await client.query(user_input)
print("Agent: ", end="")
async for message in client.receive_response():
if hasattr(message, 'content'):
for block in message.content:
if isinstance(block, TextBlock):
print(block.text, end="", flush=True)
print("\n")
if __name__ == "__main__":
asyncio.run(memory_agent())
Test the memory:
You: My name is Max.
Agent: Hello Max! Nice to meet you.
You: What is my name?
Agent: Your name is Max – you just introduced yourself!
Practical Example 3: Agent with Tools
This is where it gets interesting! Agents with tools can perform real actions:
from claude_agent_sdk import ClaudeSDKClient, ClaudeAgentOptions
from claude_agent_sdk.types import TextBlock, ToolUseBlock
import asyncio
SYSTEM_PROMPT = """You are a research assistant with access to tools.
Use the available tools to complete tasks:
- WebFetch: Retrieves web page content
- Read: Reads local files
- Grep: Searches files for patterns
- Glob: Finds files by patterns
Always explain which tool you're using and why."""
async def tool_agent():
options = ClaudeAgentOptions(
model="sonnet",
system_prompt=SYSTEM_PROMPT,
permission_mode="acceptEdits",
allowed_tools=[
"WebFetch", # Fetch web content
"Read", # Read files
"Grep", # Search text
"Glob", # Find files
]
)
async with ClaudeSDKClient(options=options) as client:
print("🔧 Tool Agent ready!")
print("Commands: 'research [URL]', 'find [file]', etc.\n")
while True:
user_input = input("You: ").strip()
if user_input.lower() == 'exit':
break
await client.query(user_input)
async for message in client.receive_response():
if hasattr(message, 'content'):
for block in message.content:
if isinstance(block, TextBlock):
print(f"Agent: {block.text}")
elif isinstance(block, ToolUseBlock):
print(f"🛠️ Using Tool: {block.name}")
print(f" Parameters: {block.input}")
print()
if __name__ == "__main__":
asyncio.run(tool_agent())
Available Built-in Tools
| Tool | Function | Example |
|---|---|---|
Read | Read files | Read("config.json") |
Write | Write files | Write("output.txt", content) |
Edit | Edit files | Edit(file, old, new) |
Glob | Search files | Glob("**/*.py") |
Grep | Search text | Grep("TODO", "src/") |
Bash | Execute commands | Bash("npm install") |
WebFetch | Fetch web content | WebFetch(url, prompt) |
Practical Example 4: Autonomous Travel Planner Agent
Now let's build a fully autonomous agent:
from claude_agent_sdk import ClaudeSDKClient, ClaudeAgentOptions
from claude_agent_sdk.types import TextBlock, ToolUseBlock, ToolResultBlock
import asyncio
import json
TRAVEL_SYSTEM_PROMPT = """You are an autonomous travel planning agent.
YOUR GOAL: Create a complete travel plan based on user requirements.
YOUR WORKFLOW:
1. Gather all necessary information (date, budget, preferences)
2. Research options with WebFetch
3. Create a structured travel plan
4. Present the plan and ask for feedback
IMPORTANT:
- Ask FIRST about missing information
- Use WebFetch for current information
- Create a clear, structured plan
- Offer alternatives
ALWAYS begin with a friendly greeting and ask about the destination."""
async def travel_planner_agent():
options = ClaudeAgentOptions(
model="sonnet",
system_prompt=TRAVEL_SYSTEM_PROMPT,
permission_mode="acceptEdits",
allowed_tools=["WebFetch", "Read", "Write"],
max_turns=20 # Allows longer agent loops
)
async with ClaudeSDKClient(options=options) as client:
print("✈️ Travel Planner Agent started!")
print("=" * 50)
# Initial greeting from the agent
await client.query("Start travel planning for a new customer.")
async for message in client.receive_response():
if hasattr(message, 'content'):
for block in message.content:
if isinstance(block, TextBlock):
print(f"Agent: {block.text}")
print()
# Interactive loop
while True:
user_input = input("You: ").strip()
if user_input.lower() in ['exit', 'done', 'thanks']:
print("Agent: You're welcome! I wish you a wonderful trip! 🌍✨")
break
await client.query(user_input)
async for message in client.receive_response():
if hasattr(message, 'content'):
for block in message.content:
if isinstance(block, TextBlock):
print(f"Agent: {block.text}")
elif isinstance(block, ToolUseBlock):
print(f"🔍 Researching: {block.name}...")
print()
if __name__ == "__main__":
asyncio.run(travel_planner_agent())
Advanced Features: MCP Integration
The Model Context Protocol (MCP) enables integration of external services:
Integrating MCP Servers
from claude_agent_sdk import ClaudeSDKClient, ClaudeAgentOptions
# MCP server configuration
MCP_CONFIG = {
"utils": {
"command": "npx",
"args": ["-y", "mcp-remote", "https://your-mcp-server.com/api"]
}
}
async def mcp_agent():
options = ClaudeAgentOptions(
model="sonnet",
system_prompt="You have access to MCP tools for extended functionality.",
permission_mode="acceptEdits",
allowed_tools=[
"WebFetch",
"mcp__utils__save_note", # MCP tools are prefixed
"mcp__utils__find_note",
],
mcp_servers=MCP_CONFIG
)
async with ClaudeSDKClient(options=options) as client:
await client.query("Create a note with the title 'Important'")
# ...
Creating Your Own MCP Server
# mcp_server.py - Simple MCP server
from mcp import Server
server = Server("my-tools")
@server.tool(name="save_note")
async def save_note(title: str, content: str) -> dict:
"""Saves a note."""
# Your logic here
return {"status": "success", "id": "note_123"}
@server.tool(name="find_note")
async def find_note(pattern: str) -> dict:
"""Finds notes by pattern."""
# Your logic here
return {"notes": [...]}
if __name__ == "__main__":
import asyncio
asyncio.run(server.run())
Subagents: Specialized Sub-Agents
For complex tasks, you can deploy subagents – specialized agents that handle subtasks:
from claude_agent_sdk import ClaudeSDKClient, ClaudeAgentOptions
ORCHESTRATOR_PROMPT = """You are a coordinator who delegates tasks to
specialized subagents:
- Research Agent: For information search
- Writing Agent: For content creation
- Analysis Agent: For data analysis
Delegate tasks according to their type."""
async def orchestrator_agent():
options = ClaudeAgentOptions(
model="sonnet",
system_prompt=ORCHESTRATOR_PROMPT,
permission_mode="acceptEdits",
allowed_tools=["SubAgent", "Read", "Write"],
subagents_enabled=True # Enables subagents
)
async with ClaudeSDKClient(options=options) as client:
await client.query(
"Research the latest AI trends and create a report."
)
# The agent automatically delegates to subagents
When to Use Subagents?
| Situation | Recommendation |
|---|---|
| Simple, linear tasks | ❌ No subagent needed |
| Parallel, independent tasks | ✅ Use subagents |
| Specialized expertise required | ✅ Use subagents |
| Long, complex workflows | ✅ Use subagents |
Hooks: Event-Based Workflows
Hooks enable automated actions on certain events:
from claude_agent_sdk import ClaudeSDKClient, ClaudeAgentOptions, HookMatcher
# Define hook function
async def log_tool_usage(event):
"""Logs every tool usage."""
print(f"📝 Log: Tool '{event.tool_name}' was called")
return True # Allows execution
async def block_dangerous_commands(event):
"""Blocks dangerous bash commands."""
dangerous = ['rm -rf', 'sudo', 'chmod 777']
if any(cmd in str(event.arguments) for cmd in dangerous):
print("⚠️ Dangerous command blocked!")
return False # Blocks execution
return True
async def hook_agent():
options = ClaudeAgentOptions(
model="sonnet",
system_prompt="You are an assistant with security hooks.",
permission_mode="acceptAll",
allowed_tools=["Bash", "Write", "Read"],
hooks={
"PreToolUse": [
HookMatcher(hooks=[log_tool_usage]),
HookMatcher(
tool_name="Bash",
hooks=[block_dangerous_commands]
)
]
}
)
async with ClaudeSDKClient(options=options) as client:
# ...
Hook Types
| Hook | When Triggered | Application |
|---|---|---|
PreToolUse | Before tool execution | Validation, logging |
PostToolUse | After tool execution | Post-processing, alerts |
Notification | On important events | Notifications |
Stop | At session end | Cleanup, reporting |
Best Practices for Production-Ready Agents
1. Clear System Prompts
# ❌ Bad: Vague instructions
SYSTEM_PROMPT = "Be helpful."
# ✅ Good: Clear role, boundaries, and behavior
SYSTEM_PROMPT = """You are a customer service agent for TechCorp.
YOUR ROLE:
- Answer questions about our products
- Forward complex requests to humans
- Document all interactions
BOUNDARIES:
- No price negotiations
- No technical changes without approval
- When uncertain: Ask
BEHAVIOR:
- Friendly and professional
- Answer in the customer's language
- Summarize complex topics"""
2. Set Granular Permissions
# ❌ Bad: Allow everything
permission_mode = "acceptAll"
# ✅ Good: Only allow necessary tools
permission_mode = "acceptEdits"
allowed_tools = ["Read", "WebFetch"] # Only what's really needed
3. Implement Error Handling
async def resilient_agent():
max_retries = 3
for attempt in range(max_retries):
try:
async with ClaudeSDKClient(options=options) as client:
await client.query(prompt)
async for message in client.receive_response():
# Processing
pass
break # Successful, exit loop
except RateLimitError:
wait_time = 2 ** attempt # Exponential backoff
print(f"Rate limit reached. Waiting {wait_time}s...")
await asyncio.sleep(wait_time)
except Exception as e:
print(f"Error: {e}")
if attempt == max_retries - 1:
raise
4. Context Management
# For long conversations: Compress context
options = ClaudeAgentOptions(
model="sonnet",
system_prompt=SYSTEM_PROMPT,
# SDK automatically compresses when needed
max_context_tokens=100000, # Maximum context size
)
Cost and Model Selection
Available Models
| Model | Alias | Strengths | Cost |
|---|---|---|---|
| Claude Opus 4.5 | opus | Highest quality, complex tasks | $$$ |
| Claude Sonnet 4 | sonnet | Best quality/cost balance | $$ |
| Claude Haiku | haiku | Fast, affordable | $ |
Model Recommendations by Application
| Application | Recommended Model |
|---|---|
| Simple Q&A | Haiku |
| General Agents | Sonnet |
| Code Generation | Sonnet |
| Complex Analysis | Opus |
| Research Agents | Opus |
Summary: Your Path to Your First Agent
Checklist for Getting Started
- Python 3.10+ installed
- Anthropic API key created
-
claude-agent-sdkinstalled - Simple Q&A agent tested
- Agent with memory tried
- Tools added
- Autonomous agent built
Next Steps
- Experiment: Start with the simple Q&A agent
- Extend: Add tools as needed
- Specialize: Create domain-specific agents
- Scale: Use subagents for complex workflows
- Secure: Implement hooks for production environments
Frequently Asked Questions (FAQ)
What's the difference between Claude Code and the Claude Agent SDK?
Claude Code is Anthropic's complete coding assistant – a finished product you can use in your terminal.
The Claude Agent SDK is the underlying framework you can use to build your own agents for any use case. The SDK gives you the building blocks that also power Claude Code.
Do I need programming skills for the SDK?
Basic Python knowledge is helpful but not strictly required. You can follow the simple examples in this guide even without deep programming experience.
For production-ready agents, however, we recommend solid Python fundamentals.
How much does using the Claude Agent SDK cost?
The SDK itself is free. You only pay for API calls to Claude.
Sonnet costs about $3 per million input tokens and $15 per million output tokens (as of January 2026). For development and testing, we recommend starting with small contexts.
Can I use the SDK with other AI models?
The Claude Agent SDK is specifically optimized for Claude models. For other models like GPT-4 or Gemini, there are alternative SDKs like OpenAI Agents SDK or Google ADK.
However, the concepts (Agent Loop, Tools, Memory) are transferable.
How do I secure my agent for production use?
Three important steps:
- Set
permission_modeto "manual" or "acceptEdits" instead of "acceptAll" - Explicitly define
allowed_toolswith only the tools you really need - Implement hooks for security checks and logging
For critical applications, add human-in-the-loop approvals.
Further Resources
- Official Documentation: docs.claude.com/en/api/agent-sdk
- Anthropic Engineering Blog: anthropic.com/engineering
- MCP Specification: modelcontextprotocol.io
- Claude Code: anthropic.com/claude-code
Note: This guide was created for developers and AI enthusiasts who want to take their first steps with AI agents. The Claude Code Agent SDK is constantly evolving – visit the official documentation for the latest updates.
Sources
- console.anthropic.com
- docs.claude.com/en/api/agent-sdk
- anthropic.com/engineering
- modelcontextprotocol.io
- anthropic.com/claude-code
Updated sources (October 2, 2026)
- https://www.anthropic.com/news/claude-sonnet-4-5
- https://platform.claude.com/docs/en/models/overview
- https://www.morphllm.com/claude-code-models
Bring AI agents into your company
We design, build and operate AI agents for real business processes, from the first use case to production with monitoring, permissions and cost control. We run agents like OpenClaw and Hermes ourselves every day.
Start with a workshop, then scoping and a fixed-price offer.