Agent SDK

Description

The programmatic API for embedding Claude Code as a library rather than a CLI. Located at src/entrypoints/sdk/ with the public surface exported from src/entrypoints/agentSdkTypes.ts. The SDK exposes the same QueryEngine, tool system, and MCP integration as the CLI, but communicates via typed AsyncGenerator<SDKMessage> streams instead of a terminal UI. A control protocol enables out-of-band operations (permission decisions, MCP management, configuration changes) without blocking the message stream.

Public API

One-shot convenience

unstable_v2_prompt(message: string, options: SDKSessionOptions): Promise<SDKResultMessage>

Send a single prompt and get the result. The simplest way to use Claude Code programmatically.

Persistent sessions

unstable_v2_createSession(options: SDKSessionOptions): SDKSession
unstable_v2_resumeSession(sessionId: string, options: SDKSessionOptions): SDKSession

Create or resume multi-turn sessions with full state persistence. The session object exposes the message stream as an async generator.

Session management

listSessions(options?): Promise<SDKSessionInfo[]>
getSessionInfo(sessionId, options?): Promise<SDKSessionInfo | undefined>
getSessionMessages(sessionId, options?): Promise<SessionMessage[]>
renameSession(sessionId, title, options?): Promise<void>
tagSession(sessionId, tag, options?): Promise<void>
forkSession(sessionId, options?): Promise<ForkSessionResult>

Read, rename, tag, and fork existing sessions. getSessionMessages reads the JSONL transcript directly with pagination support.

Tool registration

tool<Schema>(name, description, inputSchema, handler, extras?): SdkMcpToolDefinition<Schema>
createSdkMcpServer(options: { name, version?, tools? }): McpSdkServerConfigWithInstance

Register custom tools using Zod schemas for input validation. Tools run as in-process MCP servers — no subprocess overhead. The alwaysLoad flag ensures a tool is always available; searchHint aids tool discovery.

Legacy query API

query(params: { prompt, options? }): Query | InternalQuery

Lower-level access to the QueryEngine. Returns a query object with the message stream.

Internal APIs (daemon/scheduler)

watchScheduledTasks(opts): ScheduledTasksHandle     // @internal
connectRemoteControl(opts): Promise<RemoteControlHandle | null>  // @internal

Used by the daemon and Claude Code Remote (CCR) for scheduled task execution and remote control.

Session options

SDKSessionOptions configures everything for a session:

Option Purpose
model Model identifier (required)
cwd Working directory
customSystemPrompt / appendSystemPrompt System prompt customization
tools Array of tool names to enable
agents Record of agent definitions
maxTurns / maxBudgetUsd Execution limits
jsonSchema Structured output constraint
thinkingConfig adaptive / enabled (with budget) / disabled
permissionMode default / acceptEdits / bypassPermissions / plan / dontAsk
hooks Record of hook event → callback matchers
sdkMcpServers MCP server configurations
outputStyle Output formatting preference

Message types

The SDK communicates via a stream of typed SDKMessage objects (sdk/coreSchemas.ts:1854). The major categories:

Conversation: - SDKUserMessage — user input - SDKAssistantMessage — API response (may include error field) - SDKSystemMessage (subtype 'init') — initialization with tools, models, agents

Streaming: - SDKPartialAssistantMessage — raw streaming events from the API - SDKStreamlinedTextMessage — thinking/tool blocks removed for display

Tool execution: - SDKToolProgressMessage — elapsed time, task ID tracking - SDKToolUseSummaryMessage — cumulative tool call summary

Status and control: - SDKStatusMessage — compaction/status updates - SDKCompactBoundaryMessage — history compaction markers - SDKAPIRetryMessage — retry events with attempt count - SDKSessionStateChangedMessage — idle/running/requires_action - SDKRateLimitEventSchema — rate limit info with utilization

Results: - SDKResultMessage — terminal message, union of: - Success: duration, usage, cost, model usage breakdown, structured output - Error subtypes: error_during_execution, error_max_turns, error_max_budget_usd, error_max_structured_output_retries

Hooks: - SDKHookStartedMessage, SDKHookProgressMessage, SDKHookResponseMessage

Tasks: - SDKTaskNotificationMessage, SDKTaskStartedMessage, SDKTaskProgressMessage

Control protocol

