| name | claude-agent-sdk |
| description | Build autonomous AI agents with Claude Agent SDK. Structured outputs (v0.1.45, Nov 2025) guarantee JSON schema validation, plugins system, hooks for event-driven workflows. Use when: building coding agents with validated JSON responses, SRE systems, security auditors, or troubleshooting CLI not found, structured output validation, session forking errors.
|
| license | MIT |
| metadata | {"version":"2.0.0","last_verified":"2025-11-22T00:00:00.000Z","package_version":"0.1.50","token_savings":"~70%","errors_prevented":12,"breaking_changes":"v0.1.45 - Structured outputs (Nov 2025), v0.1.0 - No default system prompt, settingSources required","keywords":["claude agent sdk","@anthropic-ai/claude-agent-sdk","structured outputs","json schema validation","outputFormat","query()","createSdkMcpServer","AgentDefinition","tool()","claude subagents","mcp servers","autonomous agents","plugins system","hooks system","session management","session forking","permissionMode","canUseTool","multi-agent orchestration","settingSources","CLI not found","context length exceeded","structured output validation","zod schema"]} |
Claude Agent SDK - Structured Outputs & Error Prevention Guide
Package: @anthropic-ai/claude-agent-sdk@0.1.50 (Nov 21, 2025)
Breaking Changes: v0.1.45 - Structured outputs (Nov 2025), v0.1.0 - No default system prompt, settingSources required
What's New in v0.1.45+ (Nov 2025)
Major Features:
1. Structured Outputs (v0.1.45, Nov 14, 2025)
- JSON schema validation - Guarantees responses match exact schemas
outputFormat parameter - Define output structure with JSON schema or Zod
- Access validated results - Via
message.structured_output
- Beta header required:
structured-outputs-2025-11-13
- Type safety - Full TypeScript inference with Zod schemas
Example:
import { query } from "@anthropic-ai/claude-agent-sdk";
import { z } from "zod";
const schema = z.object({
summary: z.string(),
sentiment: z.enum(['positive', 'neutral', 'negative']),
confidence: z.number().min(0).max(1)
});
const response = query({
prompt: "Analyze this code review feedback",
options: {
model: "claude-sonnet-4-5",
outputFormat: {
type: "json_schema",
json_schema: {
name: "AnalysisResult",
strict: true,
schema: zodToJsonSchema(schema)
}
}
}
});
for await (const message of response) {
if (message.type === 'result' && message.structured_output) {
const validated = schema.parse(message.structured_output);
console.log(`Sentiment: ${validated.sentiment}`);
}
}
2. Plugins System (v0.1.27)
plugins array - Load local plugin paths
- Custom plugin support - Extend agent capabilities
3. Hooks System (v0.1.0+)
- Event-driven callbacks - PreToolUse, PostToolUse, Notification, UserPromptSubmit
- Session event hooks - Monitor and control agent behavior
4. Additional Options
fallbackModel - Automatic model fallback on failures
maxThinkingTokens - Control extended thinking budget
strictMcpConfig - Strict MCP configuration validation
continue - Resume with new prompt (differs from resume)
permissionMode: 'plan' - New permission mode for planning workflows
š Docs: https://platform.claude.com/docs/en/agent-sdk/structured-outputs
The Complete Claude Agent SDK Reference
Table of Contents
- Core Query API
- Tool Integration
- MCP Servers
- Subagent Orchestration
- Session Management
- Permission Control
- Filesystem Settings
- Message Types & Streaming
- Error Handling
- Known Issues
Core Query API
Key signature:
query(prompt: string | AsyncIterable<SDKUserMessage>, options?: Options)
-> AsyncGenerator<SDKMessage>
Critical Options:
outputFormat - Structured JSON schema validation (v0.1.45+)
settingSources - Filesystem settings loading ('user'|'project'|'local')
canUseTool - Custom permission logic callback
agents - Programmatic subagent definitions
mcpServers - MCP server configuration
permissionMode - 'default'|'acceptEdits'|'bypassPermissions'|'plan'
Tool Integration (Built-in + Custom)
Tool Control:
allowedTools - Whitelist (takes precedence)
disallowedTools - Blacklist
canUseTool - Custom permission callback (see Permission Control section)
Built-in Tools: Read, Write, Edit, Bash, Grep, Glob, WebSearch, WebFetch, Task, NotebookEdit, BashOutput, KillBash, ListMcpResources, ReadMcpResource
MCP Servers (Model Context Protocol)
Server Types:
- In-process -
createSdkMcpServer() with tool() definitions
- External - stdio, HTTP, SSE transport
Tool Definition:
tool(name: string, description: string, zodSchema, handler)
Handler Return:
{ content: [{ type: "text", text: "..." }], isError?: boolean }
External MCP Servers (stdio)
const response = query({
prompt: "List files and analyze Git history",
options: {
mcpServers: {
"filesystem": {
command: "npx",
args: ["@modelcontextprotocol/server-filesystem"],
env: {
ALLOWED_PATHS: "/Users/developer/projects:/tmp"
}
},
"git": {
command: "npx",
args: ["@modelcontextprotocol/server-git"],
env: {
GIT_REPO_PATH: "/Users/developer/projects/my-repo"
}
}
},
allowedTools: [
"mcp__filesystem__list_files",
"mcp__filesystem__read_file",
"mcp__git__log",
"mcp__git__diff"
]
}
});
External MCP Servers (HTTP/SSE)
const response = query({
prompt: "Analyze data from remote service",
options: {
mcpServers: {
"remote-service": {
url: "https://api.example.com/mcp",
headers: {
"Authorization": "Bearer your-token-here",
"Content-Type": "application/json"
}
}
},
allowedTools: ["mcp__remote-service__analyze"]
}
});
MCP Tool Naming Convention
Format: mcp__<server-name>__<tool-name>
CRITICAL:
- Server name and tool name MUST match configuration
- Use double underscores (
__) as separators
- Include in
allowedTools array
Examples: mcp__weather-service__get_weather, mcp__filesystem__read_file
Subagent Orchestration
AgentDefinition Type
type AgentDefinition = {
description: string;
prompt: string;
tools?: string[];
model?: 'sonnet' | 'opus' | 'haiku' | 'inherit';
}
Field Details:
- description: When to use agent (used by main agent for delegation)
- prompt: System prompt (defines role, inherits main context)
- tools: Allowed tools (if omitted, inherits from main agent)
- model: Model override (
haiku/sonnet/opus/inherit)
Usage:
agents: {
"security-checker": {
description: "Security audits and vulnerability scanning",
prompt: "You check security. Scan for secrets, verify OWASP compliance.",
tools: ["Read", "Grep", "Bash"],
model: "sonnet"
}
}
Session Management
Options:
resume: sessionId - Continue previous session
forkSession: true - Create new branch from session
continue: prompt - Resume with new prompt (differs from resume)
Session Forking Pattern (Unique Capability):
const forked = query({
prompt: "Try GraphQL instead of REST",
options: {
resume: sessionId,
forkSession: true
}
});
Capture Session ID:
for await (const message of response) {
if (message.type === 'system' && message.subtype === 'init') {
sessionId = message.session_id;
}
}
Permission Control
Permission Modes:
type PermissionMode = "default" | "acceptEdits" | "bypassPermissions" | "plan";
default - Standard permission checks
acceptEdits - Auto-approve file edits
bypassPermissions - Skip ALL checks (use in CI/CD only)
plan - Planning mode (v0.1.45+)
Custom Permission Logic
const response = query({
prompt: "Deploy application to production",
options: {
permissionMode: "default",
canUseTool: async (toolName, input) => {
if (['Read', 'Grep', 'Glob'].includes(toolName)) {
return { behavior: "allow" };
}
if (toolName === 'Bash') {
const dangerous = ['rm -rf', 'dd if=', 'mkfs', '> /dev/'];
if (dangerous.some(pattern => input.command.includes(pattern))) {
return {
behavior: "deny",
message: "Destructive command blocked for safety"
};
}
}
if (input.command?.includes('deploy') || input.command?.includes('kubectl apply')) {
return {
behavior: "ask",
message: "Confirm deployment to production?"
};
}
return { behavior: "allow" };
}
}
});
canUseTool Callback
type CanUseToolCallback = (
toolName: string,
input: any
) => Promise<PermissionDecision>;
type PermissionDecision =
| { behavior: "allow" }
| { behavior: "deny"; message?: string }
| { behavior: "ask"; message?: string };
Examples:
canUseTool: async (toolName, input) => {
if (toolName === 'Write' || toolName === 'Edit') {
return { behavior: "deny", message: "No file modifications allowed" };
}
return { behavior: "allow" };
}
canUseTool: async (toolName, input) => {
const sensitivePaths = ['/etc/', '/root/', '.env', 'credentials.json'];
if ((toolName === 'Write' || toolName === 'Edit') &&
sensitivePaths.some(path => input.file_path?.includes(path))) {
return {
behavior: "ask",
message: `Modify sensitive file ${input.file_path}?`
};
}
return { behavior: "allow" };
}
canUseTool: async (toolName, input) => {
console.log(`Tool requested: ${toolName}`, input);
await logToDatabase(toolName, input);
return { behavior: "allow" };
}
Filesystem Settings
Setting Sources:
type SettingSource = 'user' | 'project' | 'local';
user - ~/.claude/settings.json (global)
project - .claude/settings.json (team-shared)
local - .claude/settings.local.json (gitignored overrides)
Default: NO settings loaded (settingSources: [])
Settings Priority
When multiple sources loaded, settings merge in this order (highest priority first):
- Programmatic options (passed to
query()) - Always win
- Local settings (
.claude/settings.local.json)
- Project settings (
.claude/settings.json)
- User settings (
~/.claude/settings.json)
Example:
{
"allowedTools": ["Read", "Write", "Edit"]
}
{
"allowedTools": ["Read"]
}
const response = query({
options: {
settingSources: ["project", "local"],
allowedTools: ["Read", "Grep"]
}
});
Best Practice: Use settingSources: ["project"] in CI/CD for consistent behavior.
Message Types & Streaming
Message Types:
system - Session init/completion (includes session_id)
assistant - Agent responses
tool_call - Tool execution requests
tool_result - Tool execution results
error - Error messages
result - Final result (includes structured_output for v0.1.45+)
Streaming Pattern:
for await (const message of response) {
if (message.type === 'system' && message.subtype === 'init') {
sessionId = message.session_id;
}
if (message.type === 'result' && message.structured_output) {
const validated = schema.parse(message.structured_output);
}
}
Error Handling
Error Codes:
| Error Code | Cause | Solution |
|---|
CLI_NOT_FOUND | Claude Code not installed | Install: npm install -g @anthropic-ai/claude-code |
AUTHENTICATION_FAILED | Invalid API key | Check ANTHROPIC_API_KEY env var |
RATE_LIMIT_EXCEEDED | Too many requests | Implement retry with backoff |
CONTEXT_LENGTH_EXCEEDED | Prompt too long | Use session compaction, reduce context |
PERMISSION_DENIED | Tool blocked | Check permissionMode, canUseTool |
TOOL_EXECUTION_FAILED | Tool error | Check tool implementation |
SESSION_NOT_FOUND | Invalid session ID | Verify session ID |
MCP_SERVER_FAILED | Server error | Check server configuration |
Known Issues Prevention
This skill prevents 12 documented issues:
Issue #1: CLI Not Found Error
Error: "Claude Code CLI not installed"
Source: SDK requires Claude Code CLI
Why It Happens: CLI not installed globally
Prevention: Install before using SDK: npm install -g @anthropic-ai/claude-code
Issue #2: Authentication Failed
Error: "Invalid API key"
Source: Missing or incorrect ANTHROPIC_API_KEY
Why It Happens: Environment variable not set
Prevention: Always set export ANTHROPIC_API_KEY="sk-ant-..."
Issue #3: Permission Denied Errors
Error: Tool execution blocked
Source: permissionMode restrictions
Why It Happens: Tool not allowed by permissions
Prevention: Use allowedTools or custom canUseTool callback
Issue #4: Context Length Exceeded
Error: "Prompt too long"
Source: Input exceeds model context window
Why It Happens: Large codebase, long conversations
Prevention: SDK auto-compacts, but reduce context if needed
Issue #5: Tool Execution Timeout
Error: Tool doesn't respond
Source: Long-running tool execution
Why It Happens: Tool takes too long (>5 minutes default)
Prevention: Implement timeout handling in tool implementations
Issue #6: Session Not Found
Error: "Invalid session ID"
Source: Session expired or invalid
Why It Happens: Session ID incorrect or too old
Prevention: Capture session_id from system init message
Issue #7: MCP Server Connection Failed
Error: Server not responding
Source: Server not running or misconfigured
Why It Happens: Command/URL incorrect, server crashed
Prevention: Test MCP server independently, verify command/URL
Issue #8: Subagent Definition Errors
Error: Invalid AgentDefinition
Source: Missing required fields
Why It Happens: description or prompt missing
Prevention: Always include description and prompt fields
Issue #9: Settings File Not Found
Error: "Cannot read settings"
Source: Settings file doesn't exist
Why It Happens: settingSources includes non-existent file
Prevention: Check file exists before including in sources
Issue #10: Tool Name Collision
Error: Duplicate tool name
Source: Multiple tools with same name
Why It Happens: Two MCP servers define same tool name
Prevention: Use unique tool names, prefix with server name
Issue #11: Zod Schema Validation Error
Error: Invalid tool input
Source: Input doesn't match Zod schema
Why It Happens: Agent provided wrong data type
Prevention: Use descriptive Zod schemas with .describe()
Issue #12: Filesystem Permission Denied
Error: Cannot access path
Source: Restricted filesystem access
Why It Happens: Path outside workingDirectory or no permissions
Prevention: Set correct workingDirectory, check file permissions
Official Documentation
Token Efficiency:
- Without skill: ~12,000 tokens (MCP setup, permission patterns, session forking, structured outputs, error handling)
- With skill: ~3,600 tokens (focused on v0.1.45+ features + error prevention + advanced patterns)
- Savings: ~70% (~8,400 tokens)
Errors prevented: 12 documented issues with exact solutions
Key value: Structured outputs (v0.1.45+), session forking, canUseTool patterns, settingSources priority, MCP naming, error codes
Last verified: 2025-11-22 | Skill version: 2.0.0 | Changes: Added v0.1.45 structured outputs, plugins, hooks, new options. Removed tutorial/basic examples (~750 lines). Focused on knowledge gaps + error prevention + advanced patterns.