Claude Code 主循环机制详解

背景

本文研究 Claude Code 单次 agentic turn 的核心驱动逻辑,即 queryLoop 状态机及其在上下文超限、输出截断、hook 拦截等情况下的恢复/终止路径。

文件位置:src/query.tsquery() 289-391 行,queryLoop() 393-2057 行)

queryLoop 是单轮 agentic turn 的核心状态机,用 while(true) + 显式 state 对象驱动。每次迭代代表一次"模型调用 → 工具执行 → 消息合并",只要模型持续产出 tool_use,就会不断 continue 循环;直到模型给出不含工具调用的最终回复(或触发终止/恢复条件),才会 return 退出。

query() 是外层薄壳:创建/复用 Langfuse trace、调用 queryLoop、在 finally 里做 autonomy 收尾和内存清理,自身不参与状态机逻辑。

代码仓库:github.com/claude-code...

1. 流程图

flowchart TD Start[进入迭代] --> PreProcess[消息预处理 tool_result 预算裁剪 snip microcompact context-collapse autocompact] PreProcess --> BlockCheck[是否触及硬阻塞上限] BlockCheck -->|是 且未开启自动压缩/折叠| ReturnBlock[return blocking_limit] BlockCheck -->|否| CallModel[调用模型 deps.callModel 流式读取 assistant 消息] CallModel --> FollowUpCheck[本轮 assistant 是否产生 tool_use needsFollowUp] FollowUpCheck -->|否 需要收尾| Recover[收尾恢复机制 413 max_tokens stop hooks token budget 见 3.5] Recover -->|可恢复 state 更新| Start Recover -->|无法恢复或正常完成| ReturnCompleted[return] FollowUpCheck -->|是 需要执行工具| ToolExec[执行工具 streamingToolExecutor 或 runTools] ToolExec --> Attachments[注入 AttachmentMessage 队列命令 记忆预取 技能预取] Attachments --> MaxTurnsCheck[超过 maxTurns] MaxTurnsCheck -->|是| ReturnMaxTurns[return max_turns] MaxTurnsCheck -->|否| NextTurn[合并消息进 state 重置恢复计数器 transition next_turn] NextTurn --> Start

图中省略了容错分支(fallback 重试、abort 中断、hook 强制停止等),只保留主干。这些分支在下方对应小节里说明。

2. 终止条件汇总

queryLoopwhile(true) 循环没有单一的"退出点",return 散落在好几处检查里。本章把这些 return 路径按代码里出现的先后顺序串一遍;每种"怎么恢复、恢复失败前还试了什么"的具体机制,仍然在第 3 章对应小节展开,这里只说清楚"什么条件下会真正终止、终止时的 Terminal.reason 是什么"。

  1. needsFollowUp 判据 (3.2 节)------每轮迭代第一个分岔口:本轮 assistant 消息里有没有出现 tool_use 块。没有才会往下走终止/恢复检查;有的话直接进入工具执行、下一轮迭代(next_turn),不会终止。
  2. 硬阻塞上限检查 (3.3 节,query.ts:790-846)------发生在消息预处理链之后、真正调模型之前:token 数已经踩到硬上限,且没有自动压缩/响应式压缩/context-collapse 任何一种机制兜底时,直接 return { reason: 'blocking_limit' },把决定权交还给用户手动 /compact
  3. Prompt-too-long / 媒体过大两级恢复失败 (3.5 节,query.ts:1372-1470)------collapse drain、reactive compact 都救不回来,return { reason: 'prompt_too_long' }(或媒体错误对应的 image_error)。
  4. Max-output-tokens 三级恢复耗尽 (3.5 节,query.ts:1475-1543)------64k 升级、最多 3 次续写都用完了,把之前压住没抛出的错误消息真正 yield 出去,随后走到下面的 API 错误分支终止。
  5. API 错误消息 (3.5 节,query.ts:1549-1555)------lastMessage.isApiErrorMessage(rate limit、认证失败等,含上一条恢复耗尽后的情形),说明模型没产出真实响应,return { reason: 'model_error' },跳过 stop hooks 复核。
  6. Stop hook 强制终止 (3.5 节,query.ts:1568-1570)------外部 Stop hook 脚本返回 preventContinuation: true,不管模型自己怎么想,直接 return { reason: 'stop_hook_prevented' }
  7. maxTurns 硬终止 (3.6 节,query.ts:1802, 2033)------无论是被中断还是正常完成一轮工具调用,只要 nextTurnCount > maxTurnsreturn { reason: 'max_turns' };这是唯一纯粹基于计数、无恢复余地的终止条件。
  8. 正常完成 (3.5 节)------上面所有检查都没触发、Stop hook 也没要求继续、TOKEN_BUDGET 也判定该结束,才真正 return { reason: 'completed' }

