QueryEngine 核心循环
Claude Code 的心脏 —— query() 无限循环如何驱动 AI 推理、工具执行与上下文管理
QueryEngine 概述
驱动 Claude Code 的核心引擎
QueryEngine 是 Claude Code 最核心的类。它拥有整个查询生命周期和会话状态, 每次 submitMessage() 调用启动一个新的 turn,而内部的 query() 函数通过 while(true) 无限循环 实现多轮工具调用。
架构上分为两层:QueryEngine 类(会话管理、消息持久化、SDK 适配) 和 query() 函数(纯推理循环、上下文压缩、工具执行)。 依赖通过 QueryDeps 注入,便于测试。
QueryEngine 两层架构
8 步执行流程
query() 循环的完整生命周期
以下是 queryLoop() 每次迭代执行的 8 个核心步骤。点击自动播放可观看完整流程动画。
1// query.ts — queryLoop entry2async function* queryLoop(params: QueryParams) {3 const budgetTracker = feature('TOKEN_BUDGET') 4 ? createBudgetTracker() : null5 const config = buildQueryConfig()6 7 // Fire-and-forget memory prefetch8 using pendingMemoryPrefetch = 9 startRelevantMemoryPrefetch(messages, toolUseContext)10 11 while (true) {Step 1: 初始化 — 创建 BudgetTracker、快照 QueryConfig(session ID、feature gates)、启动异步内存预取
执行流程全景图
从用户输入到最终结果的完整数据流
QueryEngine 完整执行流程图
初始化阶段
- ▸创建 BudgetTracker 和 QueryConfig
- ▸启动内存预取 (pendingMemoryPrefetch)
- ▸初始化 StreamingToolExecutor
上下文管理
- ▸Snip — 移除过期的僵尸标记
- ▸Microcompact — 去除冗余工具结果
- ▸Autocompact — 全量对话摘要压缩
推理与执行
- ▸流式调用 Claude API
- ▸收集 assistant 消息和 tool_use 块
- ▸并行/串行执行工具调用
终止与检查
- ▸Stop Hooks — 后台钩子检查
- ▸Token Budget — 90% 阈值/边际递减
- ▸maxTurns / maxBudgetUsd 限制
Stop Hooks 中断机制
每次 turn 结束时的钩子系统
handleStopHooks() 在 Claude 完成回复后执行,可以阻止循环继续(preventContinuation)或注入阻塞错误(blockingErrors)触发重试。 它还异步触发 Prompt Suggestion、Memory Extraction、Auto Dream 等后台任务。
对于 Teammate(子智能体),还会额外运行 TaskCompleted 和 TeammateIdle 钩子。
Stop Hooks 执行流程
blockingErrors钩子发现需要修正的问题(如代码规范违规),注入错误消息后 continue 重试,Claude 会在下一轮修正
preventContinuation钩子判定应该终止循环(如前置条件不满足),立即 return,不再继续推理
后台任务PromptSuggestion(生成后续建议)、ExtractMemories(提取对话记忆)、AutoDream(自动任务生成)异步执行,不阻塞主循环
Token Budget 动态分配
智能的 token 消耗控制策略
checkTokenBudget() 实现了双重停止条件:
- ▸90% 阈值 — 当 token 消耗达到预算的 90% 时,注入 nudge 消息提示 Claude 尽快收尾
- ▸边际递减检测 — 连续 3 次续接后,如果每轮新增 token < 500,判定为边际递减,提前终止
Token Budget 决策流程
达到预算 90% 时注入收尾提示
每轮新增低于此值视为边际递减
至少续接 3 次后才开始检测边际递减
BudgetTracker 状态
依赖注入与配置
QueryDeps + QueryConfig 的设计哲学
query() 的核心依赖通过 QueryDeps 接口注入(callModel、microcompact、autocompact、uuid),不可变配置通过 QueryConfig 在循环开始时快照。这使得测试可以直接注入 mock,无需 spyOn。
QueryDeps — 可替换依赖
QueryConfig — 不可变快照
错误恢复机制
Prompt-Too-Long、Max-Output-Tokens、Model Fallback
query() 实现了多层错误恢复策略,通过 withhold 机制暂缓错误暴露,先尝试恢复:
prompt_too_long (413)排空所有 staged collapses,保留细粒度上下文而非全量摘要
prompt_too_long / media_size_error执行 reactive compact 压缩,单次尝试,避免死循环
max_output_tokens (8k cap)自动升级到 64k tokens 重试同一请求
max_output_tokens (64k also hit)注入恢复消息,最多重试 3 次(MAX_OUTPUT_TOKENS_RECOVERY_LIMIT)
FallbackTriggeredError切换到 fallbackModel 重试,清理签名块(thinking blocks)
消息类型与流转
query() yield 的所有消息类型
query() 是一个 AsyncGenerator,通过 yield 向外推送多种消息类型。 QueryEngine.submitMessage() 负责将这些消息转换为 SDKMessage 格式并持久化到 transcript。
assistantClaude 的回复(含 thinking/tool_use 块)
user工具执行结果(tool_result)
progress工具执行进度通知
attachment文件变更、max_turns、structured_output
stream_eventmessage_start/delta/stop 事件
systemcompact_boundary、api_error、warning
tombstone标记待移除的消息(如 fallback 清理)
stream_request_startAPI 请求开始信号
tool_use_summary工具调用摘要(Haiku 生成)