CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-claude-agent-sdk

Python SDK for Claude Code enabling developers to build AI-powered applications and agents with support for custom tools, hooks, and bidirectional interactive conversations

Moderation error
Malicious code detected in tile.json: This tile describes a package named 'claude-agent-sdk' on PyPI, which appears to be typosquatting/impersonating official Anthropic SDK packages. The legitimate Anthropic Python SDK is 'anthropic', not 'claude-agent-sdk'. This naming pattern (claude-agent-sdk) is designed to deceive developers into installing a potentially malicious package by mimicking official Anthropic/Claude branding. This is a classic supply chain attack vector through package name confusion.
Overview
Eval results
Files

configuration.mddocs/reference/

Configuration Options

Comprehensive configuration through the ClaudeAgentOptions dataclass, controlling tools, permissions, models, execution environment, MCP servers, hooks, and advanced features.

Capabilities

ClaudeAgentOptions Dataclass

Main configuration dataclass with 32 fields for fine-grained control.

@dataclass
class ClaudeAgentOptions:
    """Configuration options for Claude agent interactions.
    
    All fields are optional with sensible defaults. Configure only what you need.
    """
    
    # Tool Configuration
    tools: list[str] | ToolsPreset | None = None
    allowed_tools: list[str] = field(default_factory=list)
    disallowed_tools: list[str] = field(default_factory=list)

    # Permission Configuration
    permission_mode: PermissionMode | None = None
    can_use_tool: CanUseTool | None = None
    permission_prompt_tool_name: str | None = None

    # Model Configuration
    model: str | None = None
    fallback_model: str | None = None
    betas: list[SdkBeta] = field(default_factory=list)
    max_thinking_tokens: int | None = None
    output_format: dict[str, Any] | None = None

    # Session Configuration
    system_prompt: str | SystemPromptPreset | None = None
    max_turns: int | None = None
    max_budget_usd: float | None = None
    continue_conversation: bool = False
    resume: str | None = None
    fork_session: bool = False
    user: str | None = None

    # Execution Environment
    cwd: str | Path | None = None
    cli_path: str | Path | None = None
    env: dict[str, str] = field(default_factory=dict)
    add_dirs: list[str | Path] = field(default_factory=list)
    settings: str | None = None
    setting_sources: list[SettingSource] | None = None

    # Integration
    mcp_servers: dict[str, McpServerConfig] | str | Path = field(default_factory=dict)
    hooks: dict[HookEvent, list[HookMatcher]] | None = None
    agents: dict[str, AgentDefinition] | None = None
    plugins: list[SdkPluginConfig] = field(default_factory=list)

    # Advanced
    sandbox: SandboxSettings | None = None
    enable_file_checkpointing: bool = False
    include_partial_messages: bool = False
    max_buffer_size: int | None = None
    stderr: Callable[[str], None] | None = None
    extra_args: dict[str, str | None] = field(default_factory=dict)

Tool Configuration

tools

Type: list[str] | ToolsPreset | None
Default: None

Tool preset configuration. Can be a list of tool names or a preset object.

class ToolsPreset(TypedDict):
    """Tool preset configuration."""
    type: Literal["preset"]
    preset: Literal["claude_code"]

Usage:

from claude_agent_sdk import ClaudeAgentOptions

# Using preset
options = ClaudeAgentOptions(
    tools={"type": "preset", "preset": "claude_code"}
)

# Using explicit list
options = ClaudeAgentOptions(
    tools=["Read", "Write", "Bash", "Edit"]
)

allowed_tools

Type: list[str]
Default: [] (empty list, which means no tools allowed by default when permission_mode is not bypassPermissions)

List of tools explicitly allowed for Claude to use.

Common Built-in Tools:

  • "Read" - Read files from the filesystem
  • "Write" - Write new files to the filesystem
  • "Edit" - Edit existing files
  • "Bash" - Execute bash commands
  • "Grep" - Search for patterns in files
  • "Glob" - Find files matching patterns
  • "Task" - Launch specialized sub-agents
  • "WebFetch" - Fetch content from URLs
  • "WebSearch" - Search the web
  • "AskUserQuestion" - Ask the user for input
  • "TodoWrite" - Manage task lists
  • "MultiEdit" - Edit multiple files at once

MCP Tools: Tools from MCP servers are accessed with the format mcp__<server_name>__<tool_name>. See Custom Tools and MCP Servers for details.

Usage:

from claude_agent_sdk import ClaudeAgentOptions