此外还有中断类的 aborted_streaming/aborted_tools(用户主动打断)和工具执行后 hook 要求停止的 hook_stopped,这两类不是"恢复失败"的产物,而是外部信号直接打断循环,具体触发点见 3.5、3.6 节及第 4 章速查表。

3. 关键机制说明

3.1 进入循环前后的准备与收尾

query() 外层(query.ts:289-391:只做三件事,本身不影响状态机走向。

  • Trace 生命周期:Langfuse 是接入的 LLM 可观测性平台,langfuseTracesrc/services/langfuse/tracing.ts)是这次 agentic turn 的一条调用链路记录,串联本轮调了什么模型、执行了哪些工具、每一步的输入输出,供事后调试/监控查看。toolUseContext.langfuseTrace 如果没传入(父 agent 场景),query() 内部自己 createTrace() 新建,ownsTrace = true;如果调用方已经传入(子 agent 场景,AgentToolrunAgent.ts 会提前用 createSubagentTrace() 建好再传进来),就直接复用,不重复建(ownsTrace = false)。isLangfuseEnabled() 门控:未启用时 createTrace 直接返回 null,后续相关调用什么都不做(query.ts:292-306)。

queryLoop 每轮迭代开头(query.ts:460-521

  • queryTrackingchainId/depth):首次迭代生成新 chainId,之后每轮 depth + 1,写回 toolUseContext,用于全链路埋点关联(query.ts:504-521)。
  • messagesForQuery 剥离 toolUseResult:每轮请求前对 user 消息做浅拷贝并删除 toolUseResult 字段,只保留 message.content 发给 API,防止长会话里大文件读取结果永久占用内存;用浅拷贝而非原地修改,避免和 UI 渲染产生竞态(query.ts:525-553)。
  • skill/tool 预取在迭代开头 (模型调用之前)就发起,与模型流式和工具执行重叠进行,工具执行完之后才消费结果(发起见 query.ts:484-493,消费见 3.7 附件消息注入);记忆预取用 using 声明在 while 循环 ,每个 user turn 只发起一次,而不是每轮迭代都发(query.ts:454-457)。

3.2 State 设计与重置、终止判据

Statequery.ts:261-274)是 queryLoopwhile(true) 循环的循环变量集合:messagestoolUseContext、压缩/恢复计数器等字段,只要还需要"活过这一圈、带到下一圈继续用",就属于这里------不管下一圈是因为模型正常产出 tool_use 需要执行工具再继续,还是因为 413/max-tokens/hook 拦截(3.5)需要恢复重试,都是同一套机制。

跨迭代可变字段收敛到这一个对象后,每次进入下一轮迭代都是整体替换 state = { ... },而不是逐字段更新------新增一条恢复路径时不会因为漏更新某个字段引入 bug。state.transition 显式记录"上一次为什么进入下一轮",方便测试断言具体走了哪条恢复路径。

transition.reason 共有 7 种取值,对应 6 处字面 continue 语句加上 next_turn