The control protocol (sdk/controlSchemas.ts) enables out-of-band communication between the SDK consumer and the CLI process:

SDK Consumer → CLI:  { type: 'control_request', request_id, request }
CLI → SDK Consumer:  { type: 'control_response', response: { subtype, request_id, response? } }

23 control request types:

Category Requests
Lifecycle initialize, interrupt
Permissions can_use_tool, set_permission_mode
Model set_model, set_max_thinking_tokens
MCP mcp_status, mcp_message, mcp_set_servers, mcp_reconnect, mcp_toggle
Context get_context_usage, rewind_files, cancel_async_message, seed_read_state
Hooks hook_callback
Config apply_flag_settings, get_settings, reload_plugins
Tasks stop_task
MCP auth elicitation

The initialize request configures hooks, MCP servers, agents, schemas, and prompts. The response returns available commands, agents, models, account info, output styles, and PID.

Hook system

The SDK supports 27 hook events:

PreToolUse, PostToolUse, PostToolUseFailure, Notification,
UserPromptSubmit, SessionStart, SessionEnd, Stop, StopFailure,
SubagentStart, SubagentStop, PreCompact, PostCompact,
PermissionRequest, PermissionDenied, Setup, TeammateIdle,
TaskCreated, TaskCompleted, Elicitation, ElicitationResult,
ConfigChange, WorktreeCreate, WorktreeRemove,
InstructionsLoaded, CwdChanged, FileChanged

Hooks fire with structured input (containing session_id, transcript_path, cwd, tool_name, tool_input) and return event-specific output. In the SDK, hooks execute as in-process callbacks routed via the control protocol — no subprocess spawning like in the CLI.

How it differs from the CLI

Aspect CLI SDK
Communication Terminal UI (Ink/React) AsyncGenerator<SDKMessage> stream
Initialization Auto-load config, trust dialog, plugin loading Explicit SDKSessionOptions + control protocol initialize
Permissions Interactive Ink prompts Control protocol can_use_tool or hook-based
Tool registration From settings.json + MCP config tool() + createSdkMcpServer() (in-process)
Session management JSONL files + interactive browser Programmatic listSessions / getSessionMessages
Configuration Multi-layer (user/project/local/policy) from disk Passed explicitly in session options
Output Rendered terminal UI Typed message stream
Telemetry Eager initialization Deferred until explicit initializeTelemetryAfterTrust()

Available in SDK but not CLI: - Programmatic hook registration via control protocol - In-process tool execution (MCP SDK servers, no subprocess) - Explicit session/message/config management functions - Remote daemon integration (connectRemoteControl) - Task scheduling (watchScheduledTasks)

Available in CLI but not SDK: - Interactive UI, file diff visualization, progress bars - Auto-interactive permission prompts - Command palette / slash commands - Plugin loading from --plugin-dir - Session browser UI - LSP/editor integration

Agent definitions

The SDK supports custom agent definitions:

{
  description: string,           // When to use this agent
  tools?: string[],              // Inherit from parent if omitted
  disallowedTools?: string[],
  prompt: string,                // System prompt
  model?: string,                // 'sonnet' | 'opus' | model ID | 'inherit'
  mcpServers?: (string | record<string, McpServerConfig>)[],
  skills?: string[],
  initialPrompt?: string,        // Auto-submitted first turn
  maxTurns?: number,
  background?: boolean,          // Fire-and-forget
  memory?: 'user' | 'project' | 'local',
  effort?: 'low' | 'medium' | 'high' | 'max',
  permissionMode?: PermissionMode
}

What depends on it

Design trade-offs

Decision Trade-off
AsyncGenerator for messages Natural streaming, but consumers must handle all message types (27+)
Control protocol for out-of-band ops Clean separation from message stream, but adds roundtrip latency for permission decisions
In-process MCP servers for tools Zero subprocess overhead, but tools share the process — a crash affects everything
unstable_v2_* prefix Signals API instability, but may deter adoption
Explicit config (no auto-loading) Full control for embedders, but more boilerplate than CLI's auto-discovery
Zod schemas for type safety Strong validation, but 1890-line schema file is a maintenance burden

Key claims

Relations

Sources

Source code at src/entrypoints/agentSdkTypes.ts, src/entrypoints/sdk/coreSchemas.ts, src/entrypoints/sdk/controlSchemas.ts