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.rsClaudeCode(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。下面的字段出现在多种事件上:

字段类型含义出现在
typestring事件类型所有事件
subtypestring子类型system、result
uuidstring这一行的唯一编号除 system/api_retry 以外的所有观测到的事件都有
session_idstring会话 id,等于 --session-id 给出的值。subagent 的事件与主 agent 相同所有事件
parent_tool_use_idstring 或 null主 agent 的事件为 null;subagent 内部的事件是启动它的那次 Agent 工具调用的 id。见「subagent 与后台任务」assistant、user、stream_event
timestampstringISO 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_notificationsubagent、Workflow 与后台 Bash 命令的生命周期agent 启动了这类任务
system/background_tasks_changed后台任务列表变化时agent 启动了后台任务

错误与权限

请求失败重试与工具调用被拒绝。

type / subtype何时出现需要的条件
system/api_retryAPI 请求失败后重试之前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)。

调用方模型工具claude-code 状态启动active_goalCloud Managed 容器才有autocompact_state同上rate_limit_event同上system/init模型、工具、权限模式user提示词回显,isReplay: true第 1 次模型调用:写文件system/status开始请求模型assistanttool_use Write,id Wsystem/task_summary一句当前动作的描述usertool_result,tool_use_id W第 2 次模型调用:读回system/statusassistantthinkingassistanttool_use Read,id Rusertool_result,tool_use_id R第 3 次模型调用:回答system/statusassistanttext:给调用方的回答system/post_turn_summaryresult最终回答与用量,num_turns 3system/task_summaryresult 之后还可能有会话头与结果模型输出输入与工具结果状态与流程

要点:

下面是一次带两个 subagent 的运行:主 agent 在一次模型调用里启动两个 subagent,一个写文件,一个运行命令,各自交回报告后主 agent 汇总回答。中间两列是 subagent 内部的事件,它们带 parent_tool_use_id,值为启动它的 Agent 调用的 id(图中的 A、B)。task_* 事件在主 agent 一列,用 tool_use_id 或 task_id 指向对应的 subagent。各字段见「subagent 与后台任务」。

主 agentsubagent Asubagent B启动(与上图相同,只画出 system/init 与提示词)system/inituser提示词回显,isReplay: true主 agent 在一次模型调用里启动两个 subagentsystem/statusassistanttool_use Agent,id Aassistanttool_use Agent,id B(message.id 同上一行)system/task_summarysystem/task_startedtool_use_id A,task_type local_agentusersubagent A 收到的提示词system/task_startedtool_use_id Busersubagent B 收到的提示词两个 subagent 并行工作,事件交错出现system/task_progressA 的累计用量assistanttool_use Writeusertool_resultsystem/task_progressB 的累计用量assistanttool_use Bashusertool_resultsubagent A 交回报告并结束system/task_progressassistanttool_use SubagentHandbackusertool_resultsystem/task_updatedA:status completedsystem/task_notificationA:completed,最终用量user主 agent 收到 A 的结果,tool_use_id Asubagent B 交回报告并结束system/task_progressassistanttool_use SubagentHandbackusertool_resultsystem/task_updatedB:status completedsystem/task_notificationB:completed,最终用量user主 agent 收到 B 的结果,tool_use_id B主 agent 汇总回答system/statusassistantcontent: textsystem/post_turn_summaryresultnum_turns 3,subagent_stats.spawned 2system/task_summary会话头与结果模型输出输入与工具结果状态与流程

开启逐字输出后,每次模型调用周围多出 stream_event,assistant 事件出现在对应内容块的 content_block_stop 之前:

system/status stream_event message_start stream_event content_block_start index 0, tool_use stream_event content_block_delta ×N input_json_delta assistant content: tool_use(完整参数) stream_event content_block_stop index 0 stream_event message_delta stop_reason, usage stream_event message_stop system/task_summary user tool_result

类型总览

从本节开始,事件的字段用 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 合起来判断成败:

subtypeis_errorterminal_reason情形退出码
successfalsecompleted正常完成。工具失败、权限被拒都不改变这个状态0
successtrueapi_errorAPI 返回错误(认证失败、模型不存在),api_error_status 是 HTTP 状态码,result 是合成的错误文字1
error_during_executiontrueaborted_streamingSIGINT 中断。errors 含诊断字符串,stop_reason 为 null0
error_max_turnstruemax_turns超过 --max-turns。errors 为 ["Reached maximum number of turns (N)"],没有 result 字段1
error_max_budget_usdtruebudget_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 的完整事件序列:

assistant tool_use Agent,id 为 toolu_P,input: {description, prompt, subagent_type, run_in_background} system/task_started task_id, tool_use_id: toolu_P user parent_tool_use_id: toolu_P,content: text(subagent 收到的 prompt) system/task_progress usage: {total_tokens, tool_uses, duration_ms} assistant parent_tool_use_id: toolu_P,subagent 的工具调用 user parent_tool_use_id: toolu_P,subagent 的工具结果 assistant parent_tool_use_id: toolu_P,tool_use SubagentHandback(subagent 交回报告) user parent_tool_use_id: toolu_P,SubagentHandback 的结果 system/task_updated patch: {status: "completed", end_time} system/task_notification status: "completed",usage user parent_tool_use_id: null,content[0].tool_use_id: toolu_P,主 agent 收到的 Agent 工具结果

要点:

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、文件不存在)0user 事件的 tool_result.is_error 为 true,模型继续,result 正常
权限被拒0system/permission_denied,result.permission_denials 非空,is_error 为 false
认证失败(401)1system/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-turns1result.subtype 为 error_max_turns
超过 --max-budget-usd1result.subtype 为 error_max_budget_usd
未知命令行选项1标准输出为空,标准错误 error: unknown option '--xxx'
缺少 --verbose1标准输出为空,标准错误 Error: When using --print, --output-format=stream-json requires --verbose
SIGINT0流停在当前位置,然后输出一个 user 事件([Request interrupted by user])与 subtype 为 error_during_execution、terminal_reason 为 aborted_streaming 的 result。正在流式输出的内容块没有 assistant 事件。如果中断时有后台任务,另外出现 status: stopped 的 task_notification 与 status: killed 的 task_updated
SIGTERM143流停在当前位置,没有任何收尾事件,也没有 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
}

版本与环境说明