claude-code 事件流 字段参考
本文是 claude -p --output-format stream-json --verbose 输出的事件流的字段参考:每种事件何时出现、有哪些字段、字段的类型与含义、典型运行的顺序、subagent 的嵌套方式、错误与退出码。写给要为这条流写解析器的人,不依赖 agentrun 的其他文档。依据是 claude-code 2.1.288 与 2.1.289 在 Linux 容器里的实测输出,字段表中标出了每一项的来源。
读这条流的三条规则:每行一个 JSON 对象,按
type与subtype分发,不认识的类型跳过;一次运行可能有多个result事件,以最后一个为准;成败看最后一个result的is_error,退出码只区分启动失败与运行时的限额失败。
代码位置
| 位置 | 内容 |
|---|---|
src/runtime/claudecode.rs | ClaudeCode(launch、translate、failure) |
tests/fixtures/claude-code/ | 本页样本的原始输出 *.raw.jsonl 与对应的统一事件 *.events.jsonl,格式见测试与发布 |
tests/claudecode.rs | 回放这些样本的 replay_* 测试与用假 claude 脚本做的适配器测试 |
怎样产生这条流
echo '{"type":"user","message":{"role":"user","content":"提示词"}}' | claude -p \
--input-format stream-json --replay-user-messages \
--output-format stream-json --verbose \
--model sonnet --session-id "$(uuidgen)" --no-session-persistence \
--permission-mode auto --setting-sources "" --strict-mcp-config
-p(--print)让 claude 处理一个提示词后退出;--output-format stream-json 选择逐行 JSON 输出;--verbose 是必需的,缺少它时进程不输出任何事件,在标准错误打印 Error: When using --print, --output-format=stream-json requires --verbose,退出码 1。
--input-format stream-json 让 claude 从标准输入读取 JSON 行形式的用户消息,--replay-user-messages 把读到的用户消息回显到输出流里。这样提示词会作为一个 user 事件出现在 system/init 之后、第一个 assistant 之前,带 isReplay: true,事件流本身就是这次运行的完整记录。提示词也可以作为命令行参数传入(claude -p "提示词")或以纯文本从标准输入传入,这两种方式下输出流里没有提示词,其余事件相同。实测只用过一条提示词,写完后关闭标准输入,进程正常结束。
事件流写到标准输出,标准输出里只有 JSON 行。诊断信息写到标准错误,例如模型名不存在时的 [claude-code:unrecognized_model] {"model":"...","query_source":"sdk"}。
agentrun 的 ClaudeCode::launch 生成的命令以本节开头的命令为基础。
以下选项与环境变量改变流里出现的事件:
| 选项 | 对流的影响 |
|---|---|
--include-partial-messages环境变量 CLAUDE_CODE_INCLUDE_PARTIAL_MESSAGES=true | 加入 stream_event 事件,每个模型调用的逐字输出都会出现。见「stream_event 事件」。本文的部分样本来自设置了该环境变量的环境,显式选项的效果以帮助文本为依据 |
--include-hook-events | 加入 system 的 hook_started 与 hook_response 子类型。没有配置 hook 时不会出现 |
--json-schema JSON | 模型通过一个名为 StructuredOutput 的工具调用给出结构化结果,result 事件多出 structured_output 字段 |
--max-turns N | 超过 N 轮时结束,result.subtype 为 error_max_turns,退出码 1 |
--max-budget-usd AMOUNT | 花费超过上限时结束,result.subtype 为 error_max_budget_usd,退出码 1 |
--permission-mode MODE、--permission-prompts none | 需要确认而无人确认的工具调用被拒绝,出现 system 的 permission_denied 子类型,result.permission_denials 非空。--permission-prompts 可选值为 host 与 none,-p 模式下没有确认界面时效果与 none 相同 |
--forward-subagent-text | 帮助文本说明它把 subagent 的文字与 thinking 以 parent_tool_use_id 标记后转发到流里。未实测 |
--input-format stream-json、--replay-user-messages | 从标准输入读取 JSON 消息,并把用户消息回显为 isReplay: true 的 user 事件。见上一段 |
--model、--setting-sources、--strict-mcp-config、--settings、--tools | 改变 system/init 里的 model、tools、mcp_servers、skills、slash_commands 等列表,不改变事件类型 |
每行的格式
每行是一个 JSON 对象,以 LF 结尾,没有空行,没有非 JSON 行。每个对象都有 type;type 为 system 与 result 的对象还有 subtype。下面的字段出现在多种事件上:
| 字段 | 类型 | 含义 | 出现在 |
|---|---|---|---|
type | string | 事件类型 | 所有事件 |
subtype | string | 子类型 | system、result |
uuid | string | 这一行的唯一编号 | 除 system/api_retry 以外的所有观测到的事件都有 |
session_id | string | 会话 id,等于 --session-id 给出的值。subagent 的事件与主 agent 相同 | 所有事件 |
parent_tool_use_id | string 或 null | 主 agent 的事件为 null;subagent 内部的事件是启动它的那次 Agent 工具调用的 id。见「subagent 与后台任务」 | assistant、user、stream_event |
timestamp | string | ISO 8601,UTC,毫秒。只有 assistant 与 user 事件带时间戳,其他事件没有 | assistant、user |
字符串里可能有换行(\n)与 Unicode 行分隔符,按 LF 切行后再解析 JSON,不能按通用的行分隔符切行。
有哪些事件
按用途分为六类,越靠前越需要处理。下表的事件都在样本中观测到。
结果与对话内容
解析器必须处理的四种事件:运行开始时的配置、模型输出、工具结果与最终结果。成败只看最后一个 result。
| type / subtype | 何时出现 | 需要的条件 |
|---|---|---|
system/init | 每次运行的开头一次;后台任务完成触发新一轮时再次出现 | 总是 |
assistant | 模型每输出一个内容块(文字、thinking、工具调用) | 总是 |
user | 每个工具结果;subagent 收到的提示词;中断提示;注入的技能说明 | 总是 |
result | 一轮对话结束时;可能多次 | 总是,除非进程被 SIGTERM 终止或在启动前失败 |
subagent 与后台任务
agent 启动 subagent、Workflow 或后台 Bash 命令时出现,用来跟踪这些任务的开始、进度与结束。
| type / subtype | 何时出现 | 需要的条件 |
|---|---|---|
system/task_started、task_progress、task_updated、task_notification | subagent、Workflow 与后台 Bash 命令的生命周期 | agent 启动了这类任务 |
system/background_tasks_changed | 后台任务列表变化时 | agent 启动了后台任务 |
错误与权限
请求失败重试与工具调用被拒绝。
| type / subtype | 何时出现 | 需要的条件 |
|---|---|---|
system/api_retry | API 请求失败后重试之前 | API 返回错误 |
system/permission_denied | 一次工具调用被权限规则拒绝时 | 见上一节的权限选项 |
进度与摘要
给界面显示进度用,解析结果时可以忽略。
| type / subtype | 何时出现 | 需要的条件 |
|---|---|---|
system/status | 每次向模型发请求之前 | 总是 |
system/task_summary | 工具调用前后,给出一句当前动作的描述 | 总是 |
system/post_turn_summary | 一轮结束、result 之前 | 总是 |
system/thinking_tokens | 模型输出 thinking 块的过程中 | 模型使用了 thinking |
需要选项才出现
| type / subtype | 何时出现 | 需要的条件 |
|---|---|---|
stream_event | 模型调用的逐字输出 | --include-partial-messages 或对应环境变量 |
system/hook_started、system/hook_response | 每个 hook 命令开始与结束 | --include-hook-events 且配置了 hook |
只在部分环境出现
在 Claude 的 Cloud Managed 容器里观测到,本机运行时没有。解析器跳过即可。
| type / subtype | 何时出现 | 需要的条件 |
|---|---|---|
active_goal | 启动时,在 system/init 之前 | 见「版本与环境说明」 |
autocompact_state | 启动时,在 system/init 之前 | 见「版本与环境说明」 |
rate_limit_event | 启动时,在 system/init 前后都可能 | 见「版本与环境说明」 |
一次运行的顺序
下面是一次「写文件、读回、回答」的运行,没有开启逐字输出。图中每个方框是流里的一行,从上到下按出现顺序排列,按产生它的一方分为四列。调用方的提示词由 --replay-user-messages 回显为 system/init 之后的 user 事件,调用方从最后的 result 得到回答与用量。assistant 里的 tool_use 与随后 user 里的 tool_result 用同一个 id 对应(图中的 W、R)。
要点:
- 一次模型调用返回几个内容块,就有几个
assistant事件,它们的message.id相同。每个事件的message.content只含当前这一个块。 - 每个工具调用对应一个
user事件,message.content[0].tool_use_id对应assistant事件里tool_use块的id。一次调用里有多个工具调用时,user事件按完成顺序出现,可能与调用顺序不同。 result之后还可能有system/task_summary,所以result不一定是最后一行。- 后台任务(后台 Bash 命令、Workflow)完成时,进程继续运行,再输出一次
system/init、新一轮的assistant与一个新的result。两个result用result_index(0、1)区分,第二个带origin。进程在所有后台任务结束后退出。
下面是一次带两个 subagent 的运行:主 agent 在一次模型调用里启动两个 subagent,一个写文件,一个运行命令,各自交回报告后主 agent 汇总回答。中间两列是 subagent 内部的事件,它们带 parent_tool_use_id,值为启动它的 Agent 调用的 id(图中的 A、B)。task_* 事件在主 agent 一列,用 tool_use_id 或 task_id 指向对应的 subagent。各字段见「subagent 与后台任务」。
开启逐字输出后,每次模型调用周围多出 stream_event,assistant 事件出现在对应内容块的 content_block_stop 之前:
类型总览
从本节开始,事件的字段用 TypeScript 类型定义描述。写法约定:? 表示字段可能缺失;| null 表示观测到过 null;字符串字面量的并集是观测到的全部取值,没有标注来源的定义都来自样本;注释里以「帮助文本」「文档」开头的内容没有样本,只有 claude --help 或官方文档作依据。
type StreamLine =
// 只在 Claude 的 Cloud Managed 容器里观测到,见「版本与环境说明」
| ActiveGoal | AutocompactState | RateLimitEvent
| SystemEvent
| AssistantEvent
| UserEvent
| StreamEventLine
| ResultEvent;
interface ActiveGoal { type: "active_goal"; value: null; session_id: string; uuid: string; }
interface AutocompactState { type: "autocompact_state"; value: { source: "env"; [key: string]: unknown }; session_id: string; uuid: string; }
interface RateLimitEvent { type: "rate_limit_event"; rate_limit_info: { [key: string]: unknown }; session_id: string; uuid: string; }
// 所有事件共有的三个字段
interface EventBase {
type: string;
session_id: string; // 等于 --session-id 的值;subagent 的事件与主 agent 相同
uuid: string; // 这一行的唯一编号;system/api_retry 没有
}
system 事件
agentrun 中处理这类事件的是 ClaudeCode::translate 里 type 为 system 的分支。
type SystemEvent =
| SystemInit | SystemStatus | SystemTaskSummary | SystemPostTurnSummary
| SystemThinkingTokens | SystemApiRetry | SystemPermissionDenied
| SystemHookStarted | SystemHookResponse | SystemBackgroundTasksChanged
// 后四种见「subagent 与后台任务」
| SystemTaskStarted | SystemTaskProgress | SystemTaskUpdated | SystemTaskNotification;
init
运行开始时输出一次,描述这次会话的配置。字段多,解析器一般只需要 model、tools、permissionMode、claude_code_version、cwd。
interface SystemInit extends EventBase {
type: "system";
subtype: "init";
cwd: string; // 工作目录
// 主模型 id,例如 "claude-sonnet-5-5";模型名不存在时原样给出传入的名字
model: string;
permissionMode: string; // 权限模式,例如 "auto"、"default"
// 可用工具名。启动 subagent 的工具在这里叫 "Task",在 tool_use 块里叫 "Agent"
tools: string[];
// 可用的 subagent 类型,例如 "general-purpose"、"Explore"、"Plan"
agents: string[];
mcp_servers: unknown[]; // 已加载的 MCP 服务器,观测值为空数组
skills: string[];
slash_commands: string[];
terminal_slash_commands: string[];
plugins: { name: string; path: string; source: string }[];
apiKeySource: "none" | "ANTHROPIC_API_KEY"; // "none" 表示订阅登录
claude_code_version: string; // 例如 "2.1.288"
output_style: "default";
view_mode: "default";
capabilities: string[]; // 协议能力标识,例如 "msg_lifecycle_v1"
memory_paths: { auto: string; team: string };
scratchpad_path: string; // 临时目录
messaging_socket_path: string; // 进程间通信 socket 的路径
fast_mode_state: "off";
fast_mode_disabled_reason: "sdk_opt_in_required";
per_turn_effort_active: boolean;
analytics_disabled: boolean;
product_feedback_disabled: boolean;
// 启动各阶段耗时,键名以 _ms 结尾;诊断用,键集随版本变化
startup_timing: { phases: { [name: string]: number } };
}
{
"type": "system",
"subtype": "init",
"cwd": "/work/repo",
"session_id": "SESSION_ID",
"tools": ["Task", "Bash", "Edit", "Glob", "Grep", "Read", "Write", "WebFetch", "WebSearch"],
"mcp_servers": [],
"model": "claude-sonnet-5-5",
"permissionMode": "auto",
"slash_commands": ["compact", "init"],
"terminal_slash_commands": ["doctor"],
"apiKeySource": "none",
"claude_code_version": "2.1.288",
"output_style": "default",
"agents": ["Explore", "general-purpose", "Plan"],
"skills": [],
"plugins": [],
"capabilities": ["msg_lifecycle_v1"],
"analytics_disabled": false,
"product_feedback_disabled": false,
"uuid": "UUID",
"memory_paths": { "auto": "/tmp/claude/memory/", "team": "/tmp/claude/memory/team/" },
"scratchpad_path": "/tmp/.../scratchpad",
"messaging_socket_path": "/tmp/.../cc-socks/1.sock",
"fast_mode_state": "off",
"fast_mode_disabled_reason": "sdk_opt_in_required",
"per_turn_effort_active": true,
"view_mode": "default",
"startup_timing": { "phases": { "node_boot_ms": 146 } }
}
status、task_summary、post_turn_summary、thinking_tokens、api_retry
interface SystemStatus extends EventBase {
type: "system";
subtype: "status";
status: "requesting"; // 正在向模型发请求,每次模型调用前一次
}
interface SystemTaskSummary extends EventBase {
type: "system";
subtype: "task_summary";
// 当前动作的一句描述,例如 "Writing probe-r1.txt";result 之后的那一次为 null
detail: string | null;
}
interface SystemPostTurnSummary extends EventBase {
type: "system";
subtype: "post_turn_summary";
summarizes_uuid: string; // 被总结的那个 assistant 事件的 uuid
status_category: "completed" | "review_ready";
status_detail: string; // 一句话结果
needs_action: string; // 需要用户做的事,观测值为空字符串
}
interface SystemThinkingTokens extends EventBase {
type: "system";
subtype: "thinking_tokens";
estimated_tokens: number; // 到目前为止 thinking 的估计 token 数
estimated_tokens_delta: number; // 与上一次相比的增量
}
// 没有 uuid
interface SystemApiRetry {
type: "system";
subtype: "api_retry";
session_id: string;
attempt: number; // 第几次重试,从 1 开始
max_retries: number; // 观测值 300
retry_delay_ms: number; // 重试前等待的毫秒数
error_status: number; // HTTP 状态码,例如 401
error: string; // 错误类别,例如 "authentication_failed"
}
认证失败时观测到重试两次后放弃,流程见「错误、中断与退出码」。
permission_denied
一次工具调用需要确认而没有人能确认时出现,随后的 user 事件带 is_error: true 的 tool_result,同一段文字作为工具结果交给模型。
interface SystemPermissionDenied extends EventBase {
type: "system";
subtype: "permission_denied";
tool_name: string; // 被拒绝的工具名
tool_use_id: string; // 被拒绝的 tool_use 块的 id
decision_reason_type: "asyncAgent"; // 拒绝原因的类别
decision_reason: string; // 一句话原因
message: string; // 交给模型的完整说明
}
{
"type": "system",
"subtype": "permission_denied",
"tool_name": "Bash",
"tool_use_id": "toolu_01A",
"decision_reason_type": "asyncAgent",
"decision_reason": "no approval surface in this session; permission request denied automatically",
"message": "Permission for this tool use was denied. ...",
"uuid": "UUID",
"session_id": "SESSION_ID"
}
hook_started、hook_response
需要 --include-hook-events。每个 hook 命令先后产生两个事件,用 hook_id 关联。
interface SystemHookStarted extends EventBase {
type: "system";
subtype: "hook_started";
hook_id: string; // 这次 hook 执行的 id
hook_name: string; // "事件:匹配器",例如 "PreToolUse:Bash"
hook_event: string; // hook 事件名,例如 "PreToolUse"、"PostToolUse"
}
interface SystemHookResponse extends EventBase {
type: "system";
subtype: "hook_response";
hook_id: string;
hook_name: string;
hook_event: string;
output: string; // hook 命令的输出
stdout: string;
stderr: string;
exit_code: number;
outcome: "success";
}
{
"type": "system",
"subtype": "hook_started",
"hook_id": "HOOK_ID",
"hook_name": "PreToolUse:Bash",
"hook_event": "PreToolUse",
"uuid": "UUID",
"session_id": "SESSION_ID"
}
{
"type": "system",
"subtype": "hook_response",
"hook_id": "HOOK_ID",
"hook_name": "PreToolUse:Bash",
"hook_event": "PreToolUse",
"output": "",
"stdout": "",
"stderr": "",
"exit_code": 0,
"outcome": "success",
"uuid": "UUID",
"session_id": "SESSION_ID"
}
background_tasks_changed
后台任务列表变化时输出完整的当前列表,列表为空时 tasks 为 []。
interface SystemBackgroundTasksChanged extends EventBase {
type: "system";
subtype: "background_tasks_changed";
tasks: {
task_id: string;
task_type: "local_bash" | "local_workflow";
description: string;
}[];
}
assistant 事件
模型的每个内容块一个事件。agentrun 中处理这类事件的是 ClaudeCode::translate 里 type 为 assistant 的分支。
interface AssistantEvent extends EventBase {
type: "assistant";
message: AssistantMessage; // Anthropic Messages API 的消息对象
// 主 agent 为 null;subagent 内部的事件是启动它的 Agent 调用的 id
parent_tool_use_id: string | null;
request_id: string; // API 请求 id,"req_" 开头
timestamp: string; // ISO 8601,UTC,毫秒
// 发送给工具的参数;只在含 tool_use 块的事件上,subagent 的事件上未观测到
wire_tool_inputs?: { [toolUseId: string]: object };
thinking_duration_ms?: number; // 只在含 thinking 块的事件上
subagent_type?: string; // 只在 subagent 内部的事件上
task_description?: string; // 同上
// API 错误类别,例如 "authentication_failed"、"model_not_found";只在合成的错误消息上
error?: string;
// true 表示这条消息由 claude-code 合成,message.model 为 "<synthetic>"
is_api_error_message?: boolean;
}
interface AssistantMessage {
// "msg_" 开头,同一次模型调用的各个块相同;合成消息是一个 uuid
id: string;
type: "message";
role: "assistant";
model: string; // 实际响应的模型 id;合成消息为 "<synthetic>"
content: ContentBlock[]; // 只含一个内容块
// 正常块为 null;合成消息为 "stop_sequence"。整次调用的 stop_reason 在 stream_event 的
// message_delta 与 result.stop_reason 里
stop_reason: null | "stop_sequence";
stop_sequence: null | "";
stop_details: null;
container: null;
context_management: null;
diagnostics: null;
input_transformations?: unknown[]; // 观测值为空数组;合成消息上没有
// 这次模型调用的用量,同一次调用的各个块相同,累加时按 message.id 去重
usage: Usage;
}
usage 对象
出现在 assistant.message.usage、stream_event 的 message_start 与 message_delta、result.usage、Agent 工具结果的 tool_use_result.usage。各处字段集略有不同,注释里写出。
interface Usage {
input_tokens: number; // 未命中缓存的输入 token,命中缓存时很小,例如 2
output_tokens: number; // 输出 token,含 thinking
cache_read_input_tokens: number; // 从提示缓存读取的输入 token
cache_creation_input_tokens: number; // 写入提示缓存的输入 token
// 按缓存保留时长拆分
cache_creation?: { ephemeral_5m_input_tokens: number; ephemeral_1h_input_tokens: number };
service_tier?: "standard" | null;
inference_geo?: "not_available" | "" | null;
// result 与 message_delta 上有,assistant 上没有
output_tokens_details?: { thinking_tokens: number } | null;
// result 与合成消息上有
server_tool_use?: { web_search_requests: number; web_fetch_requests: number };
iterations?: UsageIteration[] | null; // 每次迭代的用量;result 与 message_delta 上有
speed?: "standard" | null; // result 上有
fallback_credit?: null; // result 上有
}
interface UsageIteration {
type: "message";
input_tokens: number;
output_tokens: number;
cache_read_input_tokens: number;
cache_creation_input_tokens: number;
}
内容块
type ContentBlock = TextBlock | ThinkingBlock | ToolUseBlock;
interface TextBlock {
type: "text";
text: string;
}
interface ThinkingBlock {
type: "thinking";
thinking: string; // 观测值都是空字符串,正文没有输出到流里
signature: string; // base64
}
interface ToolUseBlock {
type: "tool_use";
id: string; // "toolu_" 开头
// 工具名,例如 "Bash"、"Read"、"Write"、"Edit"、"Agent"、"Skill"、"Workflow"、
// "StructuredOutput"
name: string;
input: ToolInput; // 参数,结构由工具决定
caller: { type: "direct" };
}
type ToolInput =
// Bash
| { command: string; description?: string; timeout?: number; run_in_background?: boolean }
// Read
| { file_path: string }
// Write
| { file_path: string; content: string }
// Edit
| { file_path: string; old_string: string; new_string: string; replace_all?: boolean }
// Agent
| { description: string; prompt: string; subagent_type: string; run_in_background?: boolean }
// Skill
| { skill: string }
// Workflow
| { script: string }
// StructuredOutput,由 --json-schema 决定
| { [key: string]: unknown };
{
"type": "assistant",
"message": {
"model": "claude-sonnet-5-5",
"id": "msg_01A",
"type": "message",
"role": "assistant",
"content": [
{
"type": "tool_use",
"id": "toolu_01A",
"name": "Bash",
"input": { "command": "cargo test", "description": "Run tests" },
"caller": { "type": "direct" }
}
],
"container": null,
"stop_reason": null,
"stop_sequence": null,
"stop_details": null,
"usage": {
"input_tokens": 2,
"cache_creation_input_tokens": 4950,
"cache_read_input_tokens": 28275,
"cache_creation": { "ephemeral_5m_input_tokens": 0, "ephemeral_1h_input_tokens": 4950 },
"output_tokens": 16,
"service_tier": "standard",
"inference_geo": "not_available"
},
"input_transformations": [],
"diagnostics": null,
"context_management": null
},
"parent_tool_use_id": null,
"session_id": "SESSION_ID",
"uuid": "UUID",
"timestamp": "2026-10-03T15:29:17.247Z",
"request_id": "req_01A",
"wire_tool_inputs": {
"toolu_01A": { "command": "cargo test", "description": "Run tests" }
}
}
API 错误时的合成消息:
{
"type": "assistant",
"message": {
"id": "UUID",
"model": "<synthetic>",
"role": "assistant",
"type": "message",
"stop_reason": "stop_sequence",
"stop_sequence": "",
"container": null,
"stop_details": null,
"usage": {
"input_tokens": 0,
"output_tokens": 0,
"cache_creation_input_tokens": 0,
"cache_read_input_tokens": 0,
"cache_creation": { "ephemeral_1h_input_tokens": 0, "ephemeral_5m_input_tokens": 0 },
"server_tool_use": { "web_search_requests": 0, "web_fetch_requests": 0 },
"service_tier": null,
"inference_geo": null,
"iterations": null,
"speed": null,
"fallback_credit": null,
"output_tokens_details": null
},
"content": [
{ "type": "text", "text": "Authentication error · This may be a temporary network issue, please try again" }
],
"context_management": null,
"diagnostics": null
},
"parent_tool_use_id": null,
"session_id": "SESSION_ID",
"uuid": "UUID",
"timestamp": "2026-10-03T15:31:59.550Z",
"error": "authentication_failed",
"request_id": "req_01A",
"is_api_error_message": true
}
user 事件
工具结果与若干种注入的用户消息都用 user 事件表示。agentrun 中处理这类事件的是 ClaudeCode::translate 里 type 为 user 的分支。
interface UserEvent extends EventBase {
type: "user";
message: {
role: "user";
// 只含一个块;回显的提示词是字符串
content: [ToolResultBlock] | [TextBlock] | string;
};
parent_tool_use_id: string | null;
timestamp: string; // ISO 8601
// 工具的原始结果,只在工具结果事件上。失败时是以 "Error: " 开头的字符串
tool_use_result?: ToolUseResult | string;
// 标记没有实际执行的工具调用,只在被拒绝的工具结果上
tool_result_meta?: { id: string; non_execution_kind: "permission-rule" }[];
subagent_type?: string; // 只在 subagent 内部的事件上
task_description?: string; // 同上
// true 表示这条消息由 claude-code 注入,例如 Skill 工具加载的技能说明
isSynthetic?: boolean;
// true 表示这是 --replay-user-messages 回显的用户消息
isReplay?: true;
}
interface ToolResultBlock {
type: "tool_result";
tool_use_id: string; // 对应的 tool_use 块的 id
// 交给模型的结果。多数工具是字符串;Agent 工具是 TextBlock 数组
content: string | TextBlock[];
is_error?: boolean; // 失败时为 true。成功时多数没有这个字段,少数为 false
}
Bash 命令退出码非 0 时 is_error 为 true,content 以 Exit code N 开头。被 claude-code 自身拦截的命令(例如本环境拦截单独的 sleep)的 content 包在 <tool_use_error> 标签里。
tool_use_result 按工具
type ToolUseResult =
| BashResult | ReadResult | WriteResult | EditResult | SkillResult | WorkflowResult
| AgentResult // 见「subagent 与后台任务」
| "Structured output provided successfully"; // StructuredOutput
interface BashResult {
stdout: string;
stderr: string;
interrupted: boolean;
isImage: boolean;
noOutputExpected: boolean;
backgroundTaskId?: string; // 只在 run_in_background 时
}
interface ReadResult {
type: "text";
file: { filePath: string; content: string; numLines: number; startLine: number; totalLines: number };
}
interface WriteResult {
type: "create";
filePath: string;
content: string;
structuredPatch: Hunk[];
originalFile: null;
userModified: boolean;
}
interface EditResult {
filePath: string;
oldString: string;
newString: string;
originalFile: string;
replaceAll: boolean;
userModified: boolean;
structuredPatch: Hunk[];
}
interface Hunk { // 统一 diff 的一个块
oldStart: number;
oldLines: number;
newStart: number;
newLines: number;
lines: string[];
}
interface SkillResult {
commandName: string; // 技能名
content: string; // 技能说明全文
}
interface WorkflowResult {
status: "async_launched";
taskId: string;
taskType: "local_workflow";
workflowName: string;
runId: string;
summary: string;
transcriptDir: string;
scriptPath: string;
}
{
"type": "user",
"message": {
"role": "user",
"content": [
{ "tool_use_id": "toolu_01A", "type": "tool_result", "content": "1\thello probe" }
]
},
"parent_tool_use_id": null,
"session_id": "SESSION_ID",
"uuid": "UUID",
"timestamp": "2026-10-03T15:29:18.596Z",
"tool_use_result": {
"type": "text",
"file": {
"filePath": "/work/repo/probe-r1.txt",
"content": "hello probe",
"numLines": 1,
"startLine": 1,
"totalLines": 1
}
}
}
{
"type": "user",
"message": {
"role": "user",
"content": [
{
"type": "tool_result",
"content": "Exit code 1\n/bin/bash: line 1: /root/x: Read-only file system",
"is_error": true,
"tool_use_id": "toolu_01B"
}
]
},
"parent_tool_use_id": null,
"session_id": "SESSION_ID",
"uuid": "UUID",
"timestamp": "2026-10-03T15:33:14.034Z",
"tool_use_result": "Error: Exit code 1\n/bin/bash: line 1: /root/x: Read-only file system"
}
文字类的 user 消息
--replay-user-messages 回显的提示词是一个 message.content 为字符串、带 isReplay: true 的 user 事件,parent_tool_use_id 为 null。message.content[0].type 为 text 的 user 事件有三种:subagent 收到的提示词(带 parent_tool_use_id,文字等于 Agent 调用的 prompt);SIGINT 中断时的 [Request interrupted by user];isSynthetic: true 的注入内容。这些事件没有 tool_use_result。
stream_event 事件
需要 --include-partial-messages,或把环境变量 CLAUDE_CODE_INCLUDE_PARTIAL_MESSAGES 设为 true。每个事件包一个 Anthropic Messages API 的流式事件。
interface StreamEventLine extends EventBase {
type: "stream_event";
event: ApiStreamEvent;
parent_tool_use_id: null; // 观测值都是 null,subagent 的模型调用没有产生 stream_event
ttft_ms?: number; // 首个 token 的延迟;只在 message_start 上
thinking_display?: "updates"; // message_start 与 thinking 块的事件上
}
type ApiStreamEvent =
// 一次模型调用开始。content 为空数组,usage 里已有输入侧的 token 数
| { type: "message_start"; message: AssistantMessage }
// 第 index 个内容块开始
| { type: "content_block_start"; index: number; content_block: EmptyContentBlock }
| { type: "content_block_delta"; index: number; delta: BlockDelta }
// 块结束。完整的块在此之前已作为 assistant 事件输出
| { type: "content_block_stop"; index: number }
| { type: "message_delta"; // 调用结束前的汇总
delta: { stop_reason: "end_turn" | "tool_use"; stop_sequence: null; stop_details: null; container: null };
// 这次调用的最终用量,含 output_tokens_details 与 iterations
usage: Usage;
context_management: { applied_edits: [] } }
| { type: "message_stop" };
type EmptyContentBlock =
| { type: "text"; text: "" }
| { type: "thinking"; thinking: ""; signature: "" }
| { type: "tool_use"; id: string; name: string; input: {}; caller: { type: "direct" } };
type BlockDelta =
| { type: "text_delta"; text: string }
// 观测到 thinking 为空字符串
| { type: "thinking_delta"; thinking: string; estimated_tokens: number | null }
| { type: "signature_delta"; signature: string }
// 工具参数 JSON 的片段,拼接后是 tool_use.input;第一个片段可能是空字符串
| { type: "input_json_delta"; partial_json: string };
解析器可以只用 assistant 事件得到完整的块,用 stream_event 做实时显示。中断时流可能停在任意一个 content_block_delta 之后,没有对应的 assistant 事件。
{
"type": "stream_event",
"event": {
"type": "message_start",
"message": {
"model": "claude-sonnet-5-5",
"id": "msg_01A",
"type": "message",
"role": "assistant",
"content": [],
"stop_reason": null,
"usage": {
"input_tokens": 2,
"cache_creation_input_tokens": 4950,
"cache_read_input_tokens": 28275,
"output_tokens": 16,
"service_tier": "standard"
}
}
},
"session_id": "SESSION_ID",
"parent_tool_use_id": null,
"uuid": "UUID",
"ttft_ms": 521,
"thinking_display": "updates"
}
{
"type": "stream_event",
"event": {
"type": "content_block_start",
"index": 0,
"content_block": { "type": "tool_use", "id": "toolu_01A", "name": "Bash", "input": {}, "caller": { "type": "direct" } }
},
"session_id": "SESSION_ID",
"parent_tool_use_id": null,
"uuid": "UUID"
}
{
"type": "stream_event",
"event": {
"type": "content_block_delta",
"index": 0,
"delta": { "type": "input_json_delta", "partial_json": "{\"command\": \"cargo" }
},
"session_id": "SESSION_ID",
"parent_tool_use_id": null,
"uuid": "UUID"
}
{
"type": "stream_event",
"event": { "type": "content_block_stop", "index": 0 },
"session_id": "SESSION_ID",
"parent_tool_use_id": null,
"uuid": "UUID"
}
{
"type": "stream_event",
"event": {
"type": "message_delta",
"delta": { "stop_reason": "tool_use", "stop_sequence": null, "stop_details": null, "container": null },
"usage": {
"input_tokens": 2,
"cache_creation_input_tokens": 4950,
"cache_read_input_tokens": 28275,
"output_tokens": 108,
"output_tokens_details": { "thinking_tokens": 0 },
"iterations": [
{ "input_tokens": 2, "output_tokens": 108, "cache_read_input_tokens": 28275, "cache_creation_input_tokens": 4950, "type": "message" }
]
},
"context_management": { "applied_edits": [] }
},
"session_id": "SESSION_ID",
"parent_tool_use_id": null,
"uuid": "UUID"
}
{
"type": "stream_event",
"event": { "type": "message_stop" },
"session_id": "SESSION_ID",
"parent_tool_use_id": null,
"uuid": "UUID"
}
result 事件
一轮对话结束时输出。subtype 与 is_error 合起来判断成败:
| subtype | is_error | terminal_reason | 情形 | 退出码 |
|---|---|---|---|---|
success | false | completed | 正常完成。工具失败、权限被拒都不改变这个状态 | 0 |
success | true | api_error | API 返回错误(认证失败、模型不存在),api_error_status 是 HTTP 状态码,result 是合成的错误文字 | 1 |
error_during_execution | true | aborted_streaming | SIGINT 中断。errors 含诊断字符串,stop_reason 为 null | 0 |
error_max_turns | true | max_turns | 超过 --max-turns。errors 为 ["Reached maximum number of turns (N)"],没有 result 字段 | 1 |
error_max_budget_usd | true | budget_exhausted | 超过 --max-budget-usd。errors 为 ["Reached maximum budget ($N)"],没有 result 字段 | 1 |
agentrun 中处理这类事件的是 ClaudeCode::translate 里 type 为 result 的分支,它记下最后一个 result,ClaudeCode::failure 读这个 result 判断成败。
interface ResultEvent extends EventBase {
type: "result";
subtype: "success" | "error_during_execution" | "error_max_turns" | "error_max_budget_usd";
is_error: boolean; // 这一轮是否失败
terminal_reason: "completed" | "api_error" | "aborted_streaming" | "max_turns" | "budget_exhausted";
// 主 agent 最后一段文字;--json-schema 时是结构化结果的 JSON 文本;限额失败时没有
result?: string;
// 按 --json-schema 校验过的结果对象,只在给了 --json-schema 时
structured_output?: object;
errors?: string[]; // 只在失败时
api_error_status?: number | null; // API 错误的 HTTP 状态码;限额失败与中断时没有这个字段
// 最后一次模型调用的 stop_reason;中断时为 null
stop_reason: "end_turn" | "tool_use" | "stop_sequence" | null;
num_turns: number; // 这一轮里模型调用的次数,含失败的
duration_ms: number; // 总耗时
duration_api_ms: number; // 等待 API 的耗时
total_cost_usd: number; // modelUsage 各项 costUSD 之和
// 主 agent 模型调用的用量合计,不含 subagent;中断与限额失败时可能全为 0
usage: Usage;
modelUsage: { [modelId: string]: ModelUsage }; // 包含 subagent 的用量
// 无拒绝时为 []
permission_denials: { tool_name: string; tool_use_id: string; tool_input: object }[];
subagent_stats?: SubagentStats;
result_index: number; // 这次运行里第几个 result,从 0 开始
origin?: { kind: "task-notification"; producer: "session-task" }; // 只在后台任务触发的轮次上
queued_turn_count: number; // 排队中的轮次数,观测值 0
fast_mode_state?: "off";
fast_mode_disabled_reason?: "sdk_opt_in_required";
// 以下是启动与首个 token 的计时诊断,只在正常完成的 result 上;键集随版本变化,解析器不应依赖
ttft_ms?: number;
ttft_stream_ms?: number;
first_content_frame_ms?: number;
time_to_request_ms?: number;
time_to_request_phases_ms?: object;
time_to_request_cpu_ms?: number;
time_to_request_loop_lag_ms?: number;
time_to_request_major_faults?: number;
time_to_request_from_spawn_ms?: number;
time_origin_ms?: number;
input_attachments_detail?: unknown;
turn_start_resume_kind?: string;
process_turn_index?: number;
warm_spare_claimed?: boolean;
flag_fetch_kick?: unknown;
}
interface ModelUsage {
inputTokens: number;
outputTokens: number;
cacheReadInputTokens: number;
cacheCreationInputTokens: number;
thinkingTokens: number;
webSearchRequests: number;
costUSD: number;
costBasis: "list"; // 按定价表计费
provider: "firstParty";
canonicalModel: string; // 规范模型名,例如 "claude-haiku-4-5"
contextWindow: number;
maxOutputTokens: number;
}
interface SubagentStats {
spawned: number;
completed: number;
failed: number;
requested: { background: number; foreground: number; unset: number }; // 按请求的运行方式计数
started_in_background: number;
spawned_by_subagents: number;
max_depth: number; // 最大嵌套深度
killed: { parent: number; user: number; system: number };
refused: { depth_limit: number; concurrency_limit: number; budget: number };
by_type: { [subagentType: string]: number }; // 例如 { "general-purpose": 2 }
}
每次运行的 modelUsage 里都有一个 claude-haiku-4-5-* 项,约一千个输入 token,流里没有对应的 assistant 事件。这是 claude-code 内部的辅助调用(例如 auto 权限模式的分类器),统计费用时要计入,统计主模型用量时要排除。
{
"type": "result",
"subtype": "success",
"is_error": false,
"result": "The file `probe-r1.txt` contains: `hello probe`",
"stop_reason": "end_turn",
"terminal_reason": "completed",
"api_error_status": null,
"num_turns": 3,
"duration_ms": 5256,
"duration_api_ms": 3915,
"total_cost_usd": 0.0436916,
"usage": {
"input_tokens": 6,
"cache_creation_input_tokens": 5300,
"cache_read_input_tokens": 94923,
"output_tokens": 248,
"output_tokens_details": { "thinking_tokens": 32 },
"server_tool_use": { "web_search_requests": 0, "web_fetch_requests": 0 },
"service_tier": "standard",
"cache_creation": { "ephemeral_1h_input_tokens": 5300, "ephemeral_5m_input_tokens": 0 },
"inference_geo": "not_available",
"iterations": [
{ "input_tokens": 2, "output_tokens": 23, "cache_read_input_tokens": 33423, "cache_creation_input_tokens": 152, "type": "message" }
],
"speed": "standard",
"fallback_credit": null
},
"modelUsage": {
"claude-haiku-4-5-20251001": {
"inputTokens": 925,
"outputTokens": 18,
"cacheReadInputTokens": 0,
"cacheCreationInputTokens": 0,
"webSearchRequests": 0,
"costUSD": 0.001015,
"contextWindow": 200000,
"maxOutputTokens": 32000,
"thinkingTokens": 0,
"canonicalModel": "claude-haiku-4-5",
"provider": "firstParty",
"costBasis": "list"
},
"claude-sonnet-5-5": {
"inputTokens": 6,
"outputTokens": 248,
"cacheReadInputTokens": 94923,
"cacheCreationInputTokens": 5300,
"webSearchRequests": 0,
"costUSD": 0.0426766,
"contextWindow": 1000000,
"maxOutputTokens": 128000,
"thinkingTokens": 32,
"canonicalModel": "claude-sonnet-5-5",
"provider": "firstParty",
"costBasis": "list"
}
},
"permission_denials": [],
"subagent_stats": {
"spawned": 0,
"requested": { "background": 0, "foreground": 0, "unset": 0 },
"started_in_background": 0,
"max_depth": 0,
"spawned_by_subagents": 0,
"completed": 0,
"failed": 0,
"killed": { "parent": 0, "user": 0, "system": 0 },
"refused": { "depth_limit": 0, "concurrency_limit": 0, "budget": 0 },
"by_type": {}
},
"fast_mode_state": "off",
"fast_mode_disabled_reason": "sdk_opt_in_required",
"session_id": "SESSION_ID",
"uuid": "UUID",
"result_index": 0,
"queued_turn_count": 0,
"ttft_ms": 2249
}
subagent 与后台任务
主 agent 用名为 Agent 的工具启动 subagent(system/init 的 tools 列表里这个工具叫 Task,--tools 与 --disallowedTools 也用 Task 这个名字)。一次 subagent 的完整事件序列:
要点:
- subagent 内部的
assistant与user事件都带parent_tool_use_id,值等于 Agent 调用的tool_useid;还带subagent_type与task_description。主 agent 的事件parent_tool_use_id为 null。 - 多个 subagent 并行时,它们的事件与主 agent 的事件交错出现,用
parent_tool_use_id归属。subagent 再启动 subagent 时嵌套规则相同,task_started.spawn_depth给出深度。观测到的最大深度为 1。 - subagent 内部的
assistant.message.usage是它自己每次模型调用的用量;result.usage不包含它们,result.modelUsage包含。 - subagent 的模型调用没有产生
stream_event,也没有system/status。 - subagent 最后通过
SubagentHandback工具交回报告,报告正文在主 agent 收到的工具结果的tool_use_result.handbackReport.text里。
task_* 事件
type TaskType = "local_agent" | "local_workflow" | "local_bash"; // subagent、Workflow 工具、后台 Bash 命令
interface TaskUsage { // 到目前为止或最终的累计
total_tokens: number; // 该任务所有模型调用的 token 总和
tool_uses: number;
duration_ms: number;
}
interface SystemTaskStarted extends EventBase {
type: "system";
subtype: "task_started";
task_id: string; // 任务 id,subagent 的 id 也是它的 agentId
tool_use_id: string; // 启动它的工具调用 id
task_type: TaskType;
description: string;
prompt?: string; // subagent 的提示词或 Workflow 脚本;local_bash 没有
subagent_type?: string; // 只有 local_agent 有
is_backgrounded?: boolean; // local_workflow 没有
spawn_depth?: number; // 嵌套深度,直接由主 agent 启动时为 1;只有 local_agent 有
workflow_name?: string; // 只有 local_workflow 有
}
interface SystemTaskProgress extends EventBase {
type: "system";
subtype: "task_progress";
task_id: string;
tool_use_id: string;
description: string; // 当前进度的一句描述
subagent_type?: string; // 只有 local_agent 有
usage: TaskUsage;
last_tool_name?: string; // 最近调用的工具名
summary?: string; // 只有 local_workflow 有
workflow_progress?: WorkflowProgressItem[]; // 只有 local_workflow 有
}
interface SystemTaskUpdated extends EventBase {
type: "system";
subtype: "task_updated";
task_id: string;
patch: { status: "completed" | "killed"; end_time: number }; // end_time 是毫秒时间戳
}
interface SystemTaskNotification extends EventBase {
type: "system";
subtype: "task_notification";
task_id: string;
tool_use_id: string;
status: "completed" | "stopped";
summary: string; // 一句话结果
output_file: string; // 任务输出文件的路径,可能为空字符串
usage?: TaskUsage; // 这个任务的最终用量;后台 Bash 没有
}
type WorkflowProgressItem =
| { type: "workflow_phase"; index: number; title: string }
| { type: "workflow_agent";
index: number; label: string; phaseIndex: number; phaseTitle: string;
agentId: string; model: string;
state: "start" | "progress" | "done"; attempt: number;
queuedAt: number; startedAt: number; lastProgressAt: number; durationMs: number;
tokens: number; toolCalls: number; lastToolName: string; lastToolSummary: string;
promptPreview: string; promptFramed: boolean; resultPreview: string };
{
"type": "system",
"subtype": "task_started",
"task_id": "AGENT_ID",
"tool_use_id": "toolu_01P",
"description": "Create sub1.txt",
"subagent_type": "general-purpose",
"is_backgrounded": false,
"spawn_depth": 1,
"task_type": "local_agent",
"prompt": "Create a file named sub1.txt ...",
"uuid": "UUID",
"session_id": "SESSION_ID"
}
{
"type": "system",
"subtype": "task_progress",
"task_id": "AGENT_ID",
"tool_use_id": "toolu_01P",
"description": "Writing sub1.txt",
"subagent_type": "general-purpose",
"usage": { "total_tokens": 24591, "tool_uses": 1, "duration_ms": 1262 },
"last_tool_name": "Write",
"uuid": "UUID",
"session_id": "SESSION_ID"
}
{
"type": "system",
"subtype": "task_updated",
"task_id": "AGENT_ID",
"patch": { "status": "completed", "end_time": 1791041391076 },
"uuid": "UUID",
"session_id": "SESSION_ID"
}
{
"type": "system",
"subtype": "task_notification",
"task_id": "AGENT_ID",
"tool_use_id": "toolu_01P",
"status": "completed",
"output_file": "/tmp/.../tasks/AGENT_ID.output",
"summary": "This agent's report was delivered to you as a message from \"AGENT_ID\" ...",
"usage": { "total_tokens": 24865, "tool_uses": 2, "duration_ms": 4473 },
"uuid": "UUID",
"session_id": "SESSION_ID"
}
Agent 工具结果的 tool_use_result
interface AgentResult {
status: "completed";
agentId: string; // 等于 task_id
agentType: string;
prompt: string; // subagent 收到的提示词
handback: "send"; // 报告交回方式
handbackReport: { text: string }; // subagent 的报告正文
content: TextBlock[]; // 交给主 agent 的文字块
resolvedModel: string; // subagent 使用的模型
totalDurationMs: number;
totalTokens: number; // 累计 token,usage 只是最后一次调用
totalToolUseCount: number;
usage: Usage; // subagent 最后一次模型调用的用量
toolStats: {
readCount: number; searchCount: number; bashCount: number; editFileCount: number;
linesAdded: number; linesRemoved: number; otherToolCount: number;
};
harnessNoteCount: number; // 内部字段
harnessTailCount: number;
harnessSectionHash: string;
}
后台 Bash 命令与 Workflow
Bash 工具带 run_in_background: true 时,工具结果立即返回,tool_use_result.backgroundTaskId 给出任务 id,随后出现 background_tasks_changed、task_started(task_type: local_bash,is_backgrounded: true)。命令结束后出现 task_notification(没有 usage)、background_tasks_changed、task_updated,然后 claude-code 开始新一轮:再输出 system/init,模型处理通知,输出新的 result。
Workflow 工具(task_type: local_workflow)按脚本启动多个 subagent。它的内部 agent 不产生带 parent_tool_use_id 的 assistant 与 user 事件,进度只在 task_progress.workflow_progress 里。
错误、中断与退出码
| 情形 | 退出码 | 流里的表现 |
|---|---|---|
| 正常完成 | 0 | 最后一个 result 的 is_error 为 false |
| 工具失败(命令退出码非 0、文件不存在) | 0 | user 事件的 tool_result.is_error 为 true,模型继续,result 正常 |
| 权限被拒 | 0 | system/permission_denied,result.permission_denials 非空,is_error 为 false |
| 认证失败(401) | 1 | system/api_retry 两次,一个合成的 assistant(error: authentication_failed),result 的 is_error 为 true、api_error_status 为 401、terminal_reason 为 api_error。观测耗时约 120 秒 |
| 模型不存在(404) | 1 | 标准错误一行 [claude-code:unrecognized_model] {...};流里是合成的 assistant(error: model_not_found)与 api_error_status 为 404 的 result,没有 api_retry |
超过 --max-turns | 1 | result.subtype 为 error_max_turns |
超过 --max-budget-usd | 1 | result.subtype 为 error_max_budget_usd |
| 未知命令行选项 | 1 | 标准输出为空,标准错误 error: unknown option '--xxx' |
缺少 --verbose | 1 | 标准输出为空,标准错误 Error: When using --print, --output-format=stream-json requires --verbose |
| SIGINT | 0 | 流停在当前位置,然后输出一个 user 事件([Request interrupted by user])与 subtype 为 error_during_execution、terminal_reason 为 aborted_streaming 的 result。正在流式输出的内容块没有 assistant 事件。如果中断时有后台任务,另外出现 status: stopped 的 task_notification 与 status: killed 的 task_updated |
| SIGTERM | 143 | 流停在当前位置,没有任何收尾事件,也没有 result。标准错误为空 |
判定规则:退出码非 0 一定失败;退出码为 0 时看最后一个 result 的 is_error;没有 result 时按被终止处理。启动前失败(选项错误、缺少 --verbose)的标准输出为空,认证与模型错误则会走完 init 到 result 的完整流程。
{
"type": "user",
"message": {
"role": "user",
"content": [{ "type": "text", "text": "[Request interrupted by user]" }]
},
"parent_tool_use_id": null,
"session_id": "SESSION_ID",
"uuid": "UUID",
"timestamp": "2026-10-03T15:32:10.443Z"
}
{
"type": "result",
"subtype": "error_during_execution",
"is_error": true,
"terminal_reason": "aborted_streaming",
"stop_reason": null,
"num_turns": 2,
"errors": ["[ede_diagnostic] result_type=user last_content_type=n/a stop_reason=null"],
"duration_ms": 9169,
"duration_api_ms": 648,
"total_cost_usd": 0.001024,
"usage": {
"input_tokens": 0,
"output_tokens": 0,
"cache_creation_input_tokens": 0,
"cache_read_input_tokens": 0,
"iterations": []
},
"modelUsage": {
"claude-haiku-4-5-20251001": { "inputTokens": 954, "outputTokens": 14, "costUSD": 0.001024, "...": "..." }
},
"permission_denials": [],
"session_id": "SESSION_ID",
"uuid": "UUID",
"result_index": 0,
"queued_turn_count": 0
}
版本与环境说明
- 样本来自 claude-code 2.1.288 与 2.1.289,两者的事件类型与字段集没有发现差异。
active_goal、autocompact_state、rate_limit_event三种事件只在 Claude 的 Cloud Managed 容器里观测到。autocompact_state.value.source为env,说明它来自环境变量配置;rate_limit_event.rate_limit_info含status、resetsAt、rateLimitType、overageStatus、overageDisabledReason、isUsingOverage、unifiedWindows.{five_hour, seven_day}.{utilization, resetsAt},描述订阅的用量窗口;active_goal.value观测值为 null。其他环境里是否出现未验证,解析器应把它们当作可选事件。system/init的tools、skills、slash_commands、plugins列表和startup_timing、result的计时字段随环境与版本变化,本文只列出键名,不保证完整。- thinking 块的正文在样本里都是空字符串,只有签名与 token 估计;这可能是账号或模型的设置,解析器不应假设 thinking 正文可读。
- 未实测的选项:
--forward-subagent-text、--input-format stream-json、--replay-user-messages、--fallback-model、MCP 工具(mcp__前缀的工具名)与上下文压缩(compact)过程中的事件。