11 KiB
Agent SDK — TypeScript
The Claude Agent SDK provides a higher-level interface for building AI agents with built-in tools, safety features, and agentic capabilities.
Installation
npm install @anthropic-ai/claude-agent-sdk
Quick Start
import { query } from "@anthropic-ai/claude-agent-sdk";
for await (const message of query({
prompt: "Explain this codebase",
options: { allowedTools: ["Read", "Glob", "Grep"] },
})) {
if ("result" in message) {
console.log(message.result);
}
}
Built-in Tools
| Tool | Description |
|---|---|
| Read | Read files in the workspace |
| Write | Create new files |
| Edit | Make precise edits to existing files |
| Bash | Execute shell commands |
| Glob | Find files by pattern |
| Grep | Search files by content |
| WebSearch | Search the web for information |
| WebFetch | Fetch and analyze web pages |
| AskUserQuestion | Ask user clarifying questions |
| Agent | Spawn subagents |
Permission System
for await (const message of query({
prompt: "Refactor the authentication module",
options: {
allowedTools: ["Read", "Edit", "Write"],
permissionMode: "acceptEdits",
},
})) {
if ("result" in message) console.log(message.result);
}
Permission modes:
"default": Prompt for dangerous operations"plan": Planning only, no execution"acceptEdits": Auto-accept file edits"dontAsk": Don't prompt — denies anything not pre-approved (not an auto-approve mode)"bypassPermissions": Skip all prompts (requiresallowDangerouslySkipPermissions: truein options)
MCP (Model Context Protocol) Support
for await (const message of query({
prompt: "Open example.com and describe what you see",
options: {
mcpServers: {
playwright: { command: "npx", args: ["@playwright/mcp@latest"] },
},
},
})) {
if ("result" in message) console.log(message.result);
}
In-Process MCP Tools
You can define custom tools that run in-process using tool() and createSdkMcpServer:
import { query, tool, createSdkMcpServer } from "@anthropic-ai/claude-agent-sdk";
import { z } from "zod";
const myTool = tool("my-tool", "Description", { input: z.string() }, async (args) => {
return { content: [{ type: "text", text: "result" }] };
});
const server = createSdkMcpServer({ name: "my-server", tools: [myTool] });
// Pass to query
for await (const message of query({
prompt: "Use my-tool to do something",
options: { mcpServers: { myServer: server } },
})) {
if ("result" in message) console.log(message.result);
}
Hooks
import { query, HookCallback } from "@anthropic-ai/claude-agent-sdk";
import { appendFileSync } from "fs";
const logFileChange: HookCallback = async (input) => {
const filePath = (input as any).tool_input?.file_path ?? "unknown";
appendFileSync(
"./audit.log",
`${new Date().toISOString()}: modified ${filePath}\n`,
);
return {};
};
for await (const message of query({
prompt: "Refactor utils.py to improve readability",
options: {
allowedTools: ["Read", "Edit", "Write"],
permissionMode: "acceptEdits",
hooks: {
PostToolUse: [{ matcher: "Edit|Write", hooks: [logFileChange] }],
},
},
})) {
if ("result" in message) console.log(message.result);
}
Hook event inputs for tool-lifecycle events (PreToolUse, PostToolUse, PostToolUseFailure) include agent_id and agent_type fields, allowing hooks to identify which agent (main or subagent) triggered the tool call.
Available hook events: PreToolUse, PostToolUse, PostToolUseFailure, Notification, UserPromptSubmit, SessionStart, SessionEnd, Stop, SubagentStart, SubagentStop, PreCompact, PermissionRequest, Setup, TeammateIdle, TaskCompleted, ConfigChange, Elicitation, ElicitationResult, WorktreeCreate, WorktreeRemove, InstructionsLoaded
Common Options
query() takes a top-level prompt (string) and an options object:
query({ prompt: "...", options: { ... } })
| Option | Type | Description |
|---|---|---|
cwd |
string | Working directory for file operations |
allowedTools |
array | Tools the agent can use (e.g., ["Read", "Edit", "Bash"]) |
tools |
array | preset | Built-in tools to make available (string[] or {type:'preset', preset:'claude_code'}) |
disallowedTools |
array | Tools to explicitly disallow |
permissionMode |
string | How to handle permission prompts |
allowDangerouslySkipPermissions |
bool | Must be true to use permissionMode: "bypassPermissions" |
mcpServers |
object | MCP servers to connect to |
hooks |
object | Hooks for customizing behavior |
systemPrompt |
string | preset | Custom system prompt (string or {type:'preset', preset:'claude_code', append?:string}) |
maxTurns |
number | Maximum agent turns before stopping |
maxBudgetUsd |
number | Maximum budget in USD for the query |
model |
string | Model ID (default: determined by CLI) |
agents |
object | Subagent definitions (Record<string, AgentDefinition>) |
outputFormat |
object | Structured output schema |
thinking |
object | Thinking/reasoning control |
betas |
array | Beta features to enable (e.g., ["context-1m-2025-08-07"]) |
settingSources |
array | Settings to load (e.g., ["project"]). Default: none (no CLAUDE.md files) |
env |
object | Environment variables to set for the session |
agentProgressSummaries |
bool | Enable periodic AI-generated progress summaries on task_progress events |
Subagents
for await (const message of query({
prompt: "Use the code-reviewer agent to review this codebase",
options: {
allowedTools: ["Read", "Glob", "Grep", "Agent"],
agents: {
"code-reviewer": {
description: "Expert code reviewer for quality and security reviews.",
prompt: "Analyze code quality and suggest improvements.",
tools: ["Read", "Glob", "Grep"],
},
},
},
})) {
if ("result" in message) console.log(message.result);
}
Message Types
for await (const message of query({
prompt: "Find TODO comments",
options: { allowedTools: ["Read", "Glob", "Grep"] },
})) {
if ("result" in message) {
console.log(message.result);
console.log(`Stop reason: ${message.stop_reason}`); // e.g., "end_turn", "tool_use", "max_tokens"
} else if (message.type === "system" && message.subtype === "init") {
const sessionId = message.session_id; // Capture for resuming later
}
}
Task-related system messages are also emitted for subagent operations:
task_started— emitted when a subagent task is registeredtask_progress— real-time progress updates with cumulative usage metrics, tool counts, and duration (enableagentProgressSummariesoption for periodic AI-generated summaries via thesummaryfield)task_notification— task completion notifications (includestool_use_idfor correlating with originating tool calls)
Session History
Retrieve past session data:
import { listSessions, getSessionMessages, getSessionInfo } from "@anthropic-ai/claude-agent-sdk";
// List all past sessions (supports pagination via limit/offset)
const sessions = await listSessions({ limit: 20, offset: 0 });
for (const session of sessions) {
console.log(`${session.sessionId}: ${session.cwd} (tag: ${session.tag})`);
}
// Get metadata for a single session
const sessionId = sessions[0]?.sessionId;
const info = await getSessionInfo(sessionId);
console.log(info.tag, info.createdAt);
// Get messages from a specific session (supports pagination via limit/offset)
const messages = await getSessionMessages(sessionId, { limit: 50, offset: 0 });
for (const msg of messages) {
console.log(msg);
}
Session Mutations
Rename, tag, or fork sessions:
import { renameSession, tagSession, forkSession } from "@anthropic-ai/claude-agent-sdk";
// Rename a session
await renameSession(sessionId, "My refactoring session");
// Tag a session
await tagSession(sessionId, "experiment");
// Clear a tag
await tagSession(sessionId, null);
// Fork a session — branch a conversation from a specific point
const { sessionId: forkedId } = await forkSession(sessionId);
MCP Server Management
Manage MCP servers at runtime on a running query:
// Reconnect a disconnected MCP server
await queryHandle.reconnectMcpServer("my-server");
// Toggle an MCP server on/off
await queryHandle.toggleMcpServer("my-server", false); // (name, enabled) — both required
// Get status of ALL configured MCP servers — returns an ARRAY
const statuses: McpServerStatus[] = await queryHandle.mcpServerStatus();
for (const s of statuses) {
console.log(s.name, s.scope, s.tools.length, s.error);
}
Best Practices
- Always specify allowedTools — Explicitly list which tools the agent can use
- Set working directory — Always specify
cwdfor file operations - Use appropriate permission modes — Start with
"default"and only escalate when needed - Handle all message types — Check for
resultproperty to get agent output - Limit maxTurns — Prevent runaway agents with reasonable limits