reason 位置 触发场景
collapse_drain_retry query.ts:1402 命中 413(prompt-too-long),把此前暂存但未提交的 context-collapse 折叠结果强制提交(recoverFromOverflow),如果确实清出了新内容(committed > 0)就用折叠后的消息重试;上一轮已经走过这条路径时不会重复触发,避免死循环
reactive_compact_retry query.ts:1452 413 或媒体过大,且 collapse drain 没能解决(或未开启),整体做一次响应式压缩(reactiveCompact.tryReactiveCompact,区别于 3.3 的自动 autocompact),压缩成功则用压缩后的历史重试;hasAttemptedReactiveCompacttrue,避免压缩后仍 413 时无限重试
max_output_tokens_escalate query.ts:1507 命中 max-output-tokens 且当前用的是默认 8k 上限,直接把上限提到 64k 重发同一请求(不注入任何消息);每轮最多触发一次
max_output_tokens_recovery query.ts:1538 64k 上限依然被截断(或本来就不满足 escalate 条件),注入一条 isMeta 用户消息要求模型"直接继续、不要道歉或重复",最多重试 3 次(maxOutputTokensRecoveryCount),超过则放弃恢复、把错误消息真正 yield 出去
stop_hook_blocking query.ts:1595 模型无 tool_use 主动收尾,但 Stop hook(用户/项目配置的外部脚本)返回 decision: 'block' 否决结束,把阻断理由包装成消息塞回历史,强迫模型重新看一眼再继续
token_budget_continuation query.ts:1630 模型无 tool_use 就主动收尾,但本轮消耗量还不到预算的 90%(turnTokens < budget * 0.9),怀疑提前收尾,注入 nudge 消息强制继续
next_turn query.ts:2053 模型正常产出 tool_use,执行完工具需要继续对话(最常见路径),非字面 continue------循环体正常执行到末尾、state = next 后自然回到 while(true) 顶部

next_turn 是这 7 种里唯一"一切正常"的一条,核心动作是消息合并messagesForQuery.concat(assistantMessages, toolResults) 按顺序拼接三段内容------

  1. messagesForQuery:这轮请求发出去之前的历史;
  2. assistantMessages:模型这轮流式吐出的 assistant 消息(含触发工具执行的 tool_use 块);
  3. toolResults:工具这轮执行完产出的 tool_result/附件消息。

拼接结果写入 state.messages,作为下一轮请求的输入------这样下一轮模型才能看到"我刚才调了什么工具、结果是什么",从而继续对话。

驱动"走不走 next_turn 这条路径"的判据是 needsFollowUp:是否为 true 取决于本轮 assistant 消息里是否出现了 tool_use 内容块 ,而不是模型返回的 stop_reason 字段(query.ts:756, 1090-1093)。这是有意为之:不同 provider/SDK 对 stop_reason 的支持程度不一致,但 tool_use 块是否存在可以直接观测。这一个布尔值直接决定循环走"收尾恢复"分支(3.5 节)还是"执行工具并进入 next_turn"分支,是整个状态机最核心的分支点。

3.3 消息预处理链与硬阻塞检查

真正发请求前,消息历史依次经过以下五层------层与层是叠加而非互斥关系,且严格按此顺序执行:

  1. applyToolResultBudgetquery.ts:567-582,实现在 src/utils/toolResultStorage.ts:925):按 wire message(发给 API 前,同角色连续消息会被 normalizeMessagesForAPI 合并成的最终消息单元)分组聚合 tool_result 体积,超过阈值(getPerMessageBudgetLimit())就把该组里体积最大的若干条结果写入磁盘、原地替换成一段提示信息persistToolResult + buildLargeToolResultMessage,不是摘要),替换决定按 tool_use_id 跨轮次冻结(seenIds/replacements),保证同一条结果不会来回变化、破坏 prompt cache;
  2. snipCompactIfNeededHISTORY_SNIP feature,query.ts:589-598):不做自动判断,纯粹是执行用户已下达的删除指令 ------用户手动执行 /force-snip 时会把当时全部历史消息的 uuid 记录成一个 snip_boundary 标记消息,之后每轮这里负责把标记里列出的 uuid 从发给模型的视图中过滤掉(只影响模型视角,UI 里仍能看到完整历史);
  3. deps.microcompactquery.ts:601-624,实现在 src/services/compact/microCompact.ts):只针对固定几类工具(读文件/shell/grep/glob/web 等)的旧结果生效,走两条独立路径------按时间 (距上条 assistant 消息过久、prompt cache 已过期)触发时整体清空这些工具的历史结果内容(替换为固定文案 [Old tool result content cleared]);按数量阈值触发时则通过 API 的 cache-editing 能力直接删除更早的工具结果(不修改本地消息数组);两种都不生成摘要;
  4. contextCollapse.applyCollapsesIfNeededCONTEXT_COLLAPSE feature,query.ts:638-645):把旧消息折叠成摘要,但只在"读取时"生效------投影出一份给这次请求用的精简视图,不修改原始历史数组,折叠记录本身持久化,下次进来重新 replay 一遍即可;
  5. deps.autocompactquery.ts:652-741,实现在 src/services/compact/autoCompact.ts):前面几步都不够、历史仍然超出阈值时触发的整体压缩,用一次额外的模型调用把整段历史总结成摘要(compactConversation),成功后用 postCompactMessages 整体替换 messagesForQuery,后续都基于压缩后的历史继续。

