Claude Agent SDK (TypeScript) - Comprehensive Technical Guide
Latest: 0.2.128 | Updated: May 5, 2026
Claude Agent SDK (TypeScript) - Comprehensive Technical Guide
Section titled “Claude Agent SDK (TypeScript) - Comprehensive Technical Guide”Table of Contents
- Core Fundamentals
- Simple Agents
- Multi-Agent Systems
- Tools Integration
- Computer Use API
- Structured Output
- Model Context Protocol (MCP)
- Agentic Patterns
- Automatic Context Compaction
- Permissions System
- Session Management
- Context Engineering
- Production Essentials
- Tool Development
- Streaming and Real-Time
- TypeScript Patterns
- Project Setup
- Integration Patterns
- Advanced Topics
CORE FUNDAMENTALS
Section titled “CORE FUNDAMENTALS”Installation and Project Initialization
Section titled “Installation and Project Initialization”The Claude Agent SDK is the official TypeScript library for building autonomous AI agents powered by Claude models. Install it using npm or yarn:
npm install @anthropic-ai/claude-agent-sdkOr with yarn:
yarn add @anthropic-ai/claude-agent-sdkFor the latest version with beta features:
npm install @anthropic-ai/claude-agent-sdk@latestTypeScript Configuration and tsconfig.json Setup
Section titled “TypeScript Configuration and tsconfig.json Setup”Configure your TypeScript project for optimal compatibility with the Claude Agent SDK. Create or update your tsconfig.json with the following comprehensive configuration:
{ "compilerOptions": { "target": "ES2020", "module": "ESNext", "lib": ["ES2020"], "moduleResolution": "node", "strict": true, "esModuleInterop": true, "skipLibCheck": true, "forceConsistentCasingInFileNames": true, "resolveJsonModule": true, "declaration": true, "declarationMap": true, "sourceMap": true, "outDir": "./dist", "rootDir": "./src", "isolatedModules": true, "noEmit": false, "preserveConstEnums": true, "allowSyntheticDefaultImports": true, "strictNullChecks": true, "strictFunctionTypes": true, "strictBindCallApply": true, "strictPropertyInitialisation": true, "noImplicitThis": true, "alwaysStrict": true, "noUnusedLocals": true, "noUnusedParameters": true, "noImplicitReturns": true, "noFallthroughCasesInSwitch": true, "types": ["node"] }, "include": ["src/**/*"], "exclude": ["node_modules", "dist", "**/*.test.ts"]}This configuration ensures:
- Strict type checking for maximum type safety
- ES2020 target for modern JavaScript features
- Module support for both CommonJS and ESM environments
- Declaration files for TypeScript consumers
- Source maps for debugging
- Comprehensive error checking with noUnused* options
Evolution from Claude Code SDK to Claude Agent SDK
Section titled “Evolution from Claude Code SDK to Claude Agent SDK”The Claude Agent SDK represents the evolution and expansion of the Claude Code SDK. The transition reflects Anthropic’s shift towards a more generalised agent framework capable of handling diverse workflows beyond code-centric tasks.
Key Migration Points:
- Package Name Change:
@anthropic-ai/claude-code→@anthropic-ai/claude-agent-sdk - Enhanced Capabilities: Extended from code-focused operations to general automation, research, analysis, and system orchestration
- Improved Architecture: Built on a refined harness supporting multiple authentication backends (Claude API, Amazon Bedrock, Google Vertex AI)
- Better Type System: Enhanced TypeScript definitions with comprehensive generic support
- Advanced Features: Subagent orchestration, dynamic tool loading, enhanced context management
For existing Claude Code SDK users migrating to the Agent SDK:
// OLD - Claude Code SDKimport { code } from "@anthropic-ai/claude-code";
// NEW - Claude Agent SDKimport { query } from "@anthropic-ai/claude-agent-sdk";
// The query() function replaces code() with enhanced functionalityconst response = query({ prompt: "Your task here", options: { model: "claude-sonnet-4-5", // Additional configuration options }});
for await (const message of response) { // Process messages}Architecture Overview: Built on Claude Code’s Harness
Section titled “Architecture Overview: Built on Claude Code’s Harness”The Claude Agent SDK is constructed upon the proven agent harness that powers Claude Code, Anthropic’s terminal-based AI coding assistant. This architecture provides:
Foundation Components:
- Agent Execution Engine: Manages the core agent loop, handling message processing, tool invocations, and response generation
- Context Management System: Sophisticated handling of conversation context with automatic compaction for extended interactions (supports 200K token context window)
- Tool Execution Framework: Coordinates execution of built-in tools (file operations, command execution, web search) and custom MCP tools
- Permission Layer: Fine-grained access control system enabling developers to define security boundaries
- Session State Manager: Maintains conversation state, enabling session resumption and forking
Key Architectural Principles:
- Streaming-First Design: All interactions support real-time streaming for responsive user experiences
- Type Safety: Complete TypeScript support with Zod schema integration for runtime validation
- Modularity: Extensible tool system supporting custom tools via Model Context Protocol (MCP)
- Resilience: Automatic error recovery, context compaction, and graceful degradation
- Observability: Built-in support for monitoring, logging, and audit trails
Core Concepts Explained
Section titled “Core Concepts Explained”Agents: Autonomous entities that interpret user instructions, reason about tasks, and execute actions. Agents maintain state throughout a session and can coordinate with other agents for complex workflows. Each agent instance has its own context, permissions, and execution environment.
// Conceptual agent representationinterface Agent { id: string; name: string; model: string; systemPrompt: string; context: ConversationMessage[]; permissions: PermissionPolicy; tools: ToolDefinition[]; sessionId?: string;}Tools: Capabilities that agents can invoke to perform actions. The SDK includes built-in tools (Read, Write, Edit, Delete, Bash, WebSearch, Grep, Glob) and supports custom tools via MCP integration. Tools have:
- Input Schemas: Zod schemas defining parameters
- Output Contracts: Type-safe return value specifications
- Permission Requirements: Access control specifications
- Error Handling: Graceful failure modes
Context: The accumulated state of an agent session, including:
- Previous messages (user and assistant)
- Tool execution history
- Current working directory
- Environment variables
- File system state
- Conversation metadata
The SDK automatically manages context to stay within token limits through intelligent compaction.
Sessions: Individual instances of agent-user interaction. Sessions maintain all context necessary to resume conversations. Key session features:
- Session ID: Unique identifier for resumption
- State Persistence: Capability to pause and resume
- Forking: Create alternative conversation branches
- Isolation: Sessions don’t interfere with each other
Permissions: Access control policies defining what actions agents can perform. The permission system supports:
- Global Modes: acceptEdits, default, bypassPermissions
- Per-Tool Policies: Custom rules for specific tools
- Permission Callbacks: Dynamic permission evaluation
- Audit Logging: Track all permission decisions
Model Configuration and Selection
Section titled “Model Configuration and Selection”The Claude Agent SDK supports multiple Claude models, each optimised for different use cases:
Available Models:
type SupportedModel = | 'claude-opus' | 'claude-sonnet-4-5' | 'claude-3-5-sonnet' | 'claude-3-5-haiku' | 'claude-4-turbo' // When available | 'claude-3-opus';
interface ModelConfiguration { model: SupportedModel; maxTokens?: number; // Max output tokens temperature?: number; // 0-1, default 1.0 topP?: number; // Top-p sampling, 0-1 topK?: number; // Top-k sampling}Model Selection Guide:
-
Claude 4.5 Sonnet (Recommended for most use cases):
- Superior reasoning for complex tasks
- Best performance on multi-step reasoning
- Excellent tool use and planning
- Recommended context window: Full 200K tokens
const options: ModelConfiguration = {model: 'claude-sonnet-4-5',maxTokens: 8192,temperature: 1.0}; -
Claude 3.5 Sonnet (Balanced performance):
- Strong reasoning with lower latency
- Good for code generation and analysis
- Cost-effective for most workloads
const options: ModelConfiguration = {model: 'claude-3-5-sonnet',maxTokens: 4096,temperature: 0.8}; -
Claude 3.5 Haiku (Fast, lightweight):
- Fastest response times
- Lower token costs
- Suitable for simple tasks and streaming
const options: ModelConfiguration = {model: 'claude-3-5-haiku',maxTokens: 2048,temperature: 1.0}; -
Claude Opus (High capability):
- Maximum reasoning capability
- Best for extremely complex problems
- Higher latency and cost
const options: ModelConfiguration = {model: 'claude-opus',maxTokens: 8192,temperature: 0.7};
API Key Setup and Authentication
Section titled “API Key Setup and Authentication”Secure API key management is critical for production deployments.
Environment-Based Setup (Recommended):
# .env fileANTHROPIC_API_KEY=sk-ant-...your-key-here...
# Export for shell sessionexport ANTHROPIC_API_KEY="sk-ant-...your-key-here..."
# Windows PowerShell$env:ANTHROPIC_API_KEY="sk-ant-...your-key-here..."TypeScript Implementation:
import { query } from '@anthropic-ai/claude-agent-sdk';import dotenv from 'dotenv';
// Load environment variablesdotenv.config();
// Access API key from environmentconst apiKey = process.env.ANTHROPIC_API_KEY;
if (!apiKey) { throw new Error('ANTHROPIC_API_KEY environment variable not set');}
// Use in queriesconst response = query({ prompt: 'Analyse this codebase', options: { model: 'claude-sonnet-4-5', apiKey: apiKey // Optional: defaults to env var if not provided }});Advanced Authentication Patterns:
// Type-safe API key managementclass ApiKeyManager { private static instance: ApiKeyManager; private apiKey: string;
private constructor() { this.apiKey = this.loadApiKey(); }
private loadApiKey(): string { const envKey = process.env.ANTHROPIC_API_KEY; if (!envKey) { throw new Error( 'ANTHROPIC_API_KEY not found. ' + 'Set it in your environment or .env file' ); } return envKey; }
static getInstance(): ApiKeyManager { if (!ApiKeyManager.instance) { ApiKeyManager.instance = new ApiKeyManager(); } return ApiKeyManager.instance; }
getApiKey(): string { return this.apiKey; }
validateApiKey(): boolean { // Validate key format return this.apiKey.startsWith('sk-ant-') && this.apiKey.length > 20; }}
// Usageconst keyManager = ApiKeyManager.getInstance();if (!keyManager.validateApiKey()) { throw new Error('Invalid API key format');}Alternative Authentication Methods:
// Amazon Bedrock Authenticationconst bedrockResponse = query({ prompt: 'Your task', options: { model: 'claude-sonnet-4-5', auth: { type: 'bedrock', region: 'us-west-2', credentials: { accessKeyId: process.env.AWS_ACCESS_KEY_ID, secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY } } }});
// Google Vertex AI Authenticationconst vertexResponse = query({ prompt: 'Your task', options: { model: 'claude-sonnet-4-5', auth: { type: 'vertex', projectId: process.env.GOOGLE_PROJECT_ID, region: 'us-central1' } }});SDK Initialization Patterns with TypeScript
Section titled “SDK Initialization Patterns with TypeScript”Basic Initialization:
import { query } from '@anthropic-ai/claude-agent-sdk';
// Simplest initialization - uses environment variablesconst response = query({ prompt: 'Analyse this code for security vulnerabilities'});
for await (const message of response) { console.log(message);}Comprehensive Initialization with Full Type Safety:
import { query } from '@anthropic-ai/claude-agent-sdk';import type { QueryOptions, QueryMessage, QueryResponse, PermissionMode, ToolDefinition} from '@anthropic-ai/claude-agent-sdk';
interface AgentConfig { model: string; systemPrompt: string; temperature: number; maxTokens: number; permissionMode: PermissionMode; workingDirectory: string;}
class ClaudeAgentInitializer { private config: AgentConfig;
constructor(config: Partial<AgentConfig> = {}) { this.config = { model: config.model ?? 'claude-sonnet-4-5', systemPrompt: config.systemPrompt ?? 'You are a helpful assistant.', temperature: config.temperature ?? 1.0, maxTokens: config.maxTokens ?? 4096, permissionMode: config.permissionMode ?? 'default', workingDirectory: config.workingDirectory ?? process.cwd() }; }
async initializeAgent(prompt: string): Promise<AsyncGenerator<QueryMessage>> { const options: QueryOptions = { model: this.config.model, systemPrompt: this.config.systemPrompt, temperature: this.config.temperature, maxTokens: this.config.maxTokens, permissionMode: this.config.permissionMode, workingDirectory: this.config.workingDirectory };
return query({ prompt: prompt, options: options }); }
updateConfig(updates: Partial<AgentConfig>): void { this.config = { ...this.config, ...updates }; }}
// Usageconst agentInit = new ClaudeAgentInitializer({ model: 'claude-sonnet-4-5', systemPrompt: 'You are an expert TypeScript developer', temperature: 0.7, workingDirectory: './projects/my-app'});
const agentStream = await agentInit.initializeAgent( 'Refactor the authentication module');
for await (const message of agentStream) { console.log(message);}Factory Pattern Initialization:
import { query } from '@anthropic-ai/claude-agent-sdk';
type AgentType = 'code-review' | 'security-audit' | 'documentation' | 'testing';
class AgentFactory { private static templates: Record<AgentType, string> = { 'code-review': `You are an expert code reviewer. Provide constructive feedback on: - Code quality and maintainability - Design patterns and SOLID principles - Performance optimisations - Security considerations - Test coverage`,
'security-audit': `You are a security expert specialising in: - Vulnerability identification - Authentication and authorisation - Data protection and encryption - Access control - Security best practices`,
'documentation': `You are a technical writer focused on: - Clear, comprehensive documentation - API documentation - Usage examples - Architecture diagrams - Best practices guides`,
'testing': `You are a QA specialist experienced in: - Test coverage analysis - Edge case identification - Integration testing - Performance testing - Test automation` };
static createAgent(type: AgentType, prompt: string) { const systemPrompt = this.templates[type];
return query({ prompt: prompt, options: { model: 'claude-sonnet-4-5', systemPrompt: systemPrompt, temperature: 0.8 } }); }}
// Usageconst codeReviewStream = AgentFactory.createAgent( 'code-review', 'Review this authentication service for issues');
const securityStream = AgentFactory.createAgent( 'security-audit', 'Audit the payment processing system');
const docStream = AgentFactory.createAgent( 'documentation', 'Create API documentation for the user service');
const testStream = AgentFactory.createAgent( 'testing', 'Develop comprehensive test cases for the database layer');Type Definitions and Interfaces
Section titled “Type Definitions and Interfaces”The Claude Agent SDK provides comprehensive TypeScript definitions ensuring type safety throughout your applications.
Core Type Definitions:
// Message types for agent communicationinterface Message { type: 'assistant' | 'user' | 'system' | 'tool_call' | 'tool_result' | 'error'; content?: string | MessageContent[]; id?: string; timestamp?: number;}
interface MessageContent { type: 'text' | 'tool_use' | 'tool_result' | 'image'; text?: string; name?: string; id?: string; input?: Record<string, unknown>; result?: string; image_url?: string; media_type?: 'image/jpeg' | 'image/png' | 'image/gif' | 'image/webp';}
interface SystemMessage extends Message { type: 'system'; subtype?: 'init' | 'completion' | 'subagent_start' | 'subagent_end'; session_id?: string; skills?: string[]; cost?: number;}
// Query configurationinterface QueryOptions { model?: SupportedModel; systemPrompt?: string; temperature?: number; maxTokens?: number; maxBudgetUsd?: number; permissionMode?: PermissionMode; workingDirectory?: string; apiKey?: string; resume?: string; forkSession?: boolean; canUseTool?: ToolPermissionCallback; mcpServers?: Record<string, McpServerConfig>; allowedTools?: string[]; agents?: Record<string, SubagentConfig>; settingSources?: Array<'user' | 'project' | 'local'>; plugins?: PluginDefinition[];}
type PermissionMode = 'acceptEdits' | 'default' | 'bypassPermissions';
type ToolPermissionCallback = ( toolName: string, input: Record<string, unknown>) => Promise<PermissionDecision>;
interface PermissionDecision { behavior: 'allow' | 'deny' | 'ask'; message?: string;}
// Session and budget informationinterface SessionInfo { id: string; startTime: number; endTime?: number; messageCount: number; tokenUsage: TokenUsage; costUsd: number;}
interface TokenUsage { inputTokens: number; outputTokens: number; cacheCreationInputTokens?: number; cacheReadInputTokens?: number; totalTokens: number;}
// Tool definitionsinterface ToolDefinition { name: string; description: string; inputSchema: Record<string, unknown>; outputType?: string; errorHandler?: (error: Error) => string;}
// MCP server configurationinterface McpServerConfig { command?: string; args?: string[]; env?: Record<string, string>; url?: string; headers?: Record<string, string>;}
// Subagent configurationinterface SubagentConfig { description: string; prompt: string; tools?: string[]; model?: SupportedModel; temperature?: number;}
// Plugin systeminterface PluginDefinition { name: string; version: string; initialize?: (context: PluginContext) => Promise<void>; onToolCall?: (toolName: string, input: unknown) => Promise<void>; onMessage?: (message: Message) => Promise<void>; destroy?: () => Promise<void>;}
interface PluginContext { agent: Agent; sessionId: string; [key: string]: unknown;}Advanced Type Patterns:
// Generic types for extensibilitytype MessageHandler<T extends Message = Message> = (message: T) => void | Promise<void>;
type AsyncMessageGenerator<T extends Message = Message> = AsyncGenerator<T, void, void>;
// Type-safe tool responseinterface ToolResponse<T = unknown> { success: boolean; data?: T; error?: { code: string; message: string; details?: Record<string, unknown>; }; metadata?: { executionTime: number; tokenUsage?: TokenUsage; tools?: string[]; };}
// Type-safe event emitter for agent eventstype AgentEventMap = { 'session-start': { sessionId: string }; 'session-end': { sessionId: string; duration: number }; 'tool-call': { toolName: string; input: unknown }; 'tool-result': { toolName: string; result: unknown }; 'error': { error: Error; context: string }; 'message': { message: Message }; 'permission-check': { tool: string; decision: PermissionDecision };};
type AgentEventEmitter = { on<K extends keyof AgentEventMap>(event: K, handler: (data: AgentEventMap[K]) => void): void; off<K extends keyof AgentEventMap>(event: K, handler: (data: AgentEventMap[K]) => void): void; emit<K extends keyof AgentEventMap>(event: K, data: AgentEventMap[K]): void;};SIMPLE AGENTS
Section titled “SIMPLE AGENTS”Creating Basic Claude Agents in TypeScript
Section titled “Creating Basic Claude Agents in TypeScript”Creating a basic Claude agent involves initialising the SDK with a prompt and processing the async stream of responses.
Minimal Agent Example:
import { query } from '@anthropic-ai/claude-agent-sdk';
async function basicAgent() { // Start a simple query const response = query({ prompt: 'What are the benefits of TypeScript for large-scale projects?' });
// Process streaming responses for await (const message of response) { if (message.type === 'assistant') { console.log('Agent Response:', message.content); } }}
basicAgent();Practical Agent Implementation:
import { query } from '@anthropic-ai/claude-agent-sdk';
interface AgentOptions { model?: string; temperature?: number; workingDirectory?: string;}
class SimpleAgent { private model: string; private temperature: number; private workingDirectory: string;
constructor(options: AgentOptions = {}) { this.model = options.model ?? 'claude-sonnet-4-5'; this.temperature = options.temperature ?? 1.0; this.workingDirectory = options.workingDirectory ?? process.cwd(); }
async execute(prompt: string): Promise<string> { const response = query({ prompt: prompt, options: { model: this.model, temperature: this.temperature, workingDirectory: this.workingDirectory } });
let result = '';
for await (const message of response) { if (message.type === 'assistant') { result += message.content; console.log(message.content); } else if (message.type === 'tool_call') { console.log(`Tool called: ${message.tool_name}`); } else if (message.type === 'error') { console.error('Error:', message.error); throw new Error(`Agent error: ${message.error}`); } }
return result; }}
// Usageconst agent = new SimpleAgent({ model: 'claude-sonnet-4-5', temperature: 0.8, workingDirectory: './projects/myapp'});
try { const result = await agent.execute( 'Analyse the performance characteristics of async/await in TypeScript' ); console.log('Final Result:', result);} catch (error) { console.error('Agent execution failed:', error);}System Prompts and Instructions
Section titled “System Prompts and Instructions”System prompts guide the agent’s behaviour and define its personality, expertise, and approach to tasks.
System Prompt Design:
import { query } from '@anthropic-ai/claude-agent-sdk';
// Professional system prompts for different roles
const systemPrompts = { codeReviewer: `You are an expert senior software engineer specialising in code review.Your responsibilities:- Identify potential bugs and security vulnerabilities- Suggest performance optimisations- Recommend design pattern improvements- Ensure adherence to SOLID principles- Provide constructive, actionable feedback- Consider edge cases and error handling
Always provide:1. Summary of findings2. Severity levels (critical, high, medium, low)3. Specific code examples4. Remediation steps with code samples`,
securityAuditor: `You are a cybersecurity expert with deep experience in:- Web application security- API security- Authentication and authorisation mechanisms- Data protection and encryption- Infrastructure security- Compliance requirements
When auditing, always examine:1. Authentication vulnerabilities2. Authorisation flaws3. Input validation gaps4. SQL injection and XSS vulnerabilities5. Sensitive data exposure6. Security misconfigurations7. Insecure dependencies
Provide risk ratings and remediation guidance.`,
architectureAdvisor: `You are a solutions architect with expertise in:- Microservices design- Event-driven architectures- Scalability patterns- High availability and disaster recovery- Technology selection- Cost optimisation
For architecture reviews, analyse:1. Component decomposition2. Communication patterns3. Data consistency strategies4. Failure modes and resilience5. Scaling capabilities6. Operational complexity`,
performanceOptimiser: `You are a performance engineering expert specialising in:- Algorithm analysis and optimisation- Memory management- Database query optimisation- Caching strategies- Async patterns- Monitoring and profiling
When optimising:1. Identify bottlenecks with data2. Analyse algorithmic complexity3. Profile memory usage4. Suggest targeted improvements5. Estimate performance gains6. Consider trade-offs`};
// Use specific system promptsasync function executeSpecialisedAgent(role: keyof typeof systemPrompts, task: string) { const response = query({ prompt: task, options: { model: 'claude-sonnet-4-5', systemPrompt: systemPrompts[role], temperature: 0.7 } });
for await (const message of response) { if (message.type === 'assistant') { console.log(message.content); } }}
// UsageexecuteSpecialisedAgent('codeReviewer', `Review this TypeScript implementation:\`\`\`typescriptasync function fetchUserData(userId: string) { const response = await fetch(\`/api/users/\${userId}\`); const data = await response.json(); return data;}\`\`\``);Dynamic System Prompt Construction:
import { query } from '@anthropic-ai/claude-agent-sdk';
interface PromptContext { expertise: string[]; constraints: string[]; outputFormat: string; tone: string; focusAreas: string[];}
function constructSystemPrompt(context: PromptContext): string { const expertiseSection = context.expertise.length > 0 ? `Your areas of expertise:\n${context.expertise.map(e => `- ${e}`).join('\n')}` : '';
const constraintsSection = context.constraints.length > 0 ? `\nConstraints to follow:\n${context.constraints.map(c => `- ${c}`).join('\n')}` : '';
const focusSection = context.focusAreas.length > 0 ? `\nFocus areas for this analysis:\n${context.focusAreas.map(f => `- ${f}`).join('\n')}` : '';
const toneSection = `\nCommunication tone: ${context.tone}`;
const outputSection = `\nOutput format: ${context.outputFormat}`;
return `You are an AI assistant with specialised knowledge and expertise.
${expertiseSection}${constraintsSection}${focusSection}${toneSection}${outputSection}
Provide thorough, well-reasoned responses with specific examples.`;}
// Usageconst reviewContext: PromptContext = { expertise: [ 'TypeScript and advanced type systems', 'React and component architecture', 'Node.js and backend development', 'Testing strategies and frameworks' ], constraints: [ 'Follow SOLID principles', 'Consider backwards compatibility', 'Optimise for readability', 'Minimise external dependencies' ], outputFormat: 'Structured markdown with code examples', tone: 'Professional but approachable', focusAreas: [ 'Type safety and generics', 'Error handling patterns', 'Performance implications', 'Maintainability' ]};
const systemPrompt = constructSystemPrompt(reviewContext);
const response = query({ prompt: 'Review this authentication implementation', options: { systemPrompt: systemPrompt, model: 'claude-sonnet-4-5' }});Single-Task Agent Execution
Section titled “Single-Task Agent Execution”Execute focused agents that complete specific tasks without multi-turn conversation.
import { query } from '@anthropic-ai/claude-agent-sdk';
interface TaskExecutionResult { success: boolean; output: string; executionTime: number; tokensUsed?: number;}
class SingleTaskExecutor { async execute(prompt: string, timeoutMs: number = 30000): Promise<TaskExecutionResult> { const startTime = performance.now(); let output = ''; let tokensUsed = 0;
try { // Create a timeout promise const timeoutPromise = new Promise<never>((_, reject) => { setTimeout(() => reject(new Error('Task execution timeout')), timeoutMs); });
const executePromise = (async () => { const response = query({ prompt: prompt, options: { model: 'claude-sonnet-4-5', maxTokens: 4096 } });
for await (const message of response) { if (message.type === 'assistant') { output += message.content; } else if (message.type === 'error') { throw new Error(`Task error: ${message.error}`); } } })();
await Promise.race([executePromise, timeoutPromise]);
const executionTime = performance.now() - startTime;
return { success: true, output, executionTime, tokensUsed }; } catch (error) { const executionTime = performance.now() - startTime;
return { success: false, output: output || '', executionTime, tokensUsed }; } }}
// Usageconst executor = new SingleTaskExecutor();
const result = await executor.execute( 'Generate a TypeScript interface definition for a user object with type-safe methods', 30000);
console.log(`Task completed in ${result.executionTime}ms`);console.log(`Success: ${result.success}`);console.log(`Output:\n${result.output}`);Synchronous and Asynchronous Patterns with async/await
Section titled “Synchronous and Asynchronous Patterns with async/await”The Claude Agent SDK uses async/await throughout for handling asynchronous operations.
Async Pattern Fundamentals:
import { query } from '@anthropic-ai/claude-agent-sdk';
// Basic async/await patternasync function basicAsyncAgent() { try { const response = query({ prompt: 'Explain closures in JavaScript' });
// Process all messages for await (const message of response) { if (message.type === 'assistant') { console.log('Response:', message.content); } } } catch (error) { console.error('Error:', error); }}
// Sequential execution of multiple tasksasync function sequentialTasks() { console.log('Starting task 1...');
const task1Response = query({ prompt: 'Design a database schema for an e-commerce platform' });
let task1Output = ''; for await (const message of task1Response) { if (message.type === 'assistant') { task1Output += message.content; } }
console.log('Task 1 complete. Starting task 2...');
const task2Response = query({ prompt: `Based on this schema: ${task1Output}, generate SQL migrations` });
let task2Output = ''; for await (const message of task2Response) { if (message.type === 'assistant') { task2Output += message.content; } }
console.log('All tasks complete'); return { task1: task1Output, task2: task2Output };}
// Parallel execution of independent tasksasync function parallelTasks() { const task1 = (async () => { const response = query({ prompt: 'Explain microservices architecture' }); let output = ''; for await (const message of response) { if (message.type === 'assistant') output += message.content; } return output; })();
const task2 = (async () => { const response = query({ prompt: 'Explain event-driven architecture' }); let output = ''; for await (const message of response) { if (message.type === 'assistant') output += message.content; } return output; })();
const task3 = (async () => { const response = query({ prompt: 'Explain serverless architecture' }); let output = ''; for await (const message of response) { if (message.type === 'assistant') output += message.content; } return output; })();
// Wait for all tasks to complete const [arch1, arch2, arch3] = await Promise.all([task1, task2, task3]);
return { microservices: arch1, eventDriven: arch2, serverless: arch3 };}
// Race pattern - use first resultasync function racePattern() { const task1 = query({ prompt: 'Quick analysis' }); const task2 = query({ prompt: 'Quick analysis' });
const fastestResponse = await Promise.race([task1, task2]);
return fastestResponse;}
// Allsettled for robustnessasync function robustParallelExecution() { const tasks = [ (async () => { const response = query({ prompt: 'Task 1' }); return response; })(), (async () => { const response = query({ prompt: 'Task 2' }); return response; })(), (async () => { const response = query({ prompt: 'Task 3' }); return response; })() ];
const results = await Promise.allSettled(tasks);
results.forEach((result, index) => { if (result.status === 'fulfilled') { console.log(`Task ${index + 1} succeeded`); } else { console.log(`Task ${index + 1} failed: ${result.reason}`); } });
return results;}Streaming Responses with SSE (Server-Sent Events)
Section titled “Streaming Responses with SSE (Server-Sent Events)”The Claude Agent SDK streams responses in real-time, allowing for responsive user interfaces and progressive output handling.
Streaming Response Processing:
import { query } from '@anthropic-ai/claude-agent-sdk';
// Basic streamingasync function streamResponses() { const response = query({ prompt: 'Generate a detailed TypeScript style guide', options: { model: 'claude-sonnet-4-5', maxTokens: 8192 } });
for await (const message of response) { switch (message.type) { case 'assistant': // Process text responses immediately process.stdout.write(message.content); break;
case 'tool_call': console.log(`\n[Tool Call: ${message.tool_name}]`); break;
case 'tool_result': console.log(`\n[Tool Result: ${message.result}]\n`); break;
case 'error': console.error(`\n[Error: ${message.error}]\n`); break; } }}
// Buffered streaming for structured processingclass StreamBufferer { private buffer: string = ''; private flushInterval: number; private timer?: NodeJS.Timeout;
constructor(flushIntervalMs: number = 1000) { this.flushInterval = flushIntervalMs; }
async processStream( prompt: string, onFlush: (data: string) => void ): Promise<string> { const response = query({ prompt });
return new Promise((resolve, reject) => { this.scheduleFlush(onFlush);
(async () => { try { for await (const message of response) { if (message.type === 'assistant') { this.buffer += message.content; } }
this.flush(onFlush); resolve(this.buffer); } catch (error) { reject(error); } })(); }); }
private scheduleFlush(onFlush: (data: string) => void): void { this.timer = setInterval(() => { if (this.buffer.length > 0) { this.flush(onFlush); } }, this.flushInterval); }
private flush(onFlush: (data: string) => void): void { if (this.buffer.length > 0) { onFlush(this.buffer); this.buffer = ''; } }}
// Line-by-line streamingasync function lineByLineStreaming(prompt: string) { const response = query({ prompt }); let currentLine = '';
for await (const message of response) { if (message.type === 'assistant') { for (const char of message.content) { if (char === '\n') { console.log(`Line: ${currentLine}`); currentLine = ''; } else { currentLine += char; } } } }
if (currentLine) { console.log(`Final line: ${currentLine}`); }}
// Token counting with streamingasync function countTokensInStream(prompt: string): Promise<number> { const response = query({ prompt }); let tokenCount = 0;
for await (const message of response) { if (message.type === 'assistant') { // Rough estimate: average 4 chars per token tokenCount += Math.ceil(message.content.length / 4); } }
return tokenCount;}Token Usage Tracking
Section titled “Token Usage Tracking”Monitor token consumption for cost management and optimisation.
import { query } from '@anthropic-ai/claude-agent-sdk';
interface TokenMetrics { inputTokens: number; outputTokens: number; cacheCreationTokens: number; cacheReadTokens: number; totalTokens: number; estimatedCostUsd: number;}
class TokenTracker { private metrics: TokenMetrics = { inputTokens: 0, outputTokens: 0, cacheCreationTokens: 0, cacheReadTokens: 0, totalTokens: 0, estimatedCostUsd: 0 };
// Pricing per model (as of 2024) private pricing = { 'claude-sonnet-4-5': { input: 0.003, output: 0.015, cacheCreation: 0.00375, cacheRead: 0.0003 }, 'claude-3-5-sonnet': { input: 0.003, output: 0.015, cacheCreation: 0.00375, cacheRead: 0.0003 }, 'claude-opus': { input: 0.015, output: 0.075, cacheCreation: 0.01875, cacheRead: 0.0015 }, 'claude-3-5-haiku': { input: 0.00008, output: 0.0004, cacheCreation: 0.0001, cacheRead: 0.00001 } };
async trackQuery( prompt: string, model: keyof typeof this.pricing = 'claude-sonnet-4-5' ): Promise<{ result: string; metrics: TokenMetrics }> { const response = query({ prompt, options: { model } });
let result = ''; const localMetrics: TokenMetrics = { inputTokens: 0, outputTokens: 0, cacheCreationTokens: 0, cacheReadTokens: 0, totalTokens: 0, estimatedCostUsd: 0 };
for await (const message of response) { if (message.type === 'assistant') { result += message.content; // Count approximate tokens localMetrics.outputTokens += Math.ceil(message.content.length / 4); } }
// Estimate input tokens localMetrics.inputTokens = Math.ceil(prompt.length / 4); localMetrics.totalTokens = localMetrics.inputTokens + localMetrics.outputTokens + localMetrics.cacheCreationTokens + localMetrics.cacheReadTokens;
// Calculate cost const prices = this.pricing[model]; localMetrics.estimatedCostUsd = (localMetrics.inputTokens * prices.input) / 1000 + (localMetrics.outputTokens * prices.output) / 1000 + (localMetrics.cacheCreationTokens * prices.cacheCreation) / 1000 + (localMetrics.cacheReadTokens * prices.cacheRead) / 1000;
// Update cumulative metrics this.metrics.inputTokens += localMetrics.inputTokens; this.metrics.outputTokens += localMetrics.outputTokens; this.metrics.totalTokens += localMetrics.totalTokens; this.metrics.estimatedCostUsd += localMetrics.estimatedCostUsd;
return { result, metrics: localMetrics }; }
getMetrics(): TokenMetrics { return { ...this.metrics }; }
resetMetrics(): void { this.metrics = { inputTokens: 0, outputTokens: 0, cacheCreationTokens: 0, cacheReadTokens: 0, totalTokens: 0, estimatedCostUsd: 0 }; }
printMetrics(): void { console.log('Token Usage Metrics:'); console.log(`Input Tokens: ${this.metrics.inputTokens}`); console.log(`Output Tokens: ${this.metrics.outputTokens}`); console.log(`Cache Creation Tokens: ${this.metrics.cacheCreationTokens}`); console.log(`Cache Read Tokens: ${this.metrics.cacheReadTokens}`); console.log(`Total Tokens: ${this.metrics.totalTokens}`); console.log(`Estimated Cost: $${this.metrics.estimatedCostUsd.toFixed(4)}`); }}
// Usageconst tracker = new TokenTracker();
const { result, metrics } = await tracker.trackQuery( 'Explain the theory of relativity');
console.log(result);console.log(`This query used ${metrics.totalTokens} tokens`);console.log(`Estimated cost: $${metrics.estimatedCostUsd.toFixed(4)}`);Error Handling with try-catch
Section titled “Error Handling with try-catch”Robust error handling ensures applications gracefully manage failures.
import { query } from '@anthropic-ai/claude-agent-sdk';
// Error typesclass AgentError extends Error { constructor( public code: string, message: string, public details?: Record<string, unknown> ) { super(message); this.name = 'AgentError'; }}
class AuthenticationError extends AgentError { constructor(message: string = 'Authentication failed') { super('AUTH_ERROR', message); this.name = 'AuthenticationError'; }}
class PermissionError extends AgentError { constructor(tool: string) { super('PERMISSION_DENIED', `Permission denied for tool: ${tool}`, { tool }); this.name = 'PermissionError'; }}
class TimeoutError extends AgentError { constructor(timeoutMs: number) { super('TIMEOUT', `Operation timed out after ${timeoutMs}ms`, { timeoutMs }); this.name = 'TimeoutError'; }}
class BudgetExceededError extends AgentError { constructor(spent: number, limit: number) { super('BUDGET_EXCEEDED', `Budget exceeded: $${spent} > $${limit}`, { spent, limit }); this.name = 'BudgetExceededError'; }}
// Comprehensive error handlingasync function robustAgentExecution(prompt: string, budgetLimit: number = 5.0) { try { const response = query({ prompt, options: { model: 'claude-sonnet-4-5', maxBudgetUsd: budgetLimit } });
let output = ''; let totalCost = 0;
for await (const message of response) { switch (message.type) { case 'assistant': output += message.content; break;
case 'tool_call': console.log(`Executing tool: ${message.tool_name}`); break;
case 'tool_result': console.log(`Tool completed: ${message.tool_name}`); break;
case 'error': if (message.error.type === 'PERMISSION_DENIED') { throw new PermissionError(message.error.tool); } else if (message.error.type === 'AUTHENTICATION_FAILED') { throw new AuthenticationError(message.error.message); } else if (message.error.type === 'BUDGET_EXCEEDED') { throw new BudgetExceededError( message.error.spent, budgetLimit ); } else { throw new AgentError( message.error.type, message.error.message, message.error.details ); } break;
case 'system': if (message.cost) { totalCost += message.cost; if (totalCost > budgetLimit * 0.8) { console.warn(`Budget warning: ${(totalCost / budgetLimit * 100).toFixed(1)}% used`); } } break; } }
return { success: true, output, totalCost };
} catch (error) { if (error instanceof AuthenticationError) { console.error('Authentication failed. Check your API key.'); console.error(`Details: ${error.message}`); throw error; }
if (error instanceof PermissionError) { console.error(`Access denied to tool: ${error.details?.tool}`); throw error; }
if (error instanceof BudgetExceededError) { console.error(`Budget limit exceeded: $${error.details?.spent} spent`); throw error; }
if (error instanceof TimeoutError) { console.error(`Operation timed out after ${error.details?.timeoutMs}ms`); throw error; }
if (error instanceof Error) { console.error(`Unexpected error: ${error.message}`); throw error; }
console.error('Unknown error occurred'); throw error; }}
// Retry logic with exponential backoffasync function executeWithRetry( prompt: string, maxRetries: number = 3, initialDelayMs: number = 1000): Promise<string> { let lastError: Error | null = null;
for (let attempt = 0; attempt < maxRetries; attempt++) { try { const response = query({ prompt }); let output = '';
for await (const message of response) { if (message.type === 'assistant') { output += message.content; } }
return output; } catch (error) { lastError = error as Error;
if (attempt < maxRetries - 1) { const delayMs = initialDelayMs * Math.pow(2, attempt); console.log(`Retry attempt ${attempt + 1} after ${delayMs}ms...`); await new Promise(resolve => setTimeout(resolve, delayMs)); } } }
throw new Error(`Failed after ${maxRetries} attempts: ${lastError?.message}`);}
// Usagetry { const result = await robustAgentExecution( 'Analyse the authentication module', 10.0 ); console.log(result.output);} catch (error) { if (error instanceof AgentError) { console.error(`Agent error (${error.code}): ${error.message}`); }}Type-Safe Response Handling
Section titled “Type-Safe Response Handling”Ensure responses are properly typed and validated.
import { query } from '@anthropic-ai/claude-agent-sdk';import { z } from 'zod';
// Type-safe response wrapperinterface TypedResponse<T> { data: T; raw: string; metadata: { model: string; tokensUsed: number; };}
// Response schema validationconst CodeReviewSchema = z.object({ issues: z.array(z.object({ severity: z.enum(['critical', 'high', 'medium', 'low']), file: z.string(), line: z.number(), description: z.string(), suggestion: z.string() })), summary: z.string(), scoreOut100: z.number().min(0).max(100)});
type CodeReview = z.infer<typeof CodeReviewSchema>;
// Generic response handlerclass ResponseHandler<T> { constructor(private schema: z.ZodType<T>) {}
async parseResponse(prompt: string): Promise<TypedResponse<T>> { const response = query({ prompt: prompt, options: { model: 'claude-sonnet-4-5' } });
let rawContent = '';
for await (const message of response) { if (message.type === 'assistant') { rawContent += message.content; } }
// Parse JSON from response const jsonMatch = rawContent.match(/```json\n([\s\S]*?)\n```/); const jsonString = jsonMatch ? jsonMatch[1] : rawContent;
const parsed = JSON.parse(jsonString); const validated = this.schema.parse(parsed);
return { data: validated, raw: rawContent, metadata: { model: 'claude-sonnet-4-5', tokensUsed: Math.ceil(rawContent.length / 4) } }; }}
// Usage exampleconst codeReviewHandler = new ResponseHandler(CodeReviewSchema);
const review = await codeReviewHandler.parseResponse(`Review this TypeScript code:\`\`\`typescriptasync function fetchUser(id: string) { const response = await fetch(\`/api/users/\${id}\`); const user = await response.json(); return user;}\`\`\`
Respond with JSON in this format:\`\`\`json{ "issues": [...], "summary": "...", "scoreOut100": ...}\`\`\``);
console.log('Code Review:');console.log(`Score: ${review.data.scoreOut100}/100`);console.log(`Summary: ${review.data.summary}`);console.log('Issues:');review.data.issues.forEach(issue => { console.log(`- [${issue.severity}] ${issue.description}`); console.log(` Suggestion: ${issue.suggestion}`);});MULTI-AGENT SYSTEMS
Section titled “MULTI-AGENT SYSTEMS”Multi-Agent Orchestration Patterns
Section titled “Multi-Agent Orchestration Patterns”Multi-agent orchestration enables complex task decomposition and parallel execution across specialised agents.
import { query } from '@anthropic-ai/claude-agent-sdk';import type { Message } from '@anthropic-ai/claude-agent-sdk';
// Agent specialisation registryconst agentSpecialisations = { researcher: { description: 'Research and information gathering', systemPrompt: `You are a research specialist. Your role is to:- Gather comprehensive information- Identify reliable sources- Summarise key findings- Highlight gaps in knowledge
Format findings as structured data.` }, analyst: { description: 'Data analysis and insights', systemPrompt: `You are a data analyst. Your role is to:- Analyse gathered data- Identify patterns and trends- Draw meaningful conclusions- Provide statistical insights
Base analysis on provided data.` }, strategist: { description: 'Strategic planning and recommendations', systemPrompt: `You are a strategic advisor. Your role is to:- Develop strategies based on analysis- Identify opportunities- Mitigate risks- Provide actionable recommendations
Think strategically and consider long-term implications.` }, implementer: { description: 'Implementation and execution planning', systemPrompt: `You are an implementation specialist. Your role is to:- Design implementation roadmaps- Break down strategies into tasks- Estimate timelines and resources- Identify dependencies
Provide detailed, actionable execution plans.` }};
interface OrchestrationResult { agentName: string; output: string; status: 'completed' | 'failed'; error?: string;}
class MultiAgentOrchestrator { async executeAgentSequence( initialPrompt: string, agentSequence: Array<keyof typeof agentSpecialisations> ): Promise<OrchestrationResult[]> { const results: OrchestrationResult[] = []; let contextCarry = initialPrompt;
for (const agentType of agentSequence) { const agentConfig = agentSpecialisations[agentType];
try { const agentPrompt = `Context from previous steps:\n${contextCarry}\n\n${agentConfig.description}`;
const response = query({ prompt: agentPrompt, options: { model: 'claude-sonnet-4-5', systemPrompt: agentConfig.systemPrompt, temperature: 0.7 } });
let output = ''; for await (const message of response) { if (message.type === 'assistant') { output += message.content; } }
results.push({ agentName: agentType, output, status: 'completed' });
contextCarry = output; } catch (error) { results.push({ agentName: agentType, output: '', status: 'failed', error: String(error) }); } }
return results; }
async executeAgentParallel( basePrompt: string, agents: Array<keyof typeof agentSpecialisations> ): Promise<OrchestrationResult[]> { const promises = agents.map(agentType => this.executeAgent(basePrompt, agentType) );
return Promise.all(promises); }
private async executeAgent( prompt: string, agentType: keyof typeof agentSpecialisations ): Promise<OrchestrationResult> { const agentConfig = agentSpecialisations[agentType];
try { const response = query({ prompt, options: { model: 'claude-sonnet-4-5', systemPrompt: agentConfig.systemPrompt, temperature: 0.7 } });
let output = ''; for await (const message of response) { if (message.type === 'assistant') { output += message.content; } }
return { agentName: agentType, output, status: 'completed' }; } catch (error) { return { agentName: agentType, output: '', status: 'failed', error: String(error) }; } }}
// Usageconst orchestrator = new MultiAgentOrchestrator();
// Sequential executionconst sequentialResults = await orchestrator.executeAgentSequence( 'Develop a comprehensive strategy for expanding into the European market', ['researcher', 'analyst', 'strategist', 'implementer']);
// Parallel executionconst parallelResults = await orchestrator.executeAgentParallel( 'What are the best practices for microservices architecture?', ['researcher', 'analyst', 'strategist']);
// Print resultsconsole.log('Sequential Execution Results:');sequentialResults.forEach(result => { console.log(`\n${result.agentName}: ${result.status}`); console.log(result.output.substring(0, 500) + '...');});Agent Coordination and Delegation
Section titled “Agent Coordination and Delegation”Implement sophisticated coordination patterns between agents with delegation capabilities.
import { query } from '@anthropic-ai/claude-agent-sdk';
interface Task { id: string; description: string; priority: 'high' | 'medium' | 'low'; complexity: 'simple' | 'moderate' | 'complex'; assignedAgent?: string; status: 'pending' | 'in_progress' | 'completed' | 'failed'; output?: string; dependencies?: string[];}
interface AgentCapabilities { name: string; expertise: string[]; currentLoad: number; maxConcurrent: number;}
class TaskDelegationManager { private tasks: Map<string, Task> = new Map(); private agents: Map<string, AgentCapabilities> = new Map(); private executionHistory: Array<{ taskId: string; duration: number; result: string }> = [];
registerAgent(agent: AgentCapabilities): void { this.agents.set(agent.name, agent); }
async delegateTask(task: Task): Promise<void> { // Find suitable agent const suitableAgent = this.findSuitableAgent(task);
if (!suitableAgent) { throw new Error(`No suitable agent found for task: ${task.id}`); }
task.assignedAgent = suitableAgent.name; task.status = 'in_progress'; this.tasks.set(task.id, task);
// Update agent load suitableAgent.currentLoad++;
try { const startTime = Date.now();
const response = query({ prompt: `Task: ${task.description}`, options: { model: 'claude-sonnet-4-5', systemPrompt: `You are specialised in: ${suitableAgent.expertise.join(', ')}` } });
let output = ''; for await (const message of response) { if (message.type === 'assistant') { output += message.content; } }
const duration = Date.now() - startTime;
task.status = 'completed'; task.output = output;
this.executionHistory.push({ taskId: task.id, duration, result: output });
console.log(`Task ${task.id} completed by ${suitableAgent.name} in ${duration}ms`); } catch (error) { task.status = 'failed'; task.output = String(error); console.error(`Task ${task.id} failed:`, error); } finally { suitableAgent.currentLoad--; } }
private findSuitableAgent(task: Task): AgentCapabilities | null { let bestAgent: AgentCapabilities | null = null; let bestMatch = -1;
for (const agent of this.agents.values()) { // Check if agent is available if (agent.currentLoad >= agent.maxConcurrent) { continue; }
// Calculate match score const matchScore = agent.expertise.filter(exp => task.description.toLowerCase().includes(exp.toLowerCase()) ).length;
if (matchScore > bestMatch) { bestMatch = matchScore; bestAgent = agent; } }
return bestAgent; }
async executeDependencyChain(tasks: Task[]): Promise<Map<string, Task>> { const taskMap = new Map<string, Task>(tasks.map(t => [t.id, t])); const executed = new Set<string>();
while (executed.size < tasks.length) { for (const task of tasks) { if (executed.has(task.id)) continue;
// Check if dependencies are met const dependenciesMet = !task.dependencies || task.dependencies.every(depId => executed.has(depId));
if (dependenciesMet) { await this.delegateTask(task); executed.add(task.id); } } }
return taskMap; }
getExecutionMetrics(): { totalTasks: number; completedTasks: number; failedTasks: number; averageExecutionTime: number; } { const completed = Array.from(this.tasks.values()) .filter(t => t.status === 'completed'); const failed = Array.from(this.tasks.values()) .filter(t => t.status === 'failed');
const totalDuration = this.executionHistory.reduce((sum, h) => sum + h.duration, 0); const averageExecutionTime = this.executionHistory.length > 0 ? totalDuration / this.executionHistory.length : 0;
return { totalTasks: this.tasks.size, completedTasks: completed.length, failedTasks: failed.length, averageExecutionTime }; }}
// Usageconst delegationManager = new TaskDelegationManager();
// Register agentsdelegationManager.registerAgent({ name: 'backend-specialist', expertise: ['API', 'database', 'authentication', 'performance'], currentLoad: 0, maxConcurrent: 3});
delegationManager.registerAgent({ name: 'frontend-specialist', expertise: ['UI', 'component', 'styling', 'accessibility'], currentLoad: 0, maxConcurrent: 2});
delegationManager.registerAgent({ name: 'devops-specialist', expertise: ['deployment', 'infrastructure', 'monitoring', 'security'], currentLoad: 0, maxConcurrent: 2});
// Create and delegate tasksconst tasks: Task[] = [ { id: 'task1', description: 'Design REST API endpoints for user management', priority: 'high', complexity: 'moderate', status: 'pending' }, { id: 'task2', description: 'Build React components for user dashboard', priority: 'high', complexity: 'moderate', status: 'pending', dependencies: ['task1'] }, { id: 'task3', description: 'Set up Docker containers and CI/CD pipeline', priority: 'medium', complexity: 'complex', status: 'pending' }];
// Execute with dependency trackingfor (const task of tasks) { await delegationManager.delegateTask(task);}
// Print metricsconst metrics = delegationManager.getExecutionMetrics();console.log('Execution Metrics:', metrics);(continuing in next section due to length…)
TOOLS INTEGRATION
Section titled “TOOLS INTEGRATION”Rich Tool Ecosystem Overview
Section titled “Rich Tool Ecosystem Overview”The Claude Agent SDK provides a comprehensive suite of built-in tools for file operations, code execution, web search, bash commands, and more.
Built-In Tools Available:
- Read: Read file contents
- Write: Create or overwrite files
- Edit: Modify specific sections of files
- Delete: Remove files and directories
- Bash: Execute bash commands
- Grep: Search file contents with regex
- Glob: Match files by pattern
- WebSearch: Search the internet
- Computer Use API: Control mouse, keyboard, screen (advanced)
Tool Availability and Usage:
import { query } from '@anthropic-ai/claude-agent-sdk';
const response = query({ prompt: 'List all TypeScript files, read package.json, and search for imports', options: { model: 'claude-sonnet-4-5', workingDirectory: './src', // Agent automatically selects appropriate tools // Can be restricted with allowedTools option allowedTools: ['Read', 'Glob', 'Grep'] }});
for await (const message of response) { if (message.type === 'tool_call') { console.log(`Tool: ${message.tool_name}, Input:`, message.input); } else if (message.type === 'tool_result') { console.log(`Result:`, message.result); }}Tool() Function with Zod Schemas
Section titled “Tool() Function with Zod Schemas”Create custom tools with type-safe parameter validation.
import { tool, createSdkMcpServer } from '@anthropic-ai/claude-agent-sdk';import { z } from 'zod';
// Custom tool with Zod schemaconst calculateTaxTool = tool( 'calculate_tax', 'Calculate tax amount based on income and jurisdiction', { amount: z.number().positive().describe('Gross income amount'), jurisdiction: z.enum(['US', 'UK', 'CA', 'AU']).describe('Tax jurisdiction'), filingStatus: z.enum(['single', 'married', 'head_of_household']).optional(), year: z.number().int().min(2020).max(2030).default(2024) }, async (args) => { // Tax calculation logic const taxRates = { US: 0.22, UK: 0.20, CA: 0.25, AU: 0.37 };
const rate = taxRates[args.jurisdiction]; const taxAmount = args.amount * rate;
return { content: [{ type: 'text', text: `Tax calculation for ${args.jurisdiction}:\nGross: $${args.amount}\nTax Rate: ${(rate * 100).toFixed(1)}%\nTax Amount: $${taxAmount.toFixed(2)}` }] }; });
// Tool with complex Zod schemaconst databaseQueryTool = tool( 'query_database', 'Execute a database query and return results', { query: z.string().describe('SQL query to execute'), parameters: z.record(z.any()).optional().describe('Query parameters'), timeout: z.number().int().positive().default(30000).describe('Query timeout in ms'), returnFormat: z.enum(['json', 'csv', 'table']).default('json'), limit: z.number().int().min(1).max(10000).default(100) }, async (args) => { // Database query logic return { content: [{ type: 'text', text: `Query executed: ${args.query}\nFormat: ${args.returnFormat}\nLimit: ${args.limit}` }] }; });
// Tool for external API callsconst apiCallTool = tool( 'call_external_api', 'Make HTTP requests to external APIs', { url: z.string().url().describe('API endpoint URL'), method: z.enum(['GET', 'POST', 'PUT', 'DELETE', 'PATCH']).default('GET'), headers: z.record(z.string()).optional().describe('HTTP headers'), body: z.record(z.any()).optional().describe('Request body (for POST/PUT)'), auth: z.object({ type: z.enum(['bearer', 'basic', 'api_key']), credentials: z.string() }).optional(), timeout: z.number().int().positive().default(10000) }, async (args) => { try { const headers: Record<string, string> = args.headers || {};
if (args.auth) { if (args.auth.type === 'bearer') { headers['Authorization'] = `Bearer ${args.auth.credentials}`; } else if (args.auth.type === 'basic') { headers['Authorization'] = `Basic ${Buffer.from(args.auth.credentials).toString('base64')}`; } else if (args.auth.type === 'api_key') { headers['X-API-Key'] = args.auth.credentials; } }
const controller = new AbortController(); const timeoutId = setTimeout(() => controller.abort(), args.timeout);
const response = await fetch(args.url, { method: args.method, headers, body: args.body ? JSON.stringify(args.body) : undefined, signal: controller.signal });
clearTimeout(timeoutId);
const data = await response.json();
return { content: [{ type: 'text', text: `Response (${response.status}):\n${JSON.stringify(data, null, 2)}` }] }; } catch (error) { return { content: [{ type: 'text', text: `API call failed: ${error.message}` }], isError: true }; } });
// Create MCP server with custom toolsconst customToolsServer = createSdkMcpServer({ name: 'business-tools', version: '1.0.0', tools: [ calculateTaxTool, databaseQueryTool, apiCallTool ]});
// Use in queryconst response = query({ prompt: 'Calculate tax for $100,000 income in the US, query user database, and call the weather API', options: { mcpServers: { 'business-tools': customToolsServer }, allowedTools: [ 'mcp__business-tools__calculate_tax', 'mcp__business-tools__query_database', 'mcp__business-tools__call_external_api' ], model: 'claude-sonnet-4-5' }});
for await (const message of response) { if (message.type === 'tool_call') { console.log(`Calling ${message.tool_name} with:`, message.input); }}File Operations (Read, Write, Edit, Delete)
Section titled “File Operations (Read, Write, Edit, Delete)”Work with the file system programmatically.
import { query } from '@anthropic-ai/claude-agent-sdk';
// File operations through agent promptsasync function fileOperations() { const response = query({ prompt: `1. Read package.json2. Create a new configuration file config.ts with TypeScript interfaces3. Edit README.md to add installation instructions4. List all .ts files in the src directory `, options: { model: 'claude-sonnet-4-5', workingDirectory: './my-project', allowedTools: ['Read', 'Write', 'Edit', 'Glob'] } });
for await (const message of response) { if (message.type === 'tool_call') { console.log(`\nTool: ${message.tool_name}`); console.log('Input:', message.input); } else if (message.type === 'tool_result') { console.log('Result:', message.result.substring(0, 200)); } }}
// Programmatic file operation wrapperclass FileManager { constructor(private workingDirectory: string) {}
async readFile(filePath: string): Promise<string> { const prompt = `Read the file: ${filePath}`;
const response = query({ prompt, options: { workingDirectory: this.workingDirectory, allowedTools: ['Read'] } });
let content = ''; for await (const message of response) { if (message.type === 'tool_result') { content += message.result; } }
return content; }
async writeFile(filePath: string, content: string): Promise<void> { const prompt = `Create or overwrite the file ${filePath} with this content:\n\n${content}`;
const response = query({ prompt, options: { workingDirectory: this.workingDirectory, allowedTools: ['Write'] } });
for await (const message of response) { if (message.type === 'tool_result') { console.log(`File written: ${filePath}`); } } }
async editFile(filePath: string, oldContent: string, newContent: string): Promise<void> { const prompt = `Edit ${filePath}.Find this section:\`\`\`${oldContent}\`\`\`
Replace it with:\`\`\`${newContent}\`\`\` `;
const response = query({ prompt, options: { workingDirectory: this.workingDirectory, allowedTools: ['Edit'] } });
for await (const message of response) { if (message.type === 'tool_result') { console.log(`File edited: ${filePath}`); } } }
async deleteFile(filePath: string): Promise<void> { const prompt = `Delete the file or directory: ${filePath}`;
const response = query({ prompt, options: { workingDirectory: this.workingDirectory, allowedTools: ['Delete'] } });
for await (const message of response) { if (message.type === 'tool_result') { console.log(`File deleted: ${filePath}`); } } }
async listFiles(pattern: string): Promise<string[]> { const prompt = `List all files matching the pattern: ${pattern}`;
const response = query({ prompt, options: { workingDirectory: this.workingDirectory, allowedTools: ['Glob'] } });
let files: string[] = []; for await (const message of response) { if (message.type === 'tool_result') { files = message.result.split('\n').filter(f => f.trim()); } }
return files; }}
// Usageconst fileManager = new FileManager('./projects/myapp');
const packageJson = await fileManager.readFile('package.json');console.log('Package.json content:', packageJson);
await fileManager.writeFile('config.ts', `export interface Config { port: number; host: string; environment: 'dev' | 'prod';}`);
const files = await fileManager.listFiles('*.ts');console.log('TypeScript files:', files);Bash Command Execution
Section titled “Bash Command Execution”Execute system commands and shell scripts.
import { query } from '@anthropic-ai/claude-agent-sdk';
// Execute bash commands through agentasync function bashExecution() { const response = query({ prompt: `1. Check the current Node.js version2. List the node_modules directory3. Show git status4. Count total lines of TypeScript code `, options: { model: 'claude-sonnet-4-5', workingDirectory: './my-project', allowedTools: ['Bash'], permissionMode: 'default' } });
for await (const message of response) { if (message.type === 'tool_call') { console.log(`\nExecuting: ${message.input.command}`); } else if (message.type === 'tool_result') { console.log('Output:', message.result); } }}
// Shell command wrapperclass ShellExecutor { constructor(private workingDirectory: string) {}
async execute(command: string): Promise<string> { const prompt = `Execute this shell command: ${command}`;
const response = query({ prompt, options: { workingDirectory: this.workingDirectory, allowedTools: ['Bash'], permissionMode: 'default' } });
let output = ''; for await (const message of response) { if (message.type === 'tool_result') { output += message.result; } }
return output; }
async runTests(): Promise<string> { return this.execute('npm test'); }
async buildProject(): Promise<string> { return this.execute('npm run build'); }
async runLinter(): Promise<string> { return this.execute('npm run lint'); }
async checkGitStatus(): Promise<string> { return this.execute('git status'); }
async getDependencyTree(): Promise<string> { return this.execute('npm list --depth=2'); }
async analyzeCodeMetrics(): Promise<string> { return this.execute('find src -name "*.ts" -type f | wc -l'); }}
// Usageconst executor = new ShellExecutor('./projects/myapp');
const testOutput = await executor.runTests();console.log('Test Results:', testOutput);
const gitStatus = await executor.checkGitStatus();console.log('Git Status:', gitStatus);
const buildOutput = await executor.buildProject();console.log('Build Output:', buildOutput);(Continuing with Web Search, Custom Tools, Error Handling, etc. - document continues with extensive examples…)
COMPUTER USE API
Section titled “COMPUTER USE API”Mouse Control and Automation
Section titled “Mouse Control and Automation”The Computer Use API enables sophisticated UI automation through mouse control.
import { query } from '@anthropic-ai/claude-agent-sdk';
interface MouseAction { type: 'move' | 'click' | 'drag'; x: number; y: number; button?: 'left' | 'right' | 'middle'; doubleClick?: boolean;}
class MouseAutomation { async moveMouseTo(x: number, y: number): Promise<void> { const prompt = `Move the mouse cursor to coordinates (${x}, ${y})`;
const response = query({ prompt, options: { model: 'claude-sonnet-4-5' } });
for await (const message of response) { if (message.type === 'tool_call' && message.tool_name === 'ComputerUse') { console.log('Moving mouse to', { x, y }); } } }
async clickAtCoordinates(x: number, y: number, button: string = 'left'): Promise<void> { const prompt = `Click at coordinates (${x}, ${y}) with the ${button} mouse button`;
const response = query({ prompt, options: { model: 'claude-sonnet-4-5' } });
for await (const message of response) { if (message.type === 'tool_call' && message.tool_name === 'ComputerUse') { console.log('Clicking at', { x, y, button }); } } }
async dragMouse(fromX: number, fromY: number, toX: number, toY: number): Promise<void> { const prompt = `Drag the mouse from (${fromX}, ${fromY}) to (${toX}, ${toY})`;
const response = query({ prompt, options: { model: 'claude-sonnet-4-5' } });
for await (const message of response) { if (message.type === 'tool_call' && message.tool_name === 'ComputerUse') { console.log('Dragging mouse', { from: { x: fromX, y: fromY }, to: { x: toX, y: toY } }); } } }
async doubleClick(x: number, y: number): Promise<void> { const prompt = `Double-click at coordinates (${x}, ${y})`;
const response = query({ prompt, options: { model: 'claude-sonnet-4-5' } });
for await (const message of response) { if (message.type === 'tool_call' && message.tool_name === 'ComputerUse') { console.log('Double-clicking at', { x, y }); } } }}
// Usageconst mouse = new MouseAutomation();
await mouse.moveMouseTo(1920 / 2, 1080 / 2);await mouse.clickAtCoordinates(960, 540, 'left');await mouse.dragMouse(100, 100, 500, 500);await mouse.doubleClick(500, 500);Keyboard Input Simulation
Section titled “Keyboard Input Simulation”Simulate keyboard input for UI automation.
import { query } from '@anthropic-ai/claude-agent-sdk';
class KeyboardAutomation { async typeText(text: string): Promise<void> { const prompt = `Type the following text: "${text}"`;
const response = query({ prompt, options: { model: 'claude-sonnet-4-5' } });
for await (const message of response) { if (message.type === 'tool_call' && message.tool_name === 'ComputerUse') { console.log('Typing:', text); } } }
async pressKey(key: string): Promise<void> { const prompt = `Press the ${key} key`;
const response = query({ prompt, options: { model: 'claude-sonnet-4-5' } });
for await (const message of response) { if (message.type === 'tool_call' && message.tool_name === 'ComputerUse') { console.log('Pressing key:', key); } } }
async pressKeySequence(keys: string[]): Promise<void> { const prompt = `Press these keys in sequence: ${keys.join(', ')}`;
const response = query({ prompt, options: { model: 'claude-sonnet-4-5' } });
for await (const message of response) { if (message.type === 'tool_call' && message.tool_name === 'ComputerUse') { console.log('Pressing keys:', keys); } } }
async hotkey(modifiers: string[], key: string): Promise<void> { const combinedKey = `${modifiers.join('+')}+${key}`; const prompt = `Press the hotkey: ${combinedKey}`;
const response = query({ prompt, options: { model: 'claude-sonnet-4-5' } });
for await (const message of response) { if (message.type === 'tool_call' && message.tool_name === 'ComputerUse') { console.log('Hotkey:', combinedKey); } } }
async selectAll(): Promise<void> { await this.hotkey(['Control'], 'a'); }
async copy(): Promise<void> { await this.hotkey(['Control'], 'c'); }
async paste(): Promise<void> { await this.hotkey(['Control'], 'v'); }
async undo(): Promise<void> { await this.hotkey(['Control'], 'z'); }
async redo(): Promise<void> { await this.hotkey(['Control', 'Shift'], 'z'); }
async save(): Promise<void> { await this.hotkey(['Control'], 's'); }
async find(): Promise<void> { await this.hotkey(['Control'], 'f'); }}
// Usageconst keyboard = new KeyboardAutomation();
await keyboard.typeText('Hello, World!');await keyboard.pressKey('Enter');await keyboard.hotkey(['Control'], 'a');await keyboard.hotkey(['Control'], 'c');await keyboard.save();Screen Interaction and Vision
Section titled “Screen Interaction and Vision”Use screen capture and vision capabilities for UI understanding.
import { query } from '@anthropic-ai/claude-agent-sdk';
interface ScreenElement { type: string; text?: string; location: { x: number; y: number; width: number; height: number }; clickable: boolean;}
class ScreenInteraction { async captureScreen(): Promise<string> { const prompt = 'Take a screenshot of the current screen';
const response = query({ prompt, options: { model: 'claude-sonnet-4-5' } });
let screenshot = ''; for await (const message of response) { if (message.type === 'tool_result') { screenshot = message.result; } }
return screenshot; }
async analyzeScreen(): Promise<ScreenElement[]> { const prompt = `Capture the screen and analyse it. Identify all clickable elements:- Buttons- Links- Input fields- Menu items
For each element, provide:1. Type of element2. Text label3. Location (x, y, width, height)4. Whether it's clickable
Return as JSON array. `;
const response = query({ prompt, options: { model: 'claude-sonnet-4-5' } });
let result = ''; for await (const message of response) { if (message.type === 'assistant') { result += message.content; } }
// Parse JSON response const jsonMatch = result.match(/```json\n([\s\S]*?)\n```/); if (jsonMatch) { return JSON.parse(jsonMatch[1]); }
return []; }
async findElement(description: string): Promise<ScreenElement | null> { const prompt = `Capture the screen and find the element matching this description: "${description}"Return the location and details as JSON: { type, text, location: { x, y, width, height }, clickable } `;
const response = query({ prompt, options: { model: 'claude-sonnet-4-5' } });
let result = ''; for await (const message of response) { if (message.type === 'assistant') { result += message.content; } }
const jsonMatch = result.match(/```json\n([\s\S]*?)\n```/); if (jsonMatch) { return JSON.parse(jsonMatch[1]); }
return null; }
async waitForElement(description: string, timeoutMs: number = 5000): Promise<ScreenElement | null> { const startTime = Date.now();
while (Date.now() - startTime < timeoutMs) { const element = await this.findElement(description); if (element) { return element; }
await new Promise(resolve => setTimeout(resolve, 500)); }
return null; }
async clickElement(description: string): Promise<boolean> { const element = await this.findElement(description); if (!element) { console.error(`Element not found: ${description}`); return false; }
const centerX = element.location.x + element.location.width / 2; const centerY = element.location.y + element.location.height / 2;
const prompt = `Click at coordinates (${centerX}, ${centerY})`;
const response = query({ prompt, options: { model: 'claude-sonnet-4-5' } });
for await (const message of response) { if (message.type === 'tool_call') { return true; } }
return false; }}
// Usageconst screen = new ScreenInteraction();
const elements = await screen.analyzeScreen();console.log('Found elements:', elements);
const submitButton = await screen.findElement('Submit button');if (submitButton) { await screen.clickElement('Submit button');}
const loginField = await screen.waitForElement('Login input field', 10000);if (loginField) { console.log('Login field appeared');}Autonomous Task Completion Patterns
Section titled “Autonomous Task Completion Patterns”Implement complex autonomous workflows.
import { query } from '@anthropic-ai/claude-agent-sdk';
class AutonomousTaskExecutor { async fillAndSubmitForm(fields: Record<string, string>): Promise<boolean> { const fieldDescriptions = Object.entries(fields) .map(([fieldName, value]) => `- ${fieldName}: "${value}"`) .join('\n');
const prompt = `1. Capture the screen to identify all form fields2. Fill in these fields with the provided values:${fieldDescriptions}3. Click the submit button4. Wait for the form submission confirmation
Return success or failure status. `;
const response = query({ prompt, options: { model: 'claude-sonnet-4-5' } });
for await (const message of response) { if (message.type === 'assistant') { return message.content.toLowerCase().includes('success'); } }
return false; }
async navigateWebsite(initialUrl: string, navigationSteps: string[]): Promise<string> { let currentLocation = initialUrl;
for (const step of navigationSteps) { const prompt = `Current location: ${currentLocation}Execute this navigation step: ${step}After completion, provide the new URL or location description. `;
const response = query({ prompt, options: { model: 'claude-sonnet-4-5' } });
for await (const message of response) { if (message.type === 'assistant') { // Extract location from response currentLocation = message.content; } } }
return currentLocation; }
async gatherDataFromWebsite(url: string, dataPoints: string[]): Promise<Record<string, string>> { const pointsList = dataPoints.map(p => `- ${p}`).join('\n');
const prompt = `Navigate to: ${url}Find and extract these data points:${pointsList}
Return the data as JSON: { "point1": "value1", "point2": "value2" } `;
const response = query({ prompt, options: { model: 'claude-sonnet-4-5' } });
let result: Record<string, string> = {};
for await (const message of response) { if (message.type === 'assistant') { const jsonMatch = message.content.match(/```json\n([\s\S]*?)\n```/); if (jsonMatch) { result = JSON.parse(jsonMatch[1]); } } }
return result; }
async createContentFromScreens(inputFile: string, outputFormat: string): Promise<string> { const prompt = `Read the file: ${inputFile}Capture multiple screens showing the contentAnalyse the screens and create ${outputFormat} formatted output
Return the final content. `;
const response = query({ prompt, options: { model: 'claude-sonnet-4-5' } });
let content = '';
for await (const message of response) { if (message.type === 'assistant') { content += message.content; } }
return content; }
async testUserInterface(uiDescription: string): Promise<{ passed: number; failed: number; issues: string[] }> { const prompt = `Test the following UI: ${uiDescription}
Perform these tests:1. Identify all interactive elements2. Click each element3. Verify expected behavior4. Check for errors or issues5. Validate responsive design
Return a test report with pass/fail status and any issues found. `;
const response = query({ prompt, options: { model: 'claude-sonnet-4-5' } });
let reportText = '';
for await (const message of response) { if (message.type === 'assistant') { reportText += message.content; } }
// Parse the report return { passed: (reportText.match(/pass/gi) || []).length, failed: (reportText.match(/fail/gi) || []).length, issues: reportText.split('\n').filter(line => line.includes('issue') || line.includes('error')) }; }}
// Usageconst executor = new AutonomousTaskExecutor();
// Fill and submit a formconst formSuccess = await executor.fillAndSubmitForm({ 'Email': 'user@example.com', 'Password': 'securepassword123', 'Remember Me': 'checked'});
// Navigate through websiteconst finalLocation = await executor.navigateWebsite( 'https://example.com', [ 'Click on Products menu', 'Select Category: Electronics', 'Sort by price ascending', 'Click first product' ]);
// Gather data from websiteconst extractedData = await executor.gatherDataFromWebsite( 'https://example.com/products', ['Product Name', 'Price', 'Availability', 'Rating']);
console.log('Extracted Data:', extractedData);
// Test UIconst testResults = await executor.testUserInterface('Login form with email/password fields');console.log('Test Results:', testResults);(Document continues with STRUCTURED OUTPUT, MCP, AGENTIC PATTERNS, PERMISSIONS, SESSION MANAGEMENT, CONTEXT ENGINEERING, PRODUCTION ESSENTIALS, TOOL DEVELOPMENT, STREAMING, TYPESCRIPT PATTERNS, PROJECT SETUP, INTEGRATION PATTERNS, and ADVANCED TOPICS sections…)
The comprehensive guide continues with detailed sections on each topic with extensive TypeScript examples. Due to length constraints, I’ll now create the production guide, diagrams, and recipes files as separate documents.
Revision History
Section titled “Revision History”| Version | Date | Changes |
|---|---|---|
| 0.2.128 | May 5, 2026 | Patch releases (0.2.127–0.2.128); dependency updates; version confirmed against npm @anthropic-ai/claude-agent-sdk 0.2.128 (latest, 2026-05-05, .routine-envs/check-0505-node). query runtime export PASS; PermissionMode, McpServerConfig type exports confirmed present in sdk.d.ts. |
| 0.2.126 | May 1, 2026 | Patch releases (0.2.124–0.2.126); dependency updates; version confirmed against npm @anthropic-ai/claude-agent-sdk 0.2.126 (latest, 2026-05-01). Note: 0.2.125 was not published; sequence goes 0.2.124 → 0.2.126. |
| 0.2.123 | April 29, 2026 | Patch releases (0.2.122–0.2.123); dependency updates; version confirmed against npm @anthropic-ai/claude-agent-sdk 0.2.123. |
| 0.2.121 | April 28, 2026 | Patch releases (0.2.120–0.2.121); dependency updates; version confirmed against npm @anthropic-ai/claude-agent-sdk 0.2.121. |
| 0.2.119 | April 24, 2026 | Patch releases (0.2.118–0.2.119); dependency updates; version confirmed against npm @anthropic-ai/claude-agent-sdk 0.2.119. |
| 0.2.117 | April 21, 2026 | Patch release; dependency updates. |
| 0.2.116 | April 20, 2026 | Patch release; stability improvements. |
| 0.2.114–0.2.115 | April 17, 2026 | Patch releases; internal dependency alignment. |
| 0.2.112–0.2.113 | April 16–17, 2026 | Patch releases; MCP protocol alignment. |
| 0.2.111 | April 16, 2026 | Patch release; performance improvements. |
| 0.2.110 | April 16, 2026 | Multibyte character fix; MCP cleanup fix; extended thinking config types aligned with Python SDK |
| 0.1.30 | Previous version | Package renamed from @anthropic-ai/claude-code to @anthropic-ai/claude-agent-sdk; structured outputs with Zod; MCP integration |