Y
Published on

Claude Agent SDK A Comprehensive Tutorial

Authors
  • avatar
    Name
    Yinhuan Yuan
    Twitter

What is the Claude Agent SDK?

The Claude Agent SDK is the infrastructure that powers Claude Code, but it's designed for building all kinds of agents - not just coding tools. It was originally called "Claude Code SDK" but was renamed to reflect its broader capabilities.

Key Principle: The SDK gives your agents access to a computer, allowing them to work like humans do - reading files, running commands, creating visualizations, and executing complex workflows.

Why It Matters

The SDK provides production-ready capabilities including context management, rich tool ecosystem, advanced permissions, built-in error handling, session management, and optimized Claude integration.

Available in both TypeScript and Python, making it accessible to most developers.


What Can You Build?

The SDK enables various agent types including finance agents for portfolio analysis, personal assistants for booking and scheduling, customer support agents handling ambiguous requests, and much more.

Real-World Examples:

1. Coding Agents

  • Code review bots that check for security issues
  • Migration assistants for legacy codebases
  • Automated debugging and testing

2. Research Agents

  • Deep analysis of documents and data
  • Web research with synthesis
  • Report generation with citations

3. Business Automation

  • Financial analysis with API integration
  • Customer support ticket resolution
  • Data processing and visualization

4. Personal Assistants

  • Calendar and email management
  • Travel booking
  • Task coordination across apps

Getting Started

Installation

TypeScript:

npm install @anthropic-ai/claude-agent-sdk

Python:

pip install claude-agent-sdk

Authentication

You need a Claude API key from the Claude Console. Set the ANTHROPIC_API_KEY environment variable.

export ANTHROPIC_API_KEY='your-api-key-here'

The SDK also supports Amazon Bedrock and Google Vertex AI authentication.


Core Concepts

The Agent Loop

Agents typically operate in a feedback loop: gather context → take action → verify work → repeat.

This mirrors how humans work:

  1. Gather Context: Read files, search documentation, fetch data
  2. Take Action: Edit files, run commands, call APIs
  3. Verify Work: Check outputs, run tests, validate results
  4. Repeat: Iterate until the task is complete

File System as Context

The file system represents information that can be pulled into the model's context. Claude uses bash tools like grep and tail to efficiently load large files into its context.


Tutorial: Building Your First Agent

Let me show you how to build a simple agent in both Python and TypeScript.

Example 1: Simple Query (Python)

import anyio
from claude_agent_sdk import query

async def main():
    async for message in query(prompt="What is 2 + 2?"):
        print(message)

anyio.run(main)

Example 2: File Processing Agent (Python)

from claude_agent_sdk import query, ClaudeAgentOptions, AssistantMessage, TextBlock

async def process_data():
    options = ClaudeAgentOptions(
        allowed_tools=["Read", "Write", "Bash"],
        permission_mode='acceptEdits',  # auto-accept file edits
        cwd="/path/to/project"
    )
    
    prompt = """
    Read the data.csv file, analyze the sales trends,
    and create a summary report in markdown format.
    """
    
    async for message in query(prompt=prompt, options=options):
        if isinstance(message, AssistantMessage):
            for block in message.content:
                if isinstance(block, TextBlock):
                    print(block.text)

anyio.run(process_data)

Example 3: Custom Tools (Python)

from claude_agent_sdk import tool, create_sdk_mcp_server, ClaudeAgentOptions, ClaudeSDKClient

# Define a custom tool
@tool("greet", "Greet a user", {"name": str})
async def greet_user(args):
    return {
        "content": [
            {"type": "text", "text": f"Hello, {args['name']}!"}
        ]
    }

# Another custom tool for calculations
@tool("calculate_roi", "Calculate ROI", {"investment": float, "return": float})
async def calculate_roi(args):
    roi = ((args['return'] - args['investment']) / args['investment']) * 100
    return {
        "content": [
            {"type": "text", "text": f"ROI: {roi:.2f}%"}
        ]
    }

# Create an MCP server with your tools
server = create_sdk_mcp_server(
    name="my-tools",
    version="1.0.0",
    tools=[greet_user, calculate_roi]
)

# Use it with Claude
async def main():
    options = ClaudeAgentOptions(
        mcp_servers={"tools": server},
        allowed_tools=["mcp__tools__greet", "mcp__tools__calculate_roi"]
    )
    
    async with ClaudeSDKClient(options=options) as client:
        await client.query("Calculate ROI for $10,000 investment with $15,000 return")
        
        async for msg in client.receive_response():
            print(msg)

anyio.run(main)

Example 4: Interactive Agent (TypeScript)

import { ClaudeSDKClient, ClaudeAgentOptions } from '@anthropic-ai/claude-agent-sdk';