五层跑完之后,是硬阻塞上限检查query.ts:790-846):命中真实 API 413 之前主动拦截,返回 blocking_limit,目的是给用户留出手动 /compact 的空间。三个独立条件命中任意一个都会跳过这个检查:querySourcecompact/session_memory 这类内部 forked agent(本身就是为了压缩历史,被拦住会死锁);已开启自动压缩且 reactive compact 也启用;collapseOwnsIt(reactive-compact/context-collapse 的恢复机制已经接管)。也就是说这个检查并非只由"是否关闭自动压缩"单一开关决定,而是这三个条件的合取取反。

硬阻塞检查通过之后、真正调模型之前,还有一次预测性 autocompactquery.ts:848-888):复用第 5 步同一个 deps.autocompact,但触发依据不同------不看"当前历史是否已超阈值",而是基于 estimateMaxTurnGrowth 预估这一轮模型输出会新增多少 token,提前判断加上这部分增量会不会撑破 context window,避免"这轮请求本身没超限,但这轮输出会让下一轮直接超限"。

3.4 模型调用与 Fallback

deps.callModelquery.ts:899-949)是实际发起模型请求、流式读取 assistant 消息的地方。顶层入参决定这次请求发什么内容:messagesprependUserContext(messagesForQuery, userContext),即 3.3 预处理链跑完之后的历史)、systemPromptfullSystemPrompt,已拼接 systemContext)、toolstoolUseContext.options.tools)、signal(用于中断);此外还有一个 options 字段,装了 model/maxOutputTokensOverride/taskBudget/langfuseTrace/queryTracking 等参数。

外层 while (attemptWithFallback)query.ts:894-1212)允许在模型调用抛出 FallbackTriggeredError 时整体重试:清空本次已产出的 assistantMessages/toolResults/toolUseBlocks,丢弃并重建 streamingToolExecutor(避免旧 tool_use_id 的孤儿结果混入新一轮请求),切换到 fallbackModel 后重新流式调用。

流式阶段对 prompt-too-long、媒体过大、max-output-tokens 这几类可能可恢复的错误先不 yieldwithheld = truequery.ts:1052-1078),继续推进 assistantMessages,留到收尾阶段(3.5 节的两级/三级恢复)判断能否恢复;恢复成功则这条错误消息相当于从未发生过,避免 UI 上出现"看似失败又自动消失"的中间状态。

3.5 收尾恢复机制(needsFollowUp = false 时)

只有本轮未产生 tool_use 才会进入这一整块(query.ts:1349-1647),内部按顺序尝试多种恢复手段,任何一步恢复成功都会 continue,全部失败或模型正常完成才会 return

Prompt-too-long / 媒体过大两级恢复query.ts:1372-1470):

  1. Collapse drain (先试,成本低):把已暂存但未提交的折叠清空提交,如果清出新内容就重试;用 transition.reason !== 'collapse_drain_retry' 防止同一错误反复走这条路径。
  2. Reactive compact (兜底,成本高):整体做一次响应式压缩,用 hasAttemptedReactiveCompact 标志防止压缩后仍 413 时无限重试。