# Allow specific built-in tools
options = ClaudeAgentOptions(
    allowed_tools=["Read", "Write", "Bash", "Edit", "Grep", "Glob"]
)

# Include MCP tools (use mcp__<server>__<tool> format)
options = ClaudeAgentOptions(
    allowed_tools=[
        "Read",
        "Write",
        "mcp__calculator__add",      # Tool "add" from server "calculator"
        "mcp__calculator__multiply",  # Tool "multiply" from server "calculator"
        "mcp__database__query"        # Tool "query" from server "database"
    ]
)

disallowed_tools

Type: list[str]
Default: [] (empty list)

List of tools explicitly disallowed. Takes precedence over allowed_tools.

Usage:

from claude_agent_sdk import ClaudeAgentOptions

# Allow many tools but explicitly block Bash
options = ClaudeAgentOptions(
    allowed_tools=["Read", "Write", "Bash", "Edit"],
    disallowed_tools=["Bash"]  # Bash is blocked despite being in allowed_tools
)

Permission Configuration

permission_mode

Type: PermissionMode | None
Default: None (uses CLI default behavior)

Permission behavior mode controlling how tools are authorized.

PermissionMode = Literal["default", "acceptEdits", "plan", "bypassPermissions"]

Options:

  • "default": CLI prompts for dangerous tools (interactive, not suitable for automation)
  • "acceptEdits": Auto-accept file edits (recommended for automation with file operations)
  • "plan": Plan mode for design/planning workflows
  • "bypassPermissions": Allow all tools without prompting (use with extreme caution!)

Usage:

from claude_agent_sdk import ClaudeAgentOptions

# Auto-accept file edits (recommended for automation)
options = ClaudeAgentOptions(
    permission_mode="acceptEdits",
    allowed_tools=["Read", "Write", "Edit"]
)

# Bypass all permissions (dangerous! only in controlled environments)
options = ClaudeAgentOptions(
    permission_mode="bypassPermissions"
)

can_use_tool

Type: CanUseTool | None
Default: None

Custom permission callback for fine-grained tool authorization. Requires streaming mode (ClaudeSDKClient or AsyncIterable prompt).

CanUseTool = Callable[
    [str, dict[str, Any], ToolPermissionContext],
    Awaitable[PermissionResult]
]

Callback Signature:

  • Parameter 1 (str): Tool name being requested
  • Parameter 2 (dict[str, Any]): Tool input parameters
  • Parameter 3 (ToolPermissionContext): Context with signal and suggestions
  • Returns: PermissionResult (either PermissionResultAllow or PermissionResultDeny)

Usage:

from claude_agent_sdk import (
    ClaudeSDKClient,
    ClaudeAgentOptions,
    ToolPermissionContext,
    PermissionResult,
    PermissionResultAllow,
    PermissionResultDeny
)

async def permission_callback(
    tool_name: str,
    tool_input: dict[str, Any],
    context: ToolPermissionContext
) -> PermissionResult:
    """Custom permission logic."""
    
    # Allow Read operations
    if tool_name == "Read":
        return PermissionResultAllow(behavior="allow")
    
    # Check Bash commands for dangerous operations
    if tool_name == "Bash":
        command = tool_input.get("command", "")
        
        # Block destructive commands
        if any(pattern in command for pattern in ["rm -rf", "format", "dd if="]):
            return PermissionResultDeny(
                behavior="deny",
                message=f"Dangerous command blocked: {command}",
                interrupt=True  # Stop the conversation
            )
        
        # Allow safe commands
        return PermissionResultAllow(behavior="allow")
    
    # Block Write to sensitive files
    if tool_name in ["Write", "Edit"]:
        file_path = tool_input.get("file_path", "")
        if any(sensitive in file_path for sensitive in [".env", "credentials", "secrets"]):
            return PermissionResultDeny(
                behavior="deny",
                message=f"Cannot modify sensitive file: {file_path}",
                interrupt=False
            )
    
    # Default: allow
    return PermissionResultAllow(behavior="allow")

options = ClaudeAgentOptions(
    can_use_tool=permission_callback,
    allowed_tools=["Read", "Write", "Bash"]
)

async with ClaudeSDKClient(options=options) as client:
    await client.query("Analyze and fix the codebase")
    async for msg in client.receive_response():
        print(msg)

See Permission System for complete details.

permission_prompt_tool_name

Type: str | None
Default: None

Tool name for permission prompts. Set to "stdio" for control protocol. Cannot be used with can_use_tool.

Usage:

from claude_agent_sdk import ClaudeAgentOptions

