Skip to content
building-with-claude-agent-sdk logo

Claude Agent SDK Development Guide

building-with-claude-agent-sdk

Use when building AI agents with Anthropic's Claude Agent SDK (formerly Claude Code SDK). Triggers include creating autonomous agents, building agentic applications, SDK-based automation, implementing hooks/subagents/MCP servers, session management, or agent tool usage. NOT when using Claude API ...

SKILL.md

Full skill instructions

Claude Agent SDK Development Guide

Build production AI agents that autonomously read files, run commands, search the web, edit code, and more.

Overview

The Claude Agent SDK gives you the same tools, agent loop, and context management that power Claude Code, programmable in Python and TypeScript. It differs from the Anthropic Client SDK: with the Client SDK you implement the tool loop yourself; with the Agent SDK, Claude handles tool execution autonomously.

Quick Reference

Installation

# Step 1: Install Claude Code (required runtime)
curl -fsSL https://claude.ai/​install.sh | bash  # macOS/​Linux/​WSL
# or: npm install -g @anthropic-ai/​claude-code

# Step 2: Install SDK
pip install claude-agent-sdk        # Python
npm install @anthropic-ai/​claude-agent-sdk  # TypeScript

Authentication

export ANTHROPIC_API_KEY=your-api-key
# Alternative providers:
# export CLAUDE_CODE_USE_BEDROCK=1  (Amazon Bedrock)
# export CLAUDE_CODE_USE_VERTEX=1  (Google Vertex AI)

Basic Usage

# Python
import asyncio
from claude_agent_sdk import query, ClaudeAgentOptions

async def main():
    async for message in query(
        prompt="Find and fix the bug in auth.py",
        options=ClaudeAgentOptions(
            allowed_tools=["Read", "Edit", "Bash"],
            permission_mode="acceptEdits"
        )
    ):
        if hasattr(message, "result"):
            print(message.result)

asyncio.run(main())
// TypeScript
import { query } from "@anthropic-ai/​claude-agent-sdk";

for await (const message of query({
  prompt: "Find and fix the bug in auth.py",
  options: {
    allowedTools: ["Read", "Edit", "Bash"],
    permissionMode: "acceptEdits"
  }
})) {
  if ("result" in message) console.log(message.result);
}

Built-in Tools

ToolDescription
ReadRead any file (text, images, PDFs, notebooks)
WriteCreate new files
EditMake precise edits to existing files
BashRun terminal commands, scripts, git
GlobFind files by pattern (**/​*.ts)
GrepSearch file contents with regex
WebSearchSearch the web
WebFetchFetch and parse web pages
TaskSpawn subagents for parallel work

Permission Modes

ModeBehavior
defaultStandard permission checks
acceptEditsAuto-approve file edits
bypassPermissionsNo permission prompts (use cautiously)
planPlanning mode, no execution

Key Configuration Options

ClaudeAgentOptions(
    allowed_tools=["Read", "Edit", "Bash"],  # Tool access
    disallowed_tools=["WebSearch"],           # Block specific tools
    system_prompt="You are a Python expert",  # Custom instructions
    permission_mode="acceptEdits",            # Auto-approve edits
    max_turns=10,                             # Limit iterations
    cwd="/​path/​to/​project",                   # Working directory
    mcp_servers={"db": db_server},            # MCP integrations
    hooks={"PreToolUse": [...]},              # Lifecycle hooks
    agents={"reviewer": agent_def},           # Define subagents
    # UNIQUE FEATURES (not in other SDKs):
    setting_sources=["user", "project"],      # Load Skills from .claude/​skills/
    enable_file_checkpointing=True,           # Track file changes for undo
    can_use_tool=permission_callback,         # Runtime permission decisions
    output_format={"type": "json_schema", "schema": schema},  # Structured output
)

Unique Features (Not in OpenAI/​Google SDKs)

Agent Skills via settingSources

Load filesystem-based Skills (SKILL.md files) to give your agent domain expertise:

options = ClaudeAgentOptions(
    setting_sources=["project"],  # Load from .claude/​skills/
    allowed_tools=["Skill"]       # Enable Skill tool
)

Custom Slash Commands

Create .claude/​commands/​review.md:

---
allowed-tools: Read, Grep
description: Code review
---
Review the code for security and quality issues.

Use in SDK:

async for msg in query(prompt="/​review src/​auth.py", options=opts):
    print(msg)

File Checkpointing

Track file changes and undo them:

options = ClaudeAgentOptions(
    enable_file_checkpointing=True,
    extra_args={"replay-user-messages": None}  # Get checkpoint UUIDs
)

async with ClaudeSDKClient(options) as client:
    await client.query("Refactor auth.py")
    async for msg in client.receive_response():
        if isinstance(msg, UserMessage) and msg.uuid:
            checkpoint_id = msg.uuid  # Save for later

# Later: rewind files
async with ClaudeSDKClient(ClaudeAgentOptions(
    enable_file_checkpointing=True,
    resume=session_id
)) as client:
    await client.query("")
    async for msg in client.receive_response():
        await client.rewind_files(checkpoint_id)
        break

Runtime Permissions with canUseTool

Dynamic permission decisions per tool call:

async def can_use_tool(tool: str, input: dict, context: dict):
    if tool == "Write" and "/​config/" in input.get("file_path", ""):
        return {"behavior": "deny", "message": "Config files protected"}
    return {"behavior": "allow", "updatedInput": input}

options = ClaudeAgentOptions(can_use_tool=can_use_tool)

Cost Tracking

Track per-message token usage and costs:

async for message in query(prompt="Task", options=opts):
    if message.type == "assistant" and hasattr(message, "usage"):
        print(f"Tokens: {message.usage}")
    if message.type == "result":
        print(f"Total cost: ${message.total_cost_usd:.4f}")

System Prompt Presets

Inherit Claude Code's system prompt:

options = ClaudeAgentOptions(
    system_prompt={
        "type": "preset",
        "preset": "claude_code",
        "append": "Always follow PEP 8."
    },
    setting_sources=["project"]  # Required to load CLAUDE.md
)

Sandbox Configuration

Control Bash execution security:

options = ClaudeAgentOptions(
    sandbox={
        "enabled": True,
        "autoAllowBashIfSandboxed": True,
        "network": {"allowLocalBinding": True}
    }
)

Core Patterns

Pattern 1: Streaming vs Single-Turn

Streaming (recommended): Persistent session, supports images, hooks, interrupts:

async def message_generator():
    yield {"type": "user", "message": {"role": "user", "content": "Analyze this"}}

async for msg in query(prompt=message_generator(), options=opts):
    print(msg)

Single-turn: One-shot queries, simpler but limited:

async for msg in query(prompt="Explain the auth flow", options=opts):
    if hasattr(msg, "result"):
        print(msg.result)

Pattern 2: Session Management

# Capture session ID
async for message in query(prompt="Start task", options=opts):
    if hasattr(message, 'subtype') and message.subtype == 'init':
        session_id = message.session_id

# Resume later
async for msg in query(
    prompt="Continue from where we left off",
    options=ClaudeAgentOptions(resume=session_id)
):
    print(msg)

Pattern 3: Subagents

from claude_agent_sdk import AgentDefinition

options = ClaudeAgentOptions(
    allowed_tools=["Read", "Grep", "Task"],  # Task required for subagents
    agents={
        "code-reviewer": AgentDefinition(
            description="Expert code reviewer for security and quality",
            prompt="Analyze code quality and suggest improvements.",
            tools=["Read", "Grep", "Glob"],
            model="sonnet"  # Optional model override
        )
    }
)

Pattern 4: Hooks

from claude_agent_sdk import HookMatcher

async def block_dangerous(input_data, tool_use_id, context):
    if 'rm -rf /' in input_data.get('tool_input', {}).get('command', ''):
        return {
            'hookSpecificOutput': {
                'hookEventName': 'PreToolUse',
                'permissionDecision': 'deny',
                'permissionDecisionReason': 'Dangerous command blocked'
            }
        }
    return {}

options = ClaudeAgentOptions(
    hooks={
        'PreToolUse': [HookMatcher(matcher='Bash', hooks=[block_dangerous])]
    }
)

Pattern 5: Custom MCP Tools

from claude_agent_sdk import tool, create_sdk_mcp_server

@tool("get_weather", "Get temperature for location", {"lat": float, "lon": float})
async def get_weather(args):
    # Your API call here
    return {"content": [{"type": "text", "text": f"Temperature: 72°F"}]}

weather_server = create_sdk_mcp_server(
    name="weather",
    tools=[get_weather]
)

options = ClaudeAgentOptions(
    mcp_servers={"weather": weather_server},
    allowed_tools=["mcp__weather__get_weather"]
)

ClaudeSDKClient (Python Multi-Turn)

For continuous conversations with session continuity:

from claude_agent_sdk import ClaudeSDKClient, ClaudeAgentOptions

async with ClaudeSDKClient(options) as client:
    await client.query("What's the capital of France?")
    async for msg in client.receive_response():
        print(msg)

    # Follow-up - Claude remembers context
    await client.query("What's the population of that city?")
    async for msg in client.receive_response():
        print(msg)

Hook Events

EventWhen TriggeredUse Case
PreToolUseBefore tool executesBlock/​modify operations
PostToolUseAfter tool completesLogging, auditing
UserPromptSubmitPrompt submittedAdd context
StopAgent stopsCleanup
SubagentStopSubagent finishesAggregate results
PreCompactBefore compactionArchive transcript

Best Practices

Context Management

  • Isolate per-subagent context
  • Use CLAUDE.md for project conventions
  • Periodically prune context in long sessions

Security

  • Start from deny-all; allowlist needed tools only
  • Require confirmations for sensitive actions
  • Block dangerous commands (rm -rf, sudo)

Tool Design

  • Keep tools small with clear schemas
  • Tools are prominent in Claude's context
  • Design for composability

Error Handling

from claude_agent_sdk import CLINotFoundError, ProcessError

try:
    async for msg in query(prompt="Task", options=opts):
        print(msg)
except CLINotFoundError:
    print("Install Claude Code: npm install -g @anthropic-ai/​claude-code")
except ProcessError as e:
    print(f"Failed with exit code: {e.exit_code}")

Hosting Patterns

PatternDescriptionUse Case
EphemeralNew container per taskBug fixes, one-off processing
Long-RunningPersistent containersEmail agents, chatbots
HybridHydrated with historyProject managers, deep research

Official Documentation

For complete API reference:

References

Load these for detailed patterns:

More skills from majiayu000

xiaohongshu logo
majiayu000/claude-arsenal

xiaohongshu

xiaohongshu

286 148
View
agent-task-conductor logo
majiayu000/claude-skill-registry

agent-task-conductor

Conduct multi-agent task orchestration and workflow coordination.

663 1
View
conductor-setup logo
majiayu000/claude-skill-registry

conductor-setup

Initialize project with Conductor artifacts (product definition,

663 1
View
animation-designer logo
majiayu000/claude-skill-registry

animation-designer

Expert in web animations, transitions, and motion design using Framer Motion and CSS

663 1
View
diagramming logo
majiayu000/claude-skill-registry

diagramming

Creates Mermaid and ASCII diagrams for flowcharts, architecture, ERDs, state machines, mindmaps, and more. Use when user mentions diagram, flowchart, mermaid, ASCII diagram, text diagram, terminal diagram, visualize, C4, mindmap, architecture diagram, sequence diagram, ERD, or needs visual docume...

663 1
View
h3-pg logo
majiayu000/claude-skill-registry-data

h3-pg

PostgreSQL bindings for H3 hexagonal grid system. Use when working with H3 cells in Postgres, including spatial indexing, geometry/geography integration, and raster analysis.

23 1
View
conductor-development logo
majiayu000/claude-skill-registry

conductor-development

Context-Driven Development skill for projects using Conductor. Use this skill when you detect a `conductor/` directory in the project, when working on tasks defined in a `plan.md` file, or when the user asks about tracks, specs, or plans. Automatically applies TDD workflow, tracks task completion...

663 1
View
conductor-status logo
majiayu000/claude-skill-registry

conductor-status

Display project status, active tracks, and next actions

663 1
View
dockerization logo
majiayu000/claude-skill-registry

dockerization

Official Stakpak application containerization standard operating procedure, a step-by-step guidline to properly dockerize applications. This is a rule book curated by the Stakpak Team.

663 1
View

Popular AI tools

Kaiber logo
Video

Kaiber

Generate, edit, and beat-sync AI video with leading models in one workspace.

Paid
View
Vimcal logo
Productivity

Vimcal

The world's fastest calendar for remote work

Free
View

Transform Your Design with AI Designer by ImgCreator.ai

Freemium
View
Akool AI logo
Content & writing

Akool AI

Revolutionizing Video Production with AI-Powered Creativity

Paid
View

Extend an image past the frame and let AI fill the new aspect ratio.

Freemium
View
StarByFace logo
Security

StarByFace

Discover your celebrity doppelgänger with StarByFace!

Free
View
C

ChainClarity explains 700+ crypto whitepapers in plain English, with layered summaries, comparisons, research tools, alerts, and a $4.99 Pro plan.

Freemium
View
Opus Clip logo
Coding & apps

Opus Clip

Opus.ai: Revolutionize Your Web Experience

Free
View