两级都失败则 return { reason: 'prompt_too_long' }(或媒体错误的 image_error)。

Max-output-tokens 三级恢复query.ts:1475-1543):

  1. 升级重试(一次性):若用的是默认 8k 上限,直接升到 64k 重发同一请求;
  2. 多轮续写恢复(最多 3 次):注入一条 isMeta 用户消息要求模型"直接继续";
  3. 超过 3 次:放弃恢复,把错误消息真正 yield 出去。

Stop hooks 续跑query.ts:1549-1645):这一段要解决的问题是------模型自己觉得"这轮做完了",但这个判断不是最终结论,还要经过两轮独立检查复核,才能真正放行结束。

第一轮,判断"模型这次是不是真的正常做完了":若 lastMessage.isApiErrorMessage(rate limit、认证失败等),说明模型根本没产出真实响应,只是报错了------这种情况直接触发 stop failure hooks 并 return { reason: 'model_error' },跳过后面所有检查(对一个不存在的正常响应做复核没有意义,硬跑只会导致"报错→hook 拦截→重试→又报错"的死循环)。

确认是正常完成后,依次经过两轮复核:

  1. handleStopHooks ------把这轮结果交给外部配置的 Stop hook 脚本评审,脚本有两种否决方式:返回 blockingErrors 表示"理由不充分,退回重做",把理由塞进历史消息里、continue 让模型重新审视;返回 preventContinuation 表示"不管模型怎么想,必须立刻停",直接 return,比模型自己的判断更强硬。(走"退回重做"分支时,hasAttemptedReactiveCompact 会保留而不重置,防止"压缩失败→报错→hook 拦截→又触发压缩"的无限循环。)
  2. TOKEN_BUDGET ------如果上一步没有被拦下,再检查这次任务预算花得够不够:checkTokenBudget 发现消耗量远没到预算的 90%,就判定"可能是提前收尾",注入一条 nudge 消息、continue 强制模型继续干;预算判定应该结束时才放行。

以上全部没触发,才真正 return { reason: 'completed' }------模型主动结束且没有任何机制要求它继续的唯一退出点。

Stop failure hooksexecuteStopFailureHooksquery.ts:1461, 1468, 1550)是与上面 handleStopHooks 平行但独立的一套 hook:只在恢复失败/API 错误这几条失败路径上触发,用于失败态的外部通知,不参与"是否继续"的判断(那是 handleStopHooks 的职责)。

3.6 工具执行两种模式

  • streamingToolExecutor:模型还在流式输出时,只要某个 tool_use 块已经完整到达,就立刻开始并发执行它,不等模型说完。执行过程中产生的进度消息(progress)不等工具跑完,随时产生随时 yield;工具的最终结果(tool_result)则是这个工具执行完才 yield,谁先完成谁先出,模型说完后再用 getRemainingResults() 收尾剩下还没跑完的。
  • runTools:等模型完整输出结束、拿到全部 toolUseBlocks 后才开始,内部按并发安全性分批调度、批次间严格串行。

两者不是根据本轮工具情况动态选择 ,而是在 query() 调用一开始通过灰度开关一次性定死(config.gates.streamingToolExecution),跟当前这一轮模型输出了什么工具、多少个、是否可并发都无关。唯一的运行时变化是:触发 fallback 重试时会把旧的 executor 丢弃重建,但仍是同一套"用不用流式"的机制。

两者判断"某个工具是否并发安全"的依据一致(都调用工具定义的 isConcurrencySafe(input)),但调度机制不同:runToolstoolOrchestration.ts)是拿到这一轮全部 toolUseBlocks 后,先静态分组(连续的并发安全工具合成一批,不安全的单独成批),再按批次顺序执行;streamingToolExecutor 没有预先分组,工具是流式陆续到达的,每来一个就动态判断"当前正在跑的工具里有没有不安全的、这个新工具能不能立刻插进去一起跑",遇到暂时排不上的不安全工具就停止往后派发,以维持顺序。

3.7 附件消息注入与 maxTurns 硬终止