const options: ClaudeAgentOptions = {
  allowedTools: ['Read', 'Write', 'Bash', 'WebSearch'],
  systemPrompt: 'You are a helpful coding assistant.',
  maxTurns: 10
};

const client = new ClaudeSDKClient(options);

// Query the agent
await client.query('Create a Python script that analyzes CSV data');

// Process streaming responses
for await (const message of client.receiveResponse()) {
  console.log(message);
}

await client.close();

Advanced Features

1. Context Management

The SDK automatically handles context window management, ensuring your agent doesn't run out of space.

2. Permission Control

options = ClaudeAgentOptions(
    permission_mode='acceptEdits',  # Auto-accept file changes
    allowed_tools=['Read', 'Write', 'Bash']  # Limit available tools
)

3. Subagents

Launch specialized agents for subtasks with different permissions or capabilities.

4. MCP Integration

Use Model Context Protocol for extensible tool integration.

5. Hooks

Add custom logic at different points in the agent lifecycle.


Real-World Use Case: Email Agent

Let me walk through building an email processing agent:

from claude_agent_sdk import ClaudeSDKClient, ClaudeAgentOptions, tool, create_sdk_mcp_server

# Define email-related tools
@tool("fetch_emails", "Fetch unread emails", {})
async def fetch_emails(args):
    # Your email API integration here
    emails = get_unread_emails()
    return {"content": [{"type": "text", "text": str(emails)}]}

@tool("send_email", "Send an email", {"to": str, "subject": str, "body": str})
async def send_email(args):
    # Your email sending logic
    send_email_via_api(args['to'], args['subject'], args['body'])
    return {"content": [{"type": "text", "text": "Email sent successfully"}]}

@tool("categorize_email", "Categorize email", {"email_id": str, "category": str})
async def categorize_email(args):
    # Your categorization logic
    return {"content": [{"type": "text", "text": f"Categorized as {args['category']}"}]}

# Create the agent
async def email_agent():
    server = create_sdk_mcp_server(
        name="email-tools",
        version="1.0.0",
        tools=[fetch_emails, send_email, categorize_email]
    )
    
    options = ClaudeAgentOptions(
        mcp_servers={"email": server},
        system_prompt="""
        You are an email assistant. You can:
        - Fetch and read emails
        - Categorize emails by importance
        - Draft responses
        - Send emails
        Always ask for confirmation before sending emails.
        """
    )
    
    async with ClaudeSDKClient(options=options) as client:
        await client.query("""
            Check my unread emails, categorize them by urgency,
            and draft responses to the urgent ones.
        """)
        
        async for msg in client.receive_response():
            print(msg)

anyio.run(email_agent)

Best Practices

1. Start Small

Begin with simple queries and gradually add complexity.

2. Clear Prompts

Be explicit about what you want the agent to do:

# ✅ Good
"Read the sales_data.csv file, calculate total revenue by region, and create a bar chart"

# ❌ Vague
"Analyze sales"

3. Tool Permissions

Only grant the tools your agent actually needs:

options = ClaudeAgentOptions(
    allowed_tools=['Read', 'Bash'],  # Only read and bash, no writes
    permission_mode='ask'  # Ask before each action
)

4. Error Handling

Always handle async errors properly:

try:
    async for message in query(prompt=my_prompt, options=options):
        process_message(message)
except Exception as e:
    logger.error(f"Agent error: {e}")

5. Context Efficiency

Use targeted file reads rather than loading everything:

# ✅ Good: Use grep to find relevant sections
"Use grep to find all TODO comments in Python files"

# ❌ Wasteful: Loading entire large files
"Read all files and find TODOs"

Resources


Key Takeaways

  1. The Claude Agent SDK lets you build autonomous agents that can read files, run commands, and execute complex workflows
  2. It's the same infrastructure that powers Claude Code, but for any use case
  3. Available in Python and TypeScript with similar APIs
  4. Supports custom tools via MCP for extending capabilities
  5. Production-ready with built-in context management, permissions, and error handling

Try It Yourself

Want to experiment? Here's a simple starter project:

Goal: Build an agent that analyzes your React codebase for common issues

from claude_agent_sdk import query, ClaudeAgentOptions

async def code_analyzer():
    options = ClaudeAgentOptions(
        allowed_tools=['Read', 'Bash'],
        cwd='/path/to/your/react/project'
    )
    
    prompt = """
    Analyze this React codebase:
    1. Find all useState hooks
    2. Check for missing dependency arrays in useEffect
    3. Look for performance issues (inline functions, etc.)
    4. Generate a markdown report
    """
    
    async for message in query(prompt=prompt, options=options):
        print(message)

anyio.run(code_analyzer)

Would you like me to:

  1. Create a specific agent for your React/TypeScript work?
  2. Build an STM32 code review agent using the SDK?
  3. Show more advanced patterns like subagents or custom MCP servers?