Claude Agent SDK

Medium 28 min read

SDK Overview

Why Claude Agent SDK Matters

The Problem: Building agents with Claude requires manually handling tool definitions, response parsing, conversation loops, and streaming -- significant boilerplate for every project.

The Solution: The Claude Agent SDK provides a Python-first framework for building agents with Claude, offering structured tool use, streaming responses, and seamless integration with the Anthropic API.

Real Impact: Teams using the Claude Agent SDK report 60% faster agent development with built-in best practices for safety, structured outputs, and conversation management.

Real-World Analogy

Think of the Claude Agent SDK as a professional kitchen setup:

  • Agent = The head chef who coordinates the meal preparation
  • Tools = Kitchen appliances (oven, mixer, blender) the chef uses
  • Streaming = Watching the chef cook in real-time through an open kitchen
  • System Prompt = The recipe and kitchen rules the chef follows
  • Tool Results = Ingredients delivered from the pantry when requested

Core SDK Components

Agent Class

The main entry point for creating Claude-powered agents with configurable system prompts, tools, and model parameters.

Tool Definitions

Structured tool schemas using Python dataclasses or Pydantic models that Claude can invoke during conversations.

Streaming Interface

Real-time token-by-token output with event hooks for tool calls, completions, and errors.

Claude Code Integration

Seamless integration with Claude Code for building CLI agents that can read, write, and execute code.

Setting Up

Claude Agent SDK Architecture
Your Code Agent SDK Agent Config Tool Registry Stream Handler Conversation Loop Claude API Anthropic Cloud Tools Web Search File Operations Custom Functions
setup.sh
# Install the Claude Agent SDK
pip install claude-agent-sdk

# Set your API key
export ANTHROPIC_API_KEY="your-api-key-here"

# Verify installation
python -c "import claude_agent_sdk; print(claude_agent_sdk.__version__)"

Agent Configuration

claude_agent.py
import anthropic
from claude_agent_sdk import Agent, tool

# Initialize the client
client = anthropic.Anthropic()

# Define tools using decorators
@tool
def get_weather(city: str, units: str = "celsius") -> str:
    """Get the current weather for a city.

    Args:
        city: The city name to look up
        units: Temperature units (celsius or fahrenheit)
    """
    return f"Weather in {city}: 22 {units}, partly cloudy"

@tool
def search_web(query: str) -> str:
    """Search the web for information.

    Args:
        query: The search query
    """
    return f"Search results for: {query}"

# Create the agent
agent = Agent(
    client=client,
    model="claude-sonnet-4-20250514",
    system_prompt="""You are a helpful assistant that can check
    weather and search the web. Always be concise.""",
    tools=[get_weather, search_web],
    max_turns=10,
)

# Run the agent
response = agent.run("What's the weather like in Tokyo?")
print(response)

Tool Use

Tool Definition Best Practices

  • Clear Docstrings: Claude uses docstrings to understand when and how to use tools
  • Type Hints: Always use Python type hints for parameters -- they become the tool schema
  • Default Values: Provide sensible defaults for optional parameters
  • Error Handling: Return descriptive error messages so Claude can retry or adjust
  • Focused Tools: Each tool should do one thing well rather than being a Swiss army knife

Streaming

streaming_agent.py
# Stream responses in real-time
async def run_streaming():
    agent = Agent(
        client=client,
        model="claude-sonnet-4-20250514",
        system_prompt="You are a helpful research assistant.",
        tools=[search_web],
    )

    # Stream with event callbacks
    async for event in agent.stream("Research quantum computing advances"):
        if event.type == "text":
            print(event.text, end="", flush=True)
        elif event.type == "tool_call":
            print(f"\nCalling tool: {event.tool_name}")
        elif event.type == "tool_result":
            print(f"\nTool result received")
        elif event.type == "complete":
            print("\nAgent finished")

Common Pitfall

Problem: Agent makes too many tool calls for simple queries, wasting tokens and time.

Solution: Set max_turns to limit the agent loop. Use clear system prompts that instruct Claude to answer directly when it already has the information, and only use tools when external data is truly needed.

Quick Reference

FunctionDescriptionExample
Agent()Create an agentAgent(client=c, model="...", tools=[...])
@toolDefine a tool@tool def my_func(x: str): ...
.run()Run synchronouslyresult = agent.run("query")
.stream()Stream responsesasync for event in agent.stream(...):
max_turnsLimit agent loopsAgent(..., max_turns=10)
system_promptSet agent behaviorAgent(..., system_prompt="...")
anthropic.Anthropic()API clientclient = anthropic.Anthropic()