工具执行完之后才注入 AttachmentMessagetype: 'attachment'query.ts:1894-1954),它是消息历史里独立于 assistant/user 的一种类型,专门承载工具执行之外产生的旁路信息。这里注入的三类来源:

  • 队列命令getAttachmentMessagesquery.ts:1894-1904):本轮模型/工具还在跑的时候被塞进队列的命令,例如后台任务(run_in_background 的 shell/agent)状态变化的提醒------如检测到某个后台命令卡在交互式输入上,会生成一条通知说明情况并建议改用非交互方式重跑,转成附件消息让模型在当前轮次里看到并响应;
  • 记忆预取query.ts:1913-1928):3.1 节提到的、每个 user turn 只发起一次的 pendingMemoryPrefetch,在这里消费其结果;
  • 技能/工具发现预取query.ts:1930-1954):3.1 节提到的 skill/tool prefetch,在迭代开头发起、这里消费。

之所以要等工具执行完之后才注入,是因为 API 不允许 tool_result 消息和普通 user 消息交错------必须等所有 tool_result 就位后,才能安全追加其他类型消息。记忆预取和技能/工具预取都是"尽力而为":如果 Promise 还没 settle,直接跳过、留给下一轮迭代再检查。

附件消息注入完之后,紧接着做 maxTurns 硬终止 检查:无论是"被中断"还是"正常完成一轮工具调用"之后,都会检查 nextTurnCount > maxTurnsquery.ts:1802, 2033)。这是唯一一条纯粹基于计数、无恢复余地的硬停止条件,用来防止 agentic 循环失控地跑下去。

3.8 其他旁路机制

Cache warningquery.ts:1260-1284,实现在 src/utils/cacheWarning.ts):提醒用户"这次请求的 prompt cache 命中率过低",命中率低意味着更贵、更慢------通常是历史被频繁改动(压缩、工具结果替换等)打断了缓存前缀导致的。用最后一条 assistant 消息的 usage 算出 cache_read_input_tokens 占总输入的比例,低于阈值(默认 80%,settings.json 可配置)就提示,同时给出比上一次请求命中率是升是降的趋势;同一 querySource 首次请求不报(没有基线可比)。必须在 executePostSamplingHooks 之前执行,确保警告消息排在工具结果之前显示;仅在交互式会话且未关闭该提醒(isCacheWarningEnabled())时生效。这条消息纯粹是流给上层 UI 看的旁路消息,不进入历史(呼应 3.2 的 next_turn 消息合并)。

task_budgetparams.taskBudget,API beta 特性):给这一整个 agentic turn 设一个 token 预算上限,随请求传给模型,让模型自己感知"还剩多少额度"、据此安排何时收尾------是服务端主导的机制。客户端唯一要做的事是维护 taskBudgetRemaining(loop-local 变量,不放进 State):未压缩历史时服务端能看到完整对话自己倒计时,不用客户端插手;一旦发生压缩,服务端就只能看到压缩后的摘要,会漏算被压缩掉的那部分消耗,所以客户端要在两处压缩发生点用 finalContextTokensFromLastResponse 算出"压缩前的窗口大小",从 remaining 里扣掉这一块,跨多次压缩要累加(query.ts:702-713, 1422-1433)。

TOKEN_BUDGETtokenBudget/budgetTracker/checkTokenBudget):跟上面完全独立的另一套机制,方向也相反------不是"预算快用完了提醒收尾",而是"预算还没花够、模型却主动说做完了,就怀疑它提前收尾、强制继续"。是纯客户端侧的续跑判断,具体机制见 3.5 节 stop hooks 续跑部分。两者可以同时存在于同一个请求里,互不影响。

4. 速查表

4.1 Continue / Return 一览

queryLoopwhile(true) 循环每轮迭代最终只有两种去向:continue(构造新 state,进入下一轮迭代)或 return(结束整个 queryLoop,附带一个 Terminal 结果)。下表汇总所有出现过的具体分支------continue 行对应 3.2 节 state.transition.reason 的 7 种取值,return 行对应 3.1 节 Terminal.reason 的取值,触发条件列说明每一种具体在什么情况下会走到这里。

