入口函数
心智模型:Claude Agent SDK 把Agent Session抽象成一个异步生成器
export declare function query(_params: {
prompt: string | AsyncIterable<SDKUserMessage>;
options?: Options;
}): Query; // Query extends AsyncGenerator<SDKMessage, void>
SDKMessage
for await 拿到的每一条消息都是 SDKMessage。它是一个联合类型,常见成员如下:
type |
含义 | 关键字段 |
|---|---|---|
'system'(subtype:'init') |
会话初始化信息,第一条 | claude_code_version、cwd、tools、mcp_servers、model、permissionMode、skills、plugins、capabilities? |
'assistant' |
模型一轮回复(含 text / tool_use / thinking 块) | message: BetaMessage、parent_tool_use_id、uuid、session_id、aborted?、subagent_type? |
'user' |
用户消息或工具结果回填 | message: MessageParam、tool_use_result?、shouldQuery?、priority?〔sdk.d.ts:4583-4605〕 |
'stream_event'(SDKPartialAssistantMessage) |
流式增量,仅当 includePartialMessages:true 才出现 |
|
'result' |
终结消息,流到此结束 | 见下表 |
联合里还包含
hook_started/hook_response、task_*、rate_limit、compact_boundary等大量事件类型。普通集成只需关注system/assistant/user/result,其余按需处理。
终结消息:成功 vs 失败
'result' 是 SDKResultSuccess | SDKResultError〔sdk.d.ts:4290〕。判别字段是 subtype:
成功:
{
type: 'result'; subtype: 'success';
is_error: false;
num_turns: number; // 轮数
result: string; // 最终文本
total_cost_usd: number; // 本次花费
usage: NonNullableUsage; // token 用量
structured_output?: unknown; // 仅当 outputFormat 设定时存在
terminal_reason?: TerminalReason;
session_id: string;
}
失败——subtype 只能是这四种之一,直接告诉你失败的原因类别:
subtype: 'error_during_execution'
| 'error_max_turns' // 触达 maxTurns
| 'error_max_budget_usd' // 触达 maxBudgetUsd
| 'error_max_structured_output_retries'; // 结构化输出重试耗尽
is_error: true;
errors: string[]; // 具体错误文本数组
permission_denials: SDKPermissionDenial[];
terminal_reason:循环为何终止
终结消息里可选的 terminal_reason 解释了“为什么停”。常用值:
'completed'— 正常完成'max_turns'— 触达maxTurns'budget_exhausted'— 预算耗尽'aborted_streaming'/'aborted_tools'— 被中断'stop_hook_prevented'/'hook_stopped'— 被 Stop hook 拦下'tool_deferred'/'tool_deferred_unavailable'— 工具被延迟/不可用'prompt_too_long'/'api_error'/'model_error'/'image_error'等
边界提示:拿到
result后务必先看subtype/is_error,不要假设流结束即成功。error_max_turns是最常见的“Agent 跑飞”信号——它意味着模型在maxTurns内没收敛,而不是真的完成了任务。
流式输入输出模式
当开发者把 prompt 传成 AsyncIterable<SDKUserMessage>(流式输入)时,下面这些方法才生效;传字符串时调用它们无效:
| 方法 | 作用 | 出处 |
|---|---|---|
interrupt() |
中断当前执行;返回 {still_queued, cancelled?} |
〔sdk.d.ts:2293, 3485-3494〕 |
setPermissionMode(mode) |
运行中切换权限模式 | 〔sdk.d.ts:2300〕 |
setMcpPermissionModeOverride(server, mode|null) |
针对单台 MCP server 钉住/清除权限覆盖(只能收紧不能放大,仅 'default'|'auto'|null) |
〔sdk.d.ts:2317〕 |
setModel(model?) |
运行中换模型 | 〔sdk.d.ts:2327〕 |
setMaxThinkingTokens(n|null, display?) |
已废弃,改用 thinking 选项 |
〔sdk.d.ts:2350, 2337-2340〕 |
applyFlagSettings(settings) |
运行中合并 flag 层设置 | 〔sdk.d.ts:2373〕 |
initializationResult() / reinitialize() |
取/重发 init | 〔sdk.d.ts:2382, 2399〕 |
supportedModels() / supportedAgents() / supportedCommands() |
列模型/子代理/命令 | 〔sdk.d.ts:2411, 2417, 2405〕 |
mcpServerStatus() |
各 MCP server 连接状态 | 〔sdk.d.ts:2423〕 |
getContextUsage() |
上下文用量分类明细 | 〔sdk.d.ts:2430〕 |
rewindFiles(userMessageId, {dryRun?}) |
回滚文件到某条用户消息的状态(需 enableFileCheckpointing) |
〔sdk.d.ts:2486〕 |
Options
进程与环境
env
env?: { [envVar: string]: string | undefined };
一旦传了 env,子进程就只剩用户给的那几个变量——PATH、HOME、API Key 全没了,于是命令找不到、鉴权失败。正确做法是显式展开:
env: { ...process.env, CLAUDE_AGENT_SDK_CLIENT_APP: "my-app/1.0" }
在多租户和安全场景下,尽量不直接注入 process.env。
cwd
会话工作目录,默认 process.cwd()。它决定了 Agent 读写文件的基准、以及 settingSources 里 'project' 的查找位置。
settingSources:SDK 隔离模式
settingSources?: SettingSource[]; // 'user' | 'project' | 'local'
“Pass
[]to disable filesystem settings (SDK isolation mode). Must include'project'to load CLAUDE.md files.”〔sdk.d.ts:1907-1908〕
- 省略 = 加载全部三层(与 CLI 一致)。
- 传
[]= 彻底不读任何文件系统配置,是 SDK 嵌入到别处时最干净的隔离姿态。 - 想让 Agent 读到项目里的
CLAUDE.md/AGENTS.md,必须显式包含'project'。
工具与权限
tools?: string[] | { type: 'preset'; preset: 'claude_code' };
allowedTools?: string[];
disallowedTools?: string[];
| 选项 | 作用 | 边界 |
|---|---|---|
tools |
决定哪些内置工具存在。['Bash','Read','Edit'] 显式列举;[] 禁用所有内置工具;{type:'preset',preset:'claude_code'} 用全套〔sdk.d.ts:1423-1434〕 |
native 构建可能用 Bash 的 find/grep 代替 Grep/Glob;需要的话要在 tools 或 allowedTools 里显式列出 Grep/Glob〔sdk.d.ts:1428-1429〕 |
allowedTools |
这些工具自动放行、不弹权限提示〔sdk.d.ts:1369-1371〕 | “要限制可用工具,用 tools 而不是 allowedTools”〔sdk.d.ts:1371〕;传 'Skill' 已废弃,改用 skills〔sdk.d.ts:1373〕 |
disallowedTools |
从模型上下文中移除这些工具,即便本可使用也用不了〔sdk.d.ts:1391-1395〕 | — |
常见误用:想“只允许 Bash”却设了
allowedTools:['Bash']——这只是“Bash 不弹窗”,其它工具照样存在可用。正确做法是tools:['Bash'](白名单化工具集)。
permissionMode:六种模式
export declare type PermissionMode =
'default' | 'acceptEdits' | 'bypassPermissions' | 'plan' | 'dontAsk' | 'auto';
〔sdk.d.ts:2090-2092〕官方释义(逐字):
'default'— 标准行为,危险操作弹窗'acceptEdits'— 自动接受文件编辑'bypassPermissions'— 绕过所有权限检查(需要allowDangerouslySkipPermissions)'plan'— 规划模式,不实际执行工具'dontAsk'— 不弹窗,未预批准则直接拒绝'auto'— 用模型分类器决定放行/拒绝
canUseTool:权限回调(核心,见 §4 详解)
canUseTool?: CanUseTool; // (toolName, input, options) => Promise<PermissionResult | null>
sandbox:OS 级隔离(见 §5 详解)
sandbox?: SandboxSettings;
模型与推理
model
如 'claude-sonnet-5'
thinking(推荐)
thinking?: ThinkingConfig; // adaptive | enabled | disabled
type ThinkingAdaptive = { type: 'adaptive'; display?: 'summarized' | 'omitted' }; // Claude 自己决定何时/思考多少(Opus 4.6+),支持模型的默认值
type ThinkingEnabled = { type: 'enabled'; budgetTokens?: number; display?: ... }; // 固定思考预算(旧模型)
type ThinkingDisabled = { type: 'disabled' };
effort:努力度
effort?: EffortLevel; // 'low' | 'medium' | 'high' | 'xhigh' | 'max'
| 级别 | 语义 | 支持模型 |
|---|---|---|
'low' |
最少思考、最快 | — |
'medium' |
适中 | — |
'high' |
深度推理(默认) | — |
'xhigh' |
比 high 更深 | Fable 5 / Opus 4.7+ / Sonnet 5 |
'max' |
最大努力 | Fable 5 / Opus 4.6+ / Sonnet 4.6+ |
边界:
'max'是会话级的、永不持久化。effort与 adaptive thinking 协同引导思考深度〔sdk.d.ts:1654〕。
预算与轮数
| 选项 | 作用 | 触发后果 |
|---|---|---|
maxTurns?: number |
最大对话轮数〔sdk.d.ts:1674-1678〕 | 超出 → result.subtype === 'error_max_turns' |
maxBudgetUsd?: number |
最大 USD 预算〔sdk.d.ts:1679-1683〕 | 超出 → 'error_max_budget_usd' |
taskBudget?: { total: number }(@alpha) |
API 侧 token 任务预算,模型会感知剩余预算以规划工具使用〔sdk.d.ts:1684-1693〕 | 带 task-budgets-2026-03-13 beta header |
边界:
maxTurns的“一轮”= 一条用户消息 + 一条 assistant 回复〔sdk.d.ts:1676〕。设太小会频繁触发error_max_turns——这不是崩溃,是策略性截断,要在外层据此决定是否续跑。maxBudgetUsd是硬墙,超额即停。
会话与恢复
resume?: string; // 恢复指定 session_id
continue?: boolean; // 恢复当前目录最近一次会话
sessionId?: string; // 用指定 UUID 作为新会话 ID
forkSession?: boolean; // 恢复时分叉到新 session,而不是续写
resumeSessionAt?: string; // 仅恢复到某条消息(含)为止
persistSession?: boolean; // 是否落盘(默认 true)
互斥与组合规则(这是会话管理最容易踩坑的地方):
continue与resume互斥〔sdk.d.ts:1382-1385〕。sessionId不能与continue/resume同时用,除非也设了forkSession(此时sessionId给分叉出的新会话指定 UUID)〔sdk.d.ts:1805-1809〕。resumeSessionAt只能与resume搭配,消息 UUID 应取自SDKAssistantMessage.uuid〔sdk.d.ts:1810-1815〕。forkSession:true时,恢复会分叉出新 session_id,不污染原会话〔sdk.d.ts:1496-1500〕。
persistSession 与 sessionStore
persistSession默认true;设false则不落盘到~/.claude/projects/,无法 resume〔sdk.d.ts:1580-1586〕。sessionStore(@alpha)把 transcript 镜像到外部存储;子进程仍会本地写(可把CLAUDE_CONFIG_DIR设到/tmp做临时本地副本)并双写到 adapter〔sdk.d.ts:1587-1598〕。- 硬约束:
sessionStore不能与persistSession:false同用——镜像 hook 在本地写成功后才触发,没有本地写就没有镜像〔sdk.d.ts:1592-1593〕。 sessionStoreFlush?: 'batched' | 'eager'控制刷新激进程度,默认'batched'〔sdk.d.ts:1599-1606, 4905〕。loadTimeoutMs(默认 60000)兜底 resume 载入超时,否则延迟 spawn 路径无上限地挂起迭代器〔sdk.d.ts:1607-1616〕。
SessionStore 契约要点〔sdk.d.ts:4793-4815〕:
append(key, entries):本地写成功后调用,~100ms 一批;带uuid的条目应作为幂等键(upsert/去重),无uuid的(标题/标签)直接追加。- 拒绝会重试 3 次;超时(60s)不重试;最终失败则丢批并发出
mirror_error系统消息,子进程不受影响。
输入输出形态
systemPrompt:三种形态
systemPrompt?: string | string[] | {
type: 'preset'; preset: 'claude_code';
append?: string; excludeDynamicSections?: boolean;
};
```- `string`:完全替换系统提示。
- `string[]`:可插入**缓存边界标记** `SYSTEM_PROMPT_DYNAMIC_BOUNDARY`(`"__SYSTEM_PROMPT_DYNAMIC_BOUNDARY__"`)〔sdk.d.ts:6855-6863〕。**边界之前**的块获得**跨会话全局缓存**作用域,**之后**的块是会话级、不全局缓存。这让你把“稳定的系统指令”和“每次会话变动的动态指令”分开,吃满 prompt cache。
- `{type:'preset', preset:'claude_code', append?, excludeDynamicSections?}`:保留默认 Claude Code 系统提示,追加 `append`,可选排除动态段落。
#### `outputFormat`:结构化输出
```ts
outputFormat?: OutputFormat; // = JsonSchemaOutputFormat
type JsonSchemaOutputFormat = { type: 'json_schema'; schema: Record<string, unknown> };
〔sdk.d.ts:1714-1726, 2065, 930-933, 4314〕
设定后,成功结果里会出现 structured_output?: unknown,其内容匹配你给的 schema〔sdk.d.ts:4314〕。若结构化输出反复校验失败,会以 error_max_structured_output_retries 终结〔sdk.d.ts:4271〕。
扩展能力
mcpServers?: Record<string, McpServerConfig>:MCP 服务器配置(见 §7)〔sdk.d.ts:1694-1708〕。agents?: Record<string, AgentDefinition>:自定义子代理(见 §8)〔sdk.d.ts:1367〕。hooks?: Partial<Record<HookEvent, HookCallbackMatcher[]>>:钩子(见 §6)〔sdk.d.ts:1508-1521〕。onElicitation?: OnElicitation:MCP elicitation(表单/URL 鉴权)回调;不提供且无 hook 处理时,elicitation 请求会被自动拒绝〔sdk.d.ts:1522-1542〕。onUserDialog:处理request_user_dialog控制请求〔sdk.d.ts:1543〕。betas?: SdkBeta[]:如'context-1m-2025-08-07'(1M 上下文,仅 Sonnet 4/4.5)〔sdk.d.ts:1501-1507〕。