Python SDK for programmatically interacting with Claude Code, enabling AI-powered automation workflows with support for bidirectional conversations, custom in-process tools, hooks, and fine-grained permission control
—
—
Does it follow best practices?
Run evals on this skill
Adds up to 20 points to the overall score
View guide
—
The risk profile of this skill
This plugin was archived by the owner on Jun 3, 2026
Reason: Retiring all tiles created prior to the transition to plugin support
The ClaudeAgentOptions dataclass provides comprehensive configuration for controlling Claude's behavior, permissions, tools, and execution environment. It's used with both the query() function and ClaudeSDKClient.
Configuration dataclass for customizing Claude SDK behavior including tool access, permissions, MCP servers, execution environment, and conversation settings.
@dataclass
class ClaudeAgentOptions:
"""
Query options for Claude SDK.
This dataclass provides comprehensive configuration for controlling Claude's
behavior, permissions, tools, and execution environment. All fields are optional
with sensible defaults.
Tool Control:
- allowed_tools: Explicit list of tool names Claude can use
- disallowed_tools: Explicit list of tool names Claude cannot use
- mcp_servers: MCP server configurations for custom tools
Permissions:
- permission_mode: Control how permissions are handled
- can_use_tool: Callback for custom permission logic
Conversation Control:
- continue_conversation: Continue from last conversation
- resume: Resume specific session by ID
- max_turns: Limit conversation length
- fork_session: Fork resumed sessions to new session ID
System Configuration:
- system_prompt: Custom system prompt or preset
- model: AI model to use
- cwd: Working directory for tool execution
- env: Environment variables
- settings: Settings configuration
- add_dirs: Additional directories for context
Advanced Features:
- hooks: Event hooks for custom logic
- agents: Custom agent definitions
- can_use_tool: Permission callback
- include_partial_messages: Enable streaming of partial messages
"""
allowed_tools: list[str] = field(default_factory=list)
"""List of tool names that Claude is allowed to use.
When specified, Claude can only use tools in this list. Useful for
restricting Claude to specific capabilities for security or workflow reasons.
Examples:
- ['Read', 'Bash'] - Only allow reading files and running bash commands
- ['Write', 'Edit'] - Only allow file modifications
- [] - No restrictions (default)
"""
system_prompt: str | SystemPromptPreset | None = None
"""Custom system prompt or preset configuration.
Can be either:
- A string with custom instructions
- A SystemPromptPreset dict to use a preset and optionally append text
- None to use default system prompt
Examples:
- "You are a Python expert who explains code clearly"
- {"type": "preset", "preset": "claude_code", "append": "Focus on security"}
"""
mcp_servers: dict[str, McpServerConfig] | str | Path = field(default_factory=dict)
"""MCP server configurations for custom tools.
Can be:
- A dictionary mapping server names to configurations
- A string path to MCP config file
- A Path object to MCP config file
- Empty dict for no custom servers (default)
See mcp-config.md for detailed configuration options.
"""
permission_mode: PermissionMode | None = None
"""Permission mode for tool execution.
Controls how Claude handles tool permissions:
- 'default': Prompt user for dangerous operations (default)
- 'acceptEdits': Auto-accept file edits, prompt for other dangerous ops
- 'plan': Generate plan without executing tools
- 'bypassPermissions': Allow all tools without prompting (use with caution)
"""
continue_conversation: bool = False
"""Whether to continue from the last conversation.
When True, continues the most recent conversation session. Maintains
all context from the previous session.
"""
resume: str | None = None
"""Session ID to resume.
Specify a session ID to resume a specific conversation. Session IDs
are included in ResultMessage objects.
"""
max_turns: int | None = None
"""Maximum number of conversation turns before stopping.
Limits the conversation length to prevent infinite loops or excessive
API usage. One turn = one user message + one assistant response.
"""
disallowed_tools: list[str] = field(default_factory=list)
"""List of tool names that Claude cannot use.
Explicitly prevents Claude from using specific tools even if they would
normally be available. Takes precedence over allowed_tools.
Examples:
- ['Bash'] - Prevent shell command execution
- ['Write', 'Edit', 'MultiEdit'] - Prevent file modifications
"""
model: str | None = None
"""AI model to use for the conversation.
Specify a Claude model identifier. If None, uses the default model.
Examples:
- 'claude-sonnet-4-5'
- 'claude-opus-4-1-20250805'
- 'claude-opus-4-20250514'
"""
permission_prompt_tool_name: str | None = None
"""Tool name to use for permission prompts.
When set, permission prompts will be sent as tool calls to this tool
instead of being handled by the SDK.
"""
cwd: str | Path | None = None
"""Working directory for tool execution.
All file operations and bash commands will be executed relative to
this directory. If None, uses current working directory.
"""
settings: str | None = None
"""Settings configuration.
JSON string or path to settings file for Claude Code configuration.
"""
add_dirs: list[str | Path] = field(default_factory=list)
"""Additional directories to add to Claude's context.
These directories will be available for Claude to explore and work with.
Useful for multi-directory projects.
"""
env: dict[str, str] = field(default_factory=dict)
"""Environment variables for tool execution.
These variables will be available to bash commands and tools executed
by Claude. Useful for providing API keys, configuration, etc.
Example:
{"API_KEY": "secret", "DEBUG": "true"}
"""
extra_args: dict[str, str | None] = field(default_factory=dict)
"""Arbitrary CLI flags to pass to Claude Code.
Advanced option for passing additional command-line flags not covered
by other options. Keys are flag names, values are flag values (or None
for boolean flags).
Example:
{"--verbose": None, "--timeout": "30"}
"""
max_buffer_size: int | None = None
"""Maximum bytes when buffering CLI stdout.
Limits memory usage when buffering output from the Claude Code CLI.
If None, uses default buffer size.
"""
debug_stderr: Any = sys.stderr
"""Deprecated: File-like object for debug output.
This field is deprecated. Use the stderr callback instead.
"""
stderr: Callable[[str], None] | None = None
"""Callback for stderr output from Claude Code CLI.
This function will be called with each line of stderr output from the
CLI process. Useful for logging or debugging.
Example:
lambda line: logging.debug(f"CLI: {line}")
"""
can_use_tool: CanUseTool | None = None
"""Custom tool permission callback.
When set, this async function is called before each tool execution to
determine if the tool should be allowed. Provides full control over
tool permissions.
See permissions.md for details.
"""
hooks: dict[HookEvent, list[HookMatcher]] | None = None
"""Hook configurations for custom event handling.
Hooks allow you to inject custom logic at specific points in Claude's
execution loop. Maps hook events to lists of matchers with callbacks.
See hooks.md for details.
"""
user: str | None = None
"""User identifier for the conversation.
Optional identifier for tracking conversations by user. Useful in
multi-user applications.
"""
include_partial_messages: bool = False
"""Enable streaming of partial message updates.
When True, the SDK will emit StreamEvent messages containing partial
content as it's generated. Useful for real-time UIs.
See messages.md for StreamEvent details.
"""
fork_session: bool = False
"""Fork resumed sessions to new session ID.
When True, resumed sessions will fork to a new session ID rather than
continuing the previous session. Useful for creating conversation branches.
"""
agents: dict[str, AgentDefinition] | None = None
"""Custom agent definitions.
Define custom agents with specific tools, prompts, and models. Maps
agent names to AgentDefinition objects.
See agents.md for details.
"""
setting_sources: list[SettingSource] | None = None
"""Setting sources to load.
Specify which setting files to load. Options:
- 'user': User-level settings
- 'project': Project-level settings
- 'local': Local settings
If None, uses default setting sources.
"""from claude_agent_sdk import ClaudeAgentOptions, query
options = ClaudeAgentOptions(
system_prompt="You are a Python expert",
allowed_tools=["Read", "Write", "Bash"],
permission_mode='acceptEdits',
cwd="/home/user/project"
)
async for msg in query(prompt="Analyze this codebase", options=options):
print(msg)from claude_agent_sdk import ClaudeAgentOptions, query
# Only allow read operations
options = ClaudeAgentOptions(
allowed_tools=["Read", "Glob", "Grep"],
disallowed_tools=["Write", "Edit", "Bash"]
)
async for msg in query(prompt="Search for TODO comments", options=options):
print(msg)from claude_agent_sdk import ClaudeAgentOptions, query
# Using a string
options = ClaudeAgentOptions(
system_prompt="""You are a security expert. When analyzing code:
1. Look for security vulnerabilities
2. Check for proper input validation
3. Verify authentication and authorization"""
)
# Using a preset with append
options = ClaudeAgentOptions(
system_prompt={
"type": "preset",
"preset": "claude_code",
"append": "Focus on performance optimization"
}
)from claude_agent_sdk import ClaudeAgentOptions, query, ResultMessage
# Start a conversation
options = ClaudeAgentOptions()
result = None
async for msg in query(prompt="Explain Python generators", options=options):
if isinstance(msg, ResultMessage):
result = msg
print(f"Session ID: {msg.session_id}")
# Continue the conversation
options.continue_conversation = True
async for msg in query(prompt="Can you show an example?", options=options):
print(msg)
# Resume a specific session
options.resume = result.session_id
options.continue_conversation = False
async for msg in query(prompt="What about async generators?", options=options):
print(msg)from claude_agent_sdk import ClaudeAgentOptions, create_sdk_mcp_server, tool
# Create custom tools
@tool("get_weather", "Get weather for a city", {"city": str})
async def get_weather(args):
return {"content": [{"type": "text", "text": f"Weather in {args['city']}: Sunny"}]}
# Create SDK MCP server
weather_server = create_sdk_mcp_server("weather", tools=[get_weather])
# Configure options
options = ClaudeAgentOptions(
mcp_servers={"weather": weather_server},
allowed_tools=["get_weather"]
)from pathlib import Path
from claude_agent_sdk import ClaudeAgentOptions, query
options = ClaudeAgentOptions(
cwd="/home/user/myproject",
env={
"DATABASE_URL": "postgresql://localhost/mydb",
"API_KEY": "secret_key",
"DEBUG": "true"
},
add_dirs=[
Path("/home/user/shared"),
Path("/home/user/libs")
]
)
async for msg in query(prompt="Run the database migration", options=options):
print(msg)from claude_agent_sdk import ClaudeAgentOptions, query
# Limit conversation to prevent runaway loops
options = ClaudeAgentOptions(
max_turns=5, # Stop after 5 back-and-forth exchanges
allowed_tools=["Bash"]
)
async for msg in query(
prompt="Fix all Python files in this directory",
options=options
):
print(msg)from claude_agent_sdk import ClaudeAgentOptions, query
# Use specific model
options = ClaudeAgentOptions(
model='claude-sonnet-4-5'
)
async for msg in query(prompt="Write a complex algorithm", options=options):
print(msg)from claude_agent_sdk import ClaudeAgentOptions, query, StreamEvent
options = ClaudeAgentOptions(
include_partial_messages=True
)
async for msg in query(prompt="Write a long essay", options=options):
if isinstance(msg, StreamEvent):
# Handle streaming content updates
print(f"Partial update: {msg.event}")from claude_agent_sdk import ClaudeAgentOptions, query, ResultMessage
# Get a session
session_id = None
async for msg in query(prompt="Explain decorators", options=ClaudeAgentOptions()):
if isinstance(msg, ResultMessage):
session_id = msg.session_id
# Fork the session to create a branch
options = ClaudeAgentOptions(
resume=session_id,
fork_session=True # Creates new session instead of continuing
)
async for msg in query(prompt="Now explain metaclasses", options=options):
if isinstance(msg, ResultMessage):
print(f"New session ID: {msg.session_id}") # Different from originalimport logging
from claude_agent_sdk import ClaudeAgentOptions, query
logging.basicConfig(level=logging.DEBUG)
options = ClaudeAgentOptions(
stderr=lambda line: logging.debug(f"Claude CLI: {line}")
)
async for msg in query(prompt="Hello", options=options):
print(msg)from claude_agent_sdk import ClaudeAgentOptions, AgentDefinition, query
# Define custom agents
options = ClaudeAgentOptions(
agents={
"reviewer": AgentDefinition(
description="Code review expert",
prompt="You are a code reviewer. Focus on best practices and bugs.",
tools=["Read", "Grep"],
model="sonnet"
),
"implementer": AgentDefinition(
description="Code implementation expert",
prompt="You are an implementation expert. Write clean, tested code.",
tools=["Read", "Write", "Edit", "Bash"],
model="sonnet"
)
}
)
async for msg in query(prompt="Review this code then implement fixes", options=options):
print(msg)from claude_agent_sdk import ClaudeAgentOptions, query
# Load only project and local settings, skip user settings
options = ClaudeAgentOptions(
setting_sources=["project", "local"]
)
async for msg in query(prompt="Use project configuration", options=options):
print(msg)from pathlib import Path
from claude_agent_sdk import ClaudeAgentOptions, query
options = ClaudeAgentOptions(
cwd="/home/user/main-project",
add_dirs=[
Path("/home/user/shared-utils"),
Path("/home/user/config"),
Path("/home/user/docs")
]
)
async for msg in query(
prompt="Analyze code in all these directories",
options=options
):
print(msg)from claude_agent_sdk import ClaudeAgentOptions, query
# Plan mode - generate plan without execution
plan_options = ClaudeAgentOptions(
permission_mode='plan'
)
async for msg in query(prompt="How would you refactor this?", options=plan_options):
print(msg)
# Accept edits mode - auto-accept file changes
edit_options = ClaudeAgentOptions(
permission_mode='acceptEdits',
allowed_tools=["Read", "Write", "Edit"]
)
async for msg in query(prompt="Implement the refactoring", options=edit_options):
print(msg)from pathlib import Path
from claude_agent_sdk import ClaudeAgentOptions, query
# Comprehensive configuration example
options = ClaudeAgentOptions(
# Tools
allowed_tools=["Read", "Write", "Edit", "Bash", "Grep", "Glob"],
disallowed_tools=["Bash.run_in_background"],
# Permissions
permission_mode='acceptEdits',
# System
system_prompt="You are a senior software engineer specializing in Python",
model='claude-sonnet-4-5',
# Environment
cwd="/home/user/project",
env={"ENVIRONMENT": "development", "LOG_LEVEL": "debug"},
add_dirs=[Path("/home/user/shared")],
# Session
max_turns=10,
continue_conversation=False,
# Advanced
include_partial_messages=True,
stderr=lambda line: print(f"[CLI] {line}"),
)
async for msg in query(
prompt="Build a REST API with FastAPI",
options=options
):
print(msg)docs