Claude Code

Claude Code Agent SDK: The Complete Beginner's Guide to Building AI Agents (2026)

Claude Code Agent SDK: The Complete Beginner's Guide to Building AI Agents (2026)

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 /model command 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

FeatureChatbot (e.g., ChatGPT)AI Agent
InteractionQuestion → AnswerGoal → Autonomous Execution
ExecutionSingle requestLoop until goal achieved
ToolsLimitedInfinitely extensible
AutonomyNoneIndependent 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:

text
┌─────────────────────────────────────────────────────────────┐
│                    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:

  1. Gathers context: Asks about date, budget, preferences
  2. Executes actions: Searches for flights, hotels, activities
  3. Checks: Does everything fit the budget? Are the times compatible?
  4. 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

FeatureDescription
Automatic Context CompressionIntelligently manages large context windows
Tool EcosystemFile operations, code execution, web search
Permission ControlGranular control over agent actions
MCP ExtensibilityIntegration of external services via Model Context Protocol
SubagentsDelegation to specialized sub-agents
Hooks SystemEvent-based workflows

Why Choose Claude Code Agent SDK?

  1. Production-proven: The same system that powers Claude Code
  2. Minimal Boilerplate: Less code, more functionality
  3. Built-in Tools: File operations, Bash, Web out-of-the-box
  4. MCP-native: Seamless integration with Model Context Protocol

Quick Start: Installation and Setup

Prerequisites

Step 1: Install the SDK

bash
# 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

bash
# 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

python
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:

python
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:

  1. Creates a client with a system prompt
  2. Starts an interactive loop
  3. Sends user input to Claude
  4. Streams the response back

Practical Example 2: Agent with Memory

An agent with conversation memory can remember previous messages:

python
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:

text
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:

python
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

ToolFunctionExample
ReadRead filesRead("config.json")
WriteWrite filesWrite("output.txt", content)
EditEdit filesEdit(file, old, new)
GlobSearch filesGlob("**/*.py")
GrepSearch textGrep("TODO", "src/")
BashExecute commandsBash("npm install")
WebFetchFetch web contentWebFetch(url, prompt)

Practical Example 4: Autonomous Travel Planner Agent

Now let's build a fully autonomous agent:

python
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

python
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

python
# 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:

python
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?

SituationRecommendation
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:

python
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

HookWhen TriggeredApplication
PreToolUseBefore tool executionValidation, logging
PostToolUseAfter tool executionPost-processing, alerts
NotificationOn important eventsNotifications
StopAt session endCleanup, reporting

Best Practices for Production-Ready Agents

1. Clear System Prompts

python
# ❌ 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

python
# ❌ 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

python
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

python
# 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

ModelAliasStrengthsCost
Claude Opus 4.5opusHighest quality, complex tasks$$$
Claude Sonnet 4sonnetBest quality/cost balance$$
Claude HaikuhaikuFast, affordable$

Model Recommendations by Application

ApplicationRecommended Model
Simple Q&AHaiku
General AgentsSonnet
Code GenerationSonnet
Complex AnalysisOpus
Research AgentsOpus

Summary: Your Path to Your First Agent

Checklist for Getting Started

  • Python 3.10+ installed
  • Anthropic API key created
  • claude-agent-sdk installed
  • Simple Q&A agent tested
  • Agent with memory tried
  • Tools added
  • Autonomous agent built

Next Steps

  1. Experiment: Start with the simple Q&A agent
  2. Extend: Add tools as needed
  3. Specialize: Create domain-specific agents
  4. Scale: Use subagents for complex workflows
  5. 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:

  1. Set permission_mode to "manual" or "acceptEdits" instead of "acceptAll"
  2. Explicitly define allowed_tools with only the tools you really need
  3. Implement hooks for security checks and logging

For critical applications, add human-in-the-loop approvals.


Further Resources


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


Updated sources (October 2, 2026)

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.

Request a workshop →

Relevant for your team? Let's talk for 30 minutes.

We sort out what of this actually works in your company — concrete, no slide marathon.

No commitment · 30 minutes · Proposal within 48 h