Claude Code Plugins

Community-maintained marketplace

Feedback

Comprehensive guide for building production-ready agents with the Claude Agent SDK. Use when creating agents, designing tools, implementing subagents, managing sessions, integrating MCP servers, or understanding SDK-native features. Emphasizes documentation-first approach and using only SDK native capabilities.

Install Skill

1Download skill
2Enable skills in Claude

Open claude.ai/settings/capabilities and find the "Skills" section

3Upload to Claude

Click "Upload skill" and select the downloaded ZIP file

Note: Please verify skill by going through its instructions before using it.

SKILL.md

name claude-agent-sdk
description Comprehensive guide for building production-ready agents with the Claude Agent SDK. Use when creating agents, designing tools, implementing subagents, managing sessions, integrating MCP servers, or understanding SDK-native features. Emphasizes documentation-first approach and using only SDK native capabilities.
license MIT

Claude Agent SDK Builder

Documentation-First Agent Development

🚨 THE CRITICAL PRINCIPLE

USE ONLY THE SDK'S NATIVE CAPABILITIES

❌ NEVER implement custom logic for functionality the SDK already handles
✅ ALWAYS check documentation BEFORE writing any code
✅ Every line of code must be justified by the official documentation

Why this matters:

  • 70% of agents fail due to poor design
  • Custom implementations of SDK features create technical debt
  • The SDK evolves - your custom code becomes obsolete
  • SDK features are battle-tested and optimized

Documentation resources:

Quick Start Checklist

Before writing ANY code:

  • Read relevant SDK documentation sections
  • Confirm SDK doesn't provide this feature natively
  • Check Tool Design Framework if creating tools
  • Review Subagent Patterns if using subagents
  • Understand the agent feedback loop: gather context → take action → verify work

The Agent Feedback Loop

Every agent operates in this cycle:

1. GATHER CONTEXT
   ↓
2. TAKE ACTION
   ↓
3. VERIFY WORK
   ↓
(repeat)

Design your agent's capabilities around this loop.

Agent Creation Workflow

Phase 1: Define Requirements

Essential questions:

  • What user intention does this agent serve?
  • What tools and capabilities does it need?
  • Does it need session persistence? Subagents? MCP integration?
  • What are security and performance requirements?

Map requirements to SDK features:

# Before coding, identify needed features:
FEATURES_NEEDED = {
    "session_management": True,     # Resume conversations
    "streaming_mode": True,          # Responsive UX
    "permissions": True,             # Control tool access
    "mcp_integration": False,        # External data sources
    "subagents": "evaluate",         # Complex workflows
    "custom_tools": True,            # Domain-specific actions
    "cost_tracking": True,           # User billing
    "task_tracking": True            # Multi-step workflows
}

# Read documentation for each True/evaluate feature BEFORE coding

Phase 2: Tool Design

CRITICAL: Read references/tool-design-framework.md for complete tool design guidance.

Quick tool design checklist:

  • Tool models clear user intention (not API wrapper)
  • Multi-step workflows consolidated in tool
  • Parameters are natural language concepts
  • Uses SDK's @Tool.register decorator
  • Returns ToolResult objects
  • Error handling uses ToolError

SDK-native tool pattern:

from anthropic_sdk import Tool, ToolResult, ToolError

@Tool.register
def intention_based_name(
    natural_param: str,
    optional_param: str = "sensible_default"
) -> ToolResult:
    """
    Clear description of USER INTENTION this serves.
    NOT what the API does.
    """
    if not natural_param:
        raise ToolError(
            "Parameter required",
            recoverable=True,
            suggestion="Provide valid parameter"
        )
    
    # Tool consolidates ALL workflow steps
    result = complete_workflow(natural_param)
    
    return ToolResult(
        content=result,
        metadata={"confidence": 0.95},
        suggestions=["Try narrowing scope"]
    )

Phase 3: Configure Agent

Choose input mode:

from anthropic_sdk import Agent, InputMode

# Streaming for interactive agents (SDK-native)
agent = Agent(
    model="claude-sonnet-4-20250514",
    input_mode=InputMode.STREAMING,
    tools=[tool1, tool2]
)

# Single for batch/deterministic workflows (SDK-native)
agent = Agent(
    model="claude-sonnet-4-20250514",
    input_mode=InputMode.SINGLE,
    tools=[tool1, tool2]
)

Configure system prompt (SDK-native methods):

# Method 1: CLAUDE.md file (recommended)
# Create CLAUDE.md in project root
# SDK automatically loads it

# Method 2: Append instructions
agent = Agent(
    model="claude-sonnet-4-20250514",
    system_prompt_append="Additional instructions...",
    tools=[...]
)

# Method 3: Output style presets
agent = Agent(
    model="claude-sonnet-4-20250514",
    output_style="concise",  # SDK presets
    tools=[...]
)

Configure permissions (SDK-native):

from anthropic_sdk import PermissionMode

agent = Agent(
    model="claude-sonnet-4-20250514",
    tools=[tool1, tool2, tool3],
    permission_mode=PermissionMode.ASK,  # Ask before tool use
    # OR PermissionMode.AUTO  # Automatic
    # OR PermissionMode.RESTRICTED with allowed_tools
)

Phase 4: Session Management (SDK-Native)

# ❌ NEVER implement custom session storage
# ✅ SDK handles it natively

# Create session
session = agent.create_session(user_id="user_123")
session_id = session.id  # Track this ID

# Resume session
session = agent.resume_session(session_id)

# Fork session for branching
new_session = session.fork()

# SDK handles:
# - Session persistence
# - Conversation history
# - Context management

Phase 5: MCP Integration (When Needed)

Use MCP for:

  • External data sources
  • Third-party API integrations
  • Dynamic resource exposure
from anthropic_sdk import MCPServer

agent = Agent(
    model="claude-sonnet-4-20250514",
    mcp_servers=[
        MCPServer(
            name="database",
            command="uvx",
            args=["mcp-server-sqlite", "--db-path", "data.db"]
        ),
        MCPServer(
            name="github",
            command="npx",
            args=["-y", "@modelcontextprotocol/server-github"],
            env={"GITHUB_TOKEN": os.getenv("GITHUB_TOKEN")}
        )
    ]
)
# SDK manages server lifecycle, auth, tool registration

Phase 6: Subagent Architecture (When Needed)

IMPORTANT: Read references/subagent-patterns.md for complete patterns.

Use subagents for:

  • Specialized agents for different domains
  • Parallel processing of independent tasks
  • Context isolation (sift through large data)
  • Restricted tool access by task type
from anthropic_sdk import Subagent

main_agent = Agent(
    model="claude-sonnet-4-20250514",
    tools=[coordination_tool]
)

# SDK-native subagent
research_subagent = Subagent(
    name="researcher",
    model="claude-sonnet-4-20250514",
    tools=[web_search, document_fetch],
    system_prompt="Research specialist instructions...",
    parent_agent=main_agent
)

# SDK handles orchestration, context isolation, result aggregation

Phase 7: Built-in Features (SDK-Native)

Slash commands:

# Built-in commands:
# /clear - Clear conversation history
# /compact - Compress context
# /session - Session management
# /usage - Token usage

# Custom commands
from anthropic_sdk import SlashCommand

@SlashCommand.register("summarize")
def summarize_conversation(agent: Agent, session: Session):
    return agent.summarize(session)

Cost tracking:

result = agent.run("User message")

# SDK provides accurate metrics
print(f"Tokens: {result.usage.total_tokens}")
print(f"Cost: ${result.usage.estimated_cost}")

# Per-step metrics
for step in result.steps:
    print(f"{step.type}: {step.usage.total_tokens} tokens")

Task tracking:

agent = Agent(
    model="claude-sonnet-4-20250514",
    enable_todos=True,  # SDK-native
    tools=[...]
)

result = agent.run("Plan and execute market analysis")

# SDK tracks tasks automatically
for task in result.todos:
    print(f"{task.description}: {task.status} ({task.progress}%)")

Context Gathering Strategies

Agentic search (recommended):

  • Use file system and bash for context gathering
  • Claude uses grep, tail, etc. to load context intelligently
  • More accurate and transparent than semantic search

Semantic search (when needed):

  • Faster but less accurate
  • Use only if agentic search is too slow
  • Start with agentic, add semantic if necessary

Subagents for context:

  • Spin up subagents to sift through large data
  • Return only relevant excerpts to orchestrator
  • Keeps main agent's context lean

Context compaction (SDK-native):

agent = Agent(
    model="claude-sonnet-4-20250514",
    auto_compact=True,  # SDK automatically summarizes old messages
    tools=[...]
)

Action Strategies

Tools (primary actions):

  • Tools are prominent in context window
  • Design as primary actions agent should take
  • See references/tool-design-framework.md

Bash & scripts:

  • General-purpose flexibility
  • Let agent write and execute code
  • Useful for data processing, API calls

Code generation:

  • Precise, composable, reusable
  • Consider: which tasks benefit from code?
  • Example: Excel/PowerPoint generation via Python

MCPs:

  • Standardized external integrations
  • Handles auth and API calls automatically
  • Growing ecosystem of pre-built servers

Work Verification Strategies

1. Define rules:

@Tool.register
def send_email(to: str, body: str) -> ToolResult:
    # Rule-based validation
    if not is_valid_email(to):
        raise ToolError("Invalid email address")
    
    if not has_sent_to_before(to):
        return ToolResult(
            content="Email sent",
            metadata={"warning": "First contact with this address"}
        )

2. Visual feedback:

  • Screenshot rendered output
  • Use Playwright MCP for automation
  • Agent verifies visual correctness

3. LLM as judge:

  • Another model evaluates output
  • Heavy latency cost
  • Use only when performance boost justifies cost

Common Anti-Patterns

❌ Custom session storage:

# WRONG
def save_session(data):
    with open(f"session_{id}.json", "w") as f:
        json.dump(data, f)

# CORRECT
session = agent.create_session(user_id="user_123")

❌ Manual streaming:

# WRONG
def custom_stream(prompt):
    for chunk in api.stream(prompt):
        yield chunk

# CORRECT
agent = Agent(input_mode=InputMode.STREAMING)

❌ Custom permissions:

# WRONG
if check_user_permission(user_id, tool_name):
    result = agent.run(message)

# CORRECT
agent = Agent(
    permission_mode=PermissionMode.RESTRICTED,
    allowed_tools=get_user_tools(user_id)
)

❌ Custom token counting:

# WRONG
tokens = count_tokens_manually(text)

# CORRECT
result = agent.run(message)
tokens = result.usage.total_tokens

SDK Feature Decision Tree

User Need?
├─ Session management? → create_session/resume_session
├─ Streaming? → InputMode.STREAMING
├─ Permissions? → PermissionMode + allowed_tools
├─ System prompt? → CLAUDE.md or system_prompt_append
├─ Cost tracking? → result.usage
├─ Task tracking? → enable_todos=True
├─ External APIs? → MCP servers
├─ Multi-agent? → Subagent feature
├─ Custom commands? → SlashCommand.register
├─ Tool creation? → Tool.register with ToolResult
└─ Something else? → Re-read docs, likely SDK handles it

Pre-Production Checklist

SDK usage:

  • All features use SDK-native implementations
  • No custom code duplicating SDK functionality
  • Latest SDK version installed

Tool design:

  • Tools reviewed against Tool Design Framework
  • Clear user intentions modeled
  • SDK's Tool.register and ToolResult used

Documentation:

  • All SDK features confirmed in official docs
  • No assumptions about capabilities

Performance & security:

  • Permission modes configured
  • Cost tracking enabled
  • Session management defined
  • Error handling comprehensive

Examples

Customer support agent:

from anthropic_sdk import Agent, Tool, ToolResult, PermissionMode, InputMode

@Tool.register
def search_knowledge_base(query: str, category: str = None) -> ToolResult:
    results = kb_search(query, category)
    return ToolResult(
        content=results,
        metadata={"source": "kb", "confidence": 0.85}
    )

@Tool.register
def create_support_ticket(issue: str, priority: str = "medium") -> ToolResult:
    ticket = ticket_system.create(issue, priority)
    return ToolResult(
        content=f"Ticket #{ticket.id} created",
        metadata={"ticket_id": ticket.id}
    )

agent = Agent(
    model="claude-sonnet-4-20250514",
    input_mode=InputMode.STREAMING,
    permission_mode=PermissionMode.AUTO,
    tools=[search_knowledge_base, create_support_ticket],
    enable_todos=True,
    output_style="helpful"
)

def handle_chat(customer_id: str, message: str):
    session = agent.resume_session(f"customer_{customer_id}") or \
              agent.create_session(user_id=f"customer_{customer_id}")
    
    for chunk in agent.stream(message, session=session):
        yield chunk

Additional Resources

Key Reminders

  1. Documentation first: Read SDK docs before coding
  2. SDK-native: Use built-in features, don't reinvent
  3. Tool design: Follow framework for effective tools
  4. Test thoroughly: Use real scenarios to validate
  5. Iterate: Improve based on actual usage

The SDK is your friend. Use it fully, trust it completely, read the documentation religiously.