类型 reason 触发条件
continue collapse_drain_retry prompt-too-long 且折叠 drain 有新内容
continue reactive_compact_retry prompt-too-long/媒体过大,reactive compact 成功
continue max_output_tokens_escalate 首次命中 max tokens,升级到 64k
continue max_output_tokens_recovery max tokens 恢复重试(≤3 次)
continue stop_hook_blocking stop hook 返回阻断消息
continue token_budget_continuation token 预算要求继续
continue next_turn 正常工具调用完成
return blocking_limit 硬阻塞上限触发
return image_error 图片错误 / 媒体恢复失败
return model_error 模型调用抛出未预期异常,或 API 错误消息(rate limit 等)
return prompt_too_long 两级恢复都失败
return aborted_streaming 流式阶段被中断
return aborted_tools 工具执行阶段被中断
return hook_stopped 工具执行后 hook 要求停止
return stop_hook_prevented stop hook 直接阻止继续
return max_turns 超过 maxTurns
return completed 模型完成且无任何恢复/续跑机制触发

4.2 消息类型速览

queryLoop 生成器签名(query.ts:397-404)里 yield 的类型,加上 Message.typeMessageType)的全部取值,对照如下:

类型 说明 本文对应位置
AssistantMessagetype: 'assistant' 模型输出,可能含 tool_use/text/thinking 3.2 终止判据、3.4 模型调用
UserMessagetype: 'user' 用户输入,或工具执行后生成的 tool_result 3.2 消息合并、3.3 预处理链
SystemMessagetype: 'system' 系统级提示,如 fallback 切换通知、cache warning 3.4 Fallback、3.8 cache warning
AttachmentMessagetype: 'attachment' 工具执行之外的旁路信息:队列命令、记忆/技能/工具预取结果 3.7 附件消息注入
ProgressMessagetype: 'progress' 工具执行期间的流式进度上报 未展开,属于工具执行内部机制
GroupedToolUseMessagetype: 'grouped_tool_use' UI 侧对同批工具调用的折叠展示 未展开,纯 UI 层
collapsed_read_search UI 侧对连续读/搜索操作的折叠展示 未展开,纯 UI 层
TombstoneMessage 标记已作废的消息(如 fallback 时丢弃的孤儿 assistant 消息),提示 UI/transcript 移除 3.4 Fallback
ToolUseSummaryMessage 工具调用批次完成后异步生成的摘要,下一轮迭代开头消费 3.1 迭代初始化(pendingToolUseSummary)
RequestStartEvent 每轮迭代开始时 yield 的标记事件({ type: 'stream_request_start' }),非最终消息 未展开
StreamEvent 模型流式响应过程中的中间事件(非完整消息),非最终落地历史 3.4 模型调用
相关推荐
lyy-独立开发者1 小时前
主动推理-信息消费策略
人工智能
GuWenyue1 小时前
提示词彻底过时?一套上下文工程方案,3步让LLM落地生产,代码直接复用
前端·javascript·人工智能
秦歌6661 小时前
agno-1-入门和智能体构建
人工智能
Kel2 小时前
Pregel 为什么会成为LangGraph编排的心脏
人工智能·设计模式·架构
zhangfeng11332 小时前
aclnn 完整含义解析 华为昇腾计算库-神经网络算子API(算子开发) acl / aclnn / aclrt 三者区分
人工智能·深度学习·神经网络
天风之翼2 小时前
RAG 系统深度实战:从朴素检索到 Agentic RAG 的完整演进
人工智能
RobinDevNotes2 小时前
Headroom:给 AI Agent 上下文做压缩,省下 60%-95% 的 Token 账单
人工智能
2603_955279702 小时前
我的AI辅助开发工具链2026版:构建下一代智能编码工作流
人工智能
这张生成的图像能检测吗2 小时前
(论文速读)REF-DDPM:一种新的基于DDPM的不平衡滚动轴承故障诊断数据增强方法
人工智能·计算机视觉·故障诊断·扩散模型