随笔
Claude Code 源码解读 04:长任务如何从错误里接回来
拆解 query loop、State、tool_result 配对、compact、Stop Hook 和 API retry,说明 Claude Code 如何维持长任务轨迹。
Query Loop 把模型流、工具执行、follow-up、compact、Stop Hook、retry 和错误修补放进同一条可推进轨迹。
快速了解
- 长任务能继续,不是模型愿意继续,而是 query loop 保住了运行轨迹。
- API retry 和任务 follow-up 是两层不同循环,不能混为一谈。
- 已经出现
tool_use时,异常路径也要补tool_result。 - compact、reactive compact、context collapse 都是条件路径,不是万能恢复魔法。
如果只想快速理解,可以先读这一节;如果要看源码机制,再往下看“主线与场景插入分类”和机制图。
设问与回应
| 设问 | 回应 |
|---|---|
query() / queryLoop() 为什么要维护显式 State? | State 是 query loop 能持续推进的运行账本,保存 messages、toolUseContext、compact tracking、turn count 等跨 iteration 信息。没有显式状态,长任务会退化成一轮轮互不相干的调用。 |
为什么不能只相信 stop_reason === tool_use? | 不能只相信 stop_reason === tool_use,因为工具调用只是模型停止原因之一。系统还要处理 maxTurns、附件 drain、token budget continuation、compact、Stop Hook 和异常恢复。 |
yieldMissingToolResultBlocks() 解决的是什么轨迹断裂? | yieldMissingToolResultBlocks() 修的是协议轨迹断裂:一旦 assistant 已经产生 tool_use,后续就必须给模型一个对应的 tool_result,即使工具路径中途失败也要合成错误结果。 |
| Stop Hook 是完成路径上的验收器,还是所有错误路径的兜底? | Stop Hook 更像完成路径上的验收器和补救点,不是所有错误路径的兜底。它能拦截“看似完成”的状态,但不能替代 API retry、tool_result 修补或 compact 恢复。 |
主线与场景插入分类
| 机制/模块 | 分类 | 我保留的判断 |
|---|---|---|
query() / queryLoop() | 主线功能 | 所有模型调用、工具 follow-up、停止条件和恢复路径由它推进 |
State 跨 iteration 状态 | 主线功能 | 保存 messages、toolUseContext、compact tracking、turn count 等 |
yieldMissingToolResultBlocks() | 主线 + 恢复支撑 | 异常路径合成错误 tool_result,防止 API 轨迹断裂 |
autoCompactIfNeeded() | 场景插入 + 恢复支撑 | 只在自动 compact 开启且 token 阈值满足时触发 |
handleStopHooks() | 治理横切 + 恢复支撑 | 正常完成路径上的验收与补救,不是所有错误的兜底 |
两个 loop 必须分清
API attempt loop 处理模型调用层的 retry、fallback、容量错误、认证错误、连接错误。Query iteration loop 处理任务推进:模型输出、工具执行、工具结果、附件 drain、maxTurns、Stop Hook、token budget continuation。
Codex 的 compact 和 Claude Code 有什么区别
我更关心的不是“谁有 compact”,而是 compact 被放在什么运行边界里。Claude Code 的 compact 明显嵌在 query loop 的恢复链路中:用户主动 /compact、自动 compact、reactive compact、context collapse 分别对应不同入口、触发条件和状态反馈。它要解决的是长任务继续推进时,消息链、工具结果、Stop Hook 和后续 turn 还能不能保持协议连续。
拿 Codex 做对比时,重点应该拆成三个问题:compact 是一次独立的上下文整理任务,还是 query loop 内部的恢复动作;compact 失败后,失败是否只影响当前压缩动作,还是会污染后续任务状态;compact 结果进入模型前,是否还能保留足够的执行证据、工具边界和用户意图。这样看,优秀 agent harness 的 compact 不是“把上下文变短”,而是把长任务的可恢复性、可审计性和继续执行能力一起保住。