options = ClaudeAgentOptions(
    permission_prompt_tool_name="stdio"
)

Model Configuration

model

Type: str | None
Default: None (uses CLI default, typically "sonnet")

AI model to use for the conversation.

Valid Model Names:

  • Short names: "sonnet", "opus", "haiku"
  • Full model IDs: "claude-sonnet-4-5", "claude-opus-4-5", "claude-haiku-4", or any valid Anthropic model ID

Model Comparison:

  • "haiku": Fastest, cheapest, suitable for simple tasks
  • "sonnet": Balanced performance and cost (default)
  • "opus": Most capable, slowest, most expensive

Usage:

from claude_agent_sdk import ClaudeAgentOptions

# Using short name
options = ClaudeAgentOptions(
    model="sonnet"  # or "opus", "haiku"
)

# Using full model ID
options = ClaudeAgentOptions(
    model="claude-sonnet-4-5"
)

fallback_model

Type: str | None
Default: None

Fallback model if primary model is unavailable.

Usage:

from claude_agent_sdk import ClaudeAgentOptions

options = ClaudeAgentOptions(
    model="opus",
    fallback_model="sonnet"  # Use sonnet if opus unavailable
)

betas

Type: list[SdkBeta]
Default: [] (empty list)

Beta feature flags to enable experimental features.

SdkBeta = Literal["context-1m-2025-08-07"]

Available Beta Features:

  • "context-1m-2025-08-07" - Enables extended context window support (1 million tokens)

Usage:

from claude_agent_sdk import ClaudeAgentOptions

options = ClaudeAgentOptions(
    betas=["context-1m-2025-08-07"],
    model="opus"  # Extended context typically used with more capable models
)

max_thinking_tokens

Type: int | None
Default: None

Maximum tokens for extended thinking blocks. Requires models that support extended thinking.

Usage:

from claude_agent_sdk import ClaudeAgentOptions

options = ClaudeAgentOptions(
    max_thinking_tokens=10000,
    model="opus"  # Extended thinking typically available on more capable models
)

output_format

Type: dict[str, Any] | None
Default: None

Structured output format matching Messages API structure. Use to request JSON outputs conforming to a specific schema.

Usage:

from claude_agent_sdk import ClaudeAgentOptions

# Define JSON Schema for structured output
schema = {
    "type": "json_schema",
    "json_schema": {
        "name": "code_analysis",
        "strict": True,
        "schema": {
            "type": "object",
            "properties": {
                "files_analyzed": {"type": "integer"},
                "issues": {
                    "type": "array",
                    "items": {
                        "type": "object",
                        "properties": {
                            "severity": {"type": "string", "enum": ["critical", "warning", "info"]},
                            "file": {"type": "string"},
                            "line": {"type": "integer"},
                            "description": {"type": "string"}
                        },
                        "required": ["severity", "file", "description"],
                        "additionalProperties": False
                    }
                }
            },
            "required": ["files_analyzed", "issues"],
            "additionalProperties": False
        }
    }
}

options = ClaudeAgentOptions(
    output_format=schema,
    allowed_tools=["Read", "Grep"]
)

The structured output will be available in ResultMessage.structured_output.

Session Configuration

system_prompt

Type: str | SystemPromptPreset | None
Default: None (uses CLI default system prompt)

System prompt for the conversation. Can be a string or preset configuration.

class SystemPromptPreset(TypedDict):
    """System prompt preset configuration."""
    type: Literal["preset"]
    preset: Literal["claude_code"]
    append: NotRequired[str]

Usage:

from claude_agent_sdk import ClaudeAgentOptions

# String prompt
options = ClaudeAgentOptions(
    system_prompt="You are a helpful Python expert specializing in web development"
)

# Preset with append
options = ClaudeAgentOptions(
    system_prompt={
        "type": "preset",
        "preset": "claude_code",
        "append": "Additional instructions: Focus on security and performance"
    }
)

max_turns

Type: int | None
Default: None (unlimited)

Maximum conversation turns before stopping. Useful for cost control and preventing infinite loops.

Usage:

from claude_agent_sdk import ClaudeAgentOptions

options = ClaudeAgentOptions(
    max_turns=5  # Stop after 5 turns
)

max_budget_usd

Type: float | None
Default: None (unlimited)

Cost budget limit in USD. Conversation stops if cost exceeds this limit.

Usage:

from claude_agent_sdk import ClaudeAgentOptions

options = ClaudeAgentOptions(
    max_budget_usd=1.0  # Stop if cost exceeds $1.00
)

continue_conversation

Type: bool
Default: False

Continue existing conversation session without forking.

Usage:

from claude_agent_sdk import ClaudeAgentOptions

options = ClaudeAgentOptions(
    continue_conversation=True
)

resume

Type: str | None
Default: None

Resume from session ID. Get session ID from ResultMessage.session_id.

Usage:

from claude_agent_sdk import ClaudeAgentOptions

# Resume previous session
options = ClaudeAgentOptions(
    resume="session-abc-123"  # Session ID from previous ResultMessage
)

fork_session

Type: bool
Default: False

Fork resumed session to new ID instead of continuing. Use with resume to create a branch from a previous session.

Usage:

from claude_agent_sdk import ClaudeAgentOptions

# Fork from existing session (creates new session ID)
options = ClaudeAgentOptions(
    resume="session-abc-123",
    fork_session=True  # Creates new session from this point
)

user

Type: str | None
Default: None

User identifier for the session. Useful for tracking or multi-user systems.

Usage:

from claude_agent_sdk import ClaudeAgentOptions

options = ClaudeAgentOptions(
    user="user@example.com"
)

Execution Environment

cwd

Type: str | Path | None
Default: None (uses current working directory)

Working directory for the session. All file operations are relative to this directory.

Usage:

from pathlib import Path
from claude_agent_sdk import ClaudeAgentOptions

# String path
options = ClaudeAgentOptions(
    cwd="/path/to/project"
)

# Path object
options = ClaudeAgentOptions(
    cwd=Path("/path/to/project")
)

cli_path

Type: str | Path | None
Default: None (uses bundled Claude Code CLI)

Path to Claude Code CLI executable. If None, uses bundled CLI included with SDK.

Usage:

from claude_agent_sdk import ClaudeAgentOptions

options = ClaudeAgentOptions(
    cli_path="/usr/local/bin/claude-code"  # Use custom CLI installation
)

env

Type: dict[str, str]
Default: {} (empty dict)

Environment variables for the session. These are passed to the CLI and available in tool execution.

Usage:

from claude_agent_sdk import ClaudeAgentOptions

options = ClaudeAgentOptions(
    env={
        "DEBUG": "true",
        "API_KEY": "secret",
        "ENVIRONMENT": "production"
    }
)

add_dirs

Type: list[str | Path]
Default: [] (empty list)

Additional directories to include in context for file operations.

Usage:

from claude_agent_sdk import ClaudeAgentOptions

options = ClaudeAgentOptions(
    add_dirs=["/path/to/lib", "/path/to/config", "/path/to/docs"]
)

settings

Type: str | None
Default: None

Settings profile name to load. Profiles are defined in Claude Code configuration files.

Usage:

from claude_agent_sdk import ClaudeAgentOptions

options = ClaudeAgentOptions(
    settings="production"  # Load "production" settings profile
)

setting_sources

Type: list[SettingSource] | None
Default: None (loads all sources)

Which setting sources to load. Controls configuration hierarchy.

SettingSource = Literal["user", "project", "local"]

Sources:

  • "user": User-level settings (e.g., ~/.config/claude)
  • "project": Project-level settings (e.g., .claude/ in project root)
  • "local": Local workspace settings

Usage:

from claude_agent_sdk import ClaudeAgentOptions

# Only project settings (reproducible builds for CI/CD)
options = ClaudeAgentOptions(
    setting_sources=["project"]  # Exclude user and local settings
)

# User and project, but not local
options = ClaudeAgentOptions(
    setting_sources=["user", "project"]
)

Integration Configuration

mcp_servers

Type: dict[str, McpServerConfig] | str | Path
Default: {} (empty dict, no MCP servers)

MCP server configurations. Can be dictionary of server configs or path to config file.

Usage:

from claude_agent_sdk import ClaudeAgentOptions, tool, create_sdk_mcp_server

# In-process SDK server
@tool("add", "Add numbers", {"a": float, "b": float})
async def add(args):
    return {"content": [{"type": "text", "text": f"{args['a'] + args['b']}"}]}

sdk_server = create_sdk_mcp_server("calc", tools=[add])

# Mixed configuration
options = ClaudeAgentOptions(
    mcp_servers={
        "calculator": sdk_server,  # In-process SDK server
        "external": {  # External stdio server
            "type": "stdio",
            "command": "mcp-server",
            "args": ["--config", "config.json"]
        },
        "remote": {  # Remote SSE server
            "type": "sse",
            "url": "https://example.com/mcp",
            "headers": {"Authorization": "Bearer token"}
        }
    },
    allowed_tools=[
        "mcp__calculator__add",      # SDK server tool
        "mcp__external__some_tool",  # External server tool
        "mcp__remote__remote_tool"   # Remote server tool
    ]
)

# Load from file
options = ClaudeAgentOptions(
    mcp_servers="/path/to/mcp-config.json"
)

See Custom Tools and MCP Servers for detailed information.

hooks

Type: dict[HookEvent, list[HookMatcher]] | None
Default: None (no hooks)

Hook configurations for deterministic processing at specific points in the agent loop.

Usage:

from claude_agent_sdk import ClaudeAgentOptions, HookMatcher

async def pre_tool_hook(input_data, tool_use_id, context):
    """Hook executed before tool use."""
    if input_data["tool_name"] == "Bash":
        print(f"About to execute: {input_data['tool_input']}")
    return {"continue_": True}

options = ClaudeAgentOptions(
    hooks={
        "PreToolUse": [
            HookMatcher(
                matcher="Bash",  # Only for Bash tool
                hooks=[pre_tool_hook],
                timeout=30.0
            )
        ]
    }
)

See Hooks for complete details.

agents

Type: dict[str, AgentDefinition] | None
Default: None (no custom agents)

Custom agent definitions for specialized sub-agents.

@dataclass
class AgentDefinition:
    """Custom agent definition."""
    description: str  # Human-readable description
    prompt: str  # System prompt for agent
    tools: list[str] | None = None  # Tools available to agent
    model: Literal["sonnet", "opus", "haiku", "inherit"] | None = None  # Model to use

Usage:

from claude_agent_sdk import ClaudeAgentOptions, AgentDefinition

options = ClaudeAgentOptions(
    agents={
        "reviewer": AgentDefinition(
            description="Code review specialist",
            prompt="You are an expert code reviewer",
            tools=["Read", "Grep"],
            model="sonnet"
        ),
        "implementer": AgentDefinition(
            description="Implementation specialist",
            prompt="You implement code changes",
            tools=["Read", "Write", "Edit"],
            model="opus"
        )
    }
)

See Advanced Features for details.

plugins

Type: list[SdkPluginConfig]
Default: [] (no plugins)

Plugin configurations to extend SDK functionality.

class SdkPluginConfig(TypedDict):
    """Plugin configuration."""
    type: Literal["local"]  # Plugin type
    path: str  # Path to plugin file

Usage:

from claude_agent_sdk import ClaudeAgentOptions

options = ClaudeAgentOptions(
    plugins=[
        {"type": "local", "path": "/path/to/custom_logger.py"},
        {"type": "local", "path": "/path/to/metrics_collector.py"}
    ]
)

Advanced Configuration

sandbox

Type: SandboxSettings | None
Default: None (no sandboxing)

Bash command sandboxing configuration (macOS and Linux only).

Usage:

from claude_agent_sdk import ClaudeAgentOptions

options = ClaudeAgentOptions(
    sandbox={
        "enabled": True,
        "autoAllowBashIfSandboxed": True,
        "excludedCommands": ["docker", "git"],
        "network": {
            "allowUnixSockets": ["/var/run/docker.sock"],
            "allowLocalBinding": True
        }
    }
)

See Sandbox Configuration for complete details.

enable_file_checkpointing

Type: bool
Default: False

Enable file change tracking for rewinding. Required for ClaudeSDKClient.rewind_files().

Usage:

from claude_agent_sdk import ClaudeAgentOptions

options = ClaudeAgentOptions(
    enable_file_checkpointing=True  # Enable tracking
)

include_partial_messages

Type: bool
Default: False

Include partial message updates during streaming. When enabled, yields StreamEvent messages with incremental updates.

Usage:

from claude_agent_sdk import ClaudeAgentOptions

options = ClaudeAgentOptions(
    include_partial_messages=True  # Get partial updates
)

See Message and Content Types for StreamEvent details.

max_buffer_size

Type: int | None
Default: None (unlimited)

Maximum bytes when buffering CLI stdout.

Usage:

from claude_agent_sdk import ClaudeAgentOptions

options = ClaudeAgentOptions(
    max_buffer_size=1048576  # 1MB limit
)

stderr

Type: Callable[[str], None] | None
Default: None

Callback for stderr output from CLI. Useful for logging and debugging.

Usage:

from claude_agent_sdk import ClaudeAgentOptions

def stderr_handler(output: str):
    """Handle stderr output."""
    print(f"CLI stderr: {output}")

options = ClaudeAgentOptions(
    stderr=stderr_handler
)

extra_args

Type: dict[str, str | None]
Default: {} (no extra args)

Pass arbitrary CLI flags. Values are flag values, None for boolean flags.

Usage:

from claude_agent_sdk import ClaudeAgentOptions

options = ClaudeAgentOptions(
    extra_args={
        "replay-user-messages": None,  # Boolean flag without value
        "custom-flag": "value",  # Flag with value
        "another-option": "123"
    }
)

Complete Configuration Example

import anyio
from pathlib import Path
from claude_agent_sdk import (
    ClaudeSDKClient,
    ClaudeAgentOptions,
    AgentDefinition,
    tool,
    create_sdk_mcp_server,
    HookMatcher
)

# Define custom tool
@tool("custom_tool", "A custom tool", {"input": str})
async def custom_tool(args):
    return {"content": [{"type": "text", "text": f"Processed: {args['input']}"}]}

# Define hook
async def logging_hook(input, tool_use_id, context):
    print(f"Tool {input.get('tool_name')} called")
    return {"continue_": True}

async def main():
    # Create MCP server
    server = create_sdk_mcp_server("custom", tools=[custom_tool])

    # Complete configuration
    options = ClaudeAgentOptions(
        # Tools and permissions
        allowed_tools=["Read", "Write", "Edit", "mcp__custom__custom_tool"],
        disallowed_tools=[],
        permission_mode="acceptEdits",

        # Model configuration
        model="sonnet",
        fallback_model="haiku",
        max_thinking_tokens=5000,
        betas=["context-1m-2025-08-07"],

        # Session
        system_prompt="You are an expert Python developer",
        max_turns=10,
        max_budget_usd=2.0,

        # Environment
        cwd=Path("/path/to/project"),
        env={"DEBUG": "true", "ENVIRONMENT": "development"},
        add_dirs=["/path/to/lib"],

        # Integration
        mcp_servers={"custom": server},
        hooks={
            "PreToolUse": [HookMatcher(hooks=[logging_hook])]
        },
        agents={
            "test": AgentDefinition(
                description="Test agent",
                prompt="Run tests",
                tools=["Bash"],
                model="haiku"
            )
        },

        # Advanced
        enable_file_checkpointing=True,
        sandbox={
            "enabled": True,
            "autoAllowBashIfSandboxed": True
        }
    )

    async with ClaudeSDKClient(options=options) as client:
        await client.query("Help me with this project")
        async for msg in client.receive_response():
            print(msg)

anyio.run(main)

Common Configuration Patterns

Pattern 1: Automation (Non-Interactive)

from claude_agent_sdk import ClaudeAgentOptions

options = ClaudeAgentOptions(
    permission_mode="acceptEdits",  # No prompts
    max_turns=20,
    max_budget_usd=5.0,
    model="haiku",  # Fast and cheap
    allowed_tools=["Read", "Write", "Bash"]
)

Pattern 2: Safe Exploration

from claude_agent_sdk import ClaudeAgentOptions

options = ClaudeAgentOptions(
    permission_mode="default",  # Prompt for actions
    allowed_tools=["Read", "Grep", "Glob"],  # Read-only
    max_turns=10
)

Pattern 3: CI/CD

from claude_agent_sdk import ClaudeAgentOptions

options = ClaudeAgentOptions(
    permission_mode="bypassPermissions",
    setting_sources=["project"],  # Reproducible
    max_budget_usd=1.0,
    env={"CI": "true"}
)

Pattern 4: Development

from claude_agent_sdk import ClaudeAgentOptions

options = ClaudeAgentOptions(
    enable_file_checkpointing=True,  # Allow rewind
    permission_mode="acceptEdits",
    model="sonnet",
    sandbox={"enabled": True}
)

Troubleshooting

Issue: Configuration not applied

Cause: Options passed after client already connected
Solution: Pass options to client constructor before connecting

Issue: Tools not available

Cause: Not in allowed_tools or in disallowed_tools
Solution: Add to allowed_tools, remove from disallowed_tools

Issue: Unexpected costs

Cause: No max_budget_usd or high max_turns
Solution: Set budget and turn limits

Issue: Permission prompts in automation

Cause: permission_mode="default"
Solution: Use "acceptEdits" or "bypassPermissions"

See Also

Install with Tessl CLI

npx tessl i tessl/pypi-claude-agent-sdk

docs

index.md

tile.json