Skip to content

ReAct 推理循环 ​

本文引用的源码文件

本文引用的文件

更新摘要 ​

变更内容

  • 新增检查点节流系统 (createCheckpointThrottle) 实现尾随落盘机制
  • 重构子任务中断处理,引入部分进度摘要和滚动更新机制
  • 增强子任务重放预防机制,修复取消作用域对齐问题
  • 改进UI显示逻辑,支持跳过重放的可视化标记
  • 优化上下文构建系统,支持继承上下文和重试现场恢复
  • 新增:子任务超时预算计算增强 - 移除硬编码上限,引入60秒最小预算下限
  • 新增:React循环升级接线 - 改进父任务实时剩余时间传递机制
  • 新增:观察结果字段优先级改进 - observation字段优先于result字段
  • 新增:子任务进度管理增强 - 改进部分进度摘要和滚动更新机制

目录 ​

  1. 引言
  2. 项目结构
  3. 核心组件
  4. 架构总览
  5. 详细组件分析
  6. 依赖关系分析
  7. 性能与预算控制
  8. 调试与故障排查
  9. 结论
  10. 附录:扩展指南

引言 ​

本文件聚焦于 ReAct 推理循环的实现,围绕"思考-行动-观察"主循环、工具调用协调、循环检测、子任务管理、反思机制以及错误恢复展开。重点解析 reactLoopImpl 的核心流程,包括消息处理、工具执行调度、结果缓存、上下文压缩、检查点持久化与恢复;并说明 shouldReflect、buildReflectionPrompt、reflectOnResult 的反思策略;同时梳理 loop-detector 的多模式检测(重复操作、元素枚举、振荡、失败作用域、无进展滚动、预算控制)。文档还提供扩展新工具类型、自定义 ReAct 行为与优化推理性能的实践建议,以及常见问题的定位方法。

重大更新:本次更新引入了全新的检查点节流系统和子任务中断处理机制,显著提升了系统的鲁棒性和用户体验。新增了子任务超时预算计算的增强功能,移除了硬编码的时间限制,引入了智能的60秒最小预算下限机制。

项目结构 ​

ReAct 推理循环位于扩展端 background 脚本中,由多个模块协作完成:

  • react-loop.js:ReAct 主循环、工具执行编排、子任务派发、上下文压缩、检查点、反思入口。
  • react-reflection.js:后置反思与子任务反思的 Prompt 构建、API 调用与结果解析。
  • loop-detector.js:多模式循环检测器(纯逻辑,browser-free)。
  • tool-executor.js:工具定义、动态注册(MCP/RAG)、执行分发与超时。
  • subagent-depth.js:统一的子代理/子任务嵌套深度计数器。
  • completion-verifier.js:完成度校验编排层(取证、评审、重跑指令构造)。
  • chat-manager.js:侧边栏UI渲染,包含子任务状态显示和重放跳过标记。
graph TB
RL["react-loop.js<br/>ReAct 主循环"] --> TE["tool-executor.js<br/>工具定义与执行"]
RL --> RD["loop-detector.js<br/>循环检测器"]
RL --> RR["react-reflection.js<br/>反思机制"]
RL --> CV["completion-verifier.js<br/>完成度校验编排"]
RL --> SD["subagent-depth.js<br/>嵌套深度计数"]
RL --> UI["chat-manager.js<br/>UI显示与交互"]
TE --> |调用 Agent/MCP/浏览器能力| Ext["扩展端能力"]

图表来源

章节来源

核心组件 ​

  • ReAct 主循环(reactLoopImpl)
    • 负责消息预处理、API 调用、工具执行、结果缓存、上下文压缩、检查点保存与恢复、反思触发。
  • 工具执行器(tool-executor)
    • 提供工具定义、动态注册(MCP/RAG)、参数解析、执行分发、超时与确认门控。
  • 循环检测器(loop-detector)
    • 六模式检测:重复、ref 枚举、ABAB 振荡、失败作用域、导航重置、无进展滚动,并提供软提醒与硬停。
  • 反思机制(react-reflection)
    • 后置反思 with 评估/修订解耦,子任务反思独立评分与可选修订。
  • 完成度校验(completion-verifier)
    • 客观断言取证、命令/文件类判据、DOM 类判据、重跑指令生成。
  • 嵌套深度(subagent-depth)
    • plan_task 与 dispatch_task 共享深度计数,防止递归爆炸。
  • 新增:检查点节流系统
    • createCheckpointThrottle 实现智能节流和尾随落盘,确保数据不丢失。
  • 新增:子任务进度管理
    • buildSubtaskPartialSummary、recordSubtaskPartialProgress、createSubtaskPartialProgressWriter 提供细粒度的进度跟踪。
  • 新增:子任务超时预算计算
    • computeSubtaskLoopTimeoutMs 实现智能预算分配,支持60秒最小预算下限和父任务剩余时间约束。

章节来源

架构总览 ​

下图展示 ReAct 主循环在一次迭代中的关键路径:模型响应后进入工具执行分支,并行或顺序执行工具,记录执行日志,轮末喂入循环检测器,必要时注入系统提醒;若无工具调用则进入最终答案分支,触发后置反思并返回结果。

sequenceDiagram
participant Model as "语言模型"
participant Loop as "reactLoopImpl"
participant Tools as "工具执行器"
participant Detector as "循环检测器"
participant Reflection as "反思机制"
participant Checkpoint as "检查点节流器"
Loop->>Model : 发送消息+工具定义
Model-->>Loop : assistant(tool_calls)/content
alt 有工具调用
Loop->>Tools : 执行工具并行/顺序
Tools-->>Loop : 工具结果
Loop->>Detector : 轮末记录(toolName,args,result)
Detector-->>Loop : nudge/stop
opt 软提醒
Loop->>Loop : 注入系统提醒到消息历史
end
else 无工具调用
Loop->>Reflection : shouldReflect? buildReflectionPrompt? reflectOnResult?
Reflection-->>Loop : 质量评估/修订结果
end
Loop->>Checkpoint : 保存检查点(节流)
Checkpoint-->>Loop : 尾随落盘
Loop-->>Loop : 清理

图表来源

详细组件分析 ​

reactLoopImpl:思考-行动-观察主循环 ​

  • 消息处理
    • 应用不可信内容安全合约、过滤内部字段、剥离历史图片、上下文压力评估与主动裁剪、任务锚点与便签瞬态回注。
  • API 调用
    • 流式与非流式统一封装,带外层超时 watchdog、重试回调、usage 统计与 token 校准。
  • 工具执行调度
    • 按 tool_calls 声明顺序分组并行(PARALLELIZABLE_TOOLS),plan_task 独占语义,clarify_question 暂停整体计时。
  • 结果缓存
    • 单次循环内 Map 缓存,TTL=60s,并行工具命中仍喂入检测器避免重复检测失效。
  • 执行日志与快照
    • 增量发送 EXECUTION_STATUS_UPDATE,内存窗口裁剪,checkpoint 节流保存。
  • 子任务管理
    • plan_task 拆解后 executeSubtasks,支持 sequential/parallel/dependency 策略,失败策略 stop/continue/skip,回滚已完成子任务。
  • 反思入口
    • 最终答案完成后根据 shouldReflect 决定是否进行后置反思。
flowchart TD
Start(["进入 reactLoopImpl"]) --> Prep["消息预处理/上下文压力评估"]
Prep --> CallAPI["调用模型 API流式/非流式"]
CallAPI --> HasTools{"是否包含 tool_calls?"}
HasTools --> |是| Group["分组并行/顺序执行工具"]
Group --> ExecTool["executeSingleToolCall"]
ExecTool --> CacheCheck{"缓存命中?"}
CacheCheck --> |是| FeedDetector["喂入循环检测器"]
CacheCheck --> |否| RunTool["执行工具/超时/澄清暂停"]
RunTool --> FormatRes["格式化结果/截断/卸载"]
FormatRes --> FeedDetector
FeedDetector --> Flush["轮末 flushLoopRecords"]
Flush --> SaveCP["保存检查点(节流)"]
SaveCP --> NextIter["下一轮"]
HasTools --> |否| Finalize["最终答案分支"]
Finalize --> Reflect{"shouldReflect?"}
Reflect --> |是| PostReflect["reflectOnResult(评估/修订)"]
Reflect --> |否| Return["返回结果"]
PostReflect --> Return

图表来源

章节来源

工具调用协调机制 ​

  • 用户确认门控
    • 敏感工具/action 级确认,支持"当前任务放行",会话级关联键防串扰,面板呈现回执后才开始倒计时。
  • 并行执行
    • 连续可并行工具合并为一组 Promise.all,非并行工具单独执行;plan_task 会中断同轮后续工具。
  • 结果缓存
    • 仅并行工具缓存,TTL=60s,命中时仍记录 loopRecords 以维持重复检测能力。
  • 工具观察提示
    • 失败/空结果/超大结果时追加规则提示,引导模型自我调整,零额外 LLM 调用。
classDiagram
class ReactLoop {
+executeSingleToolCall()
+dispatchSubtasksParallel()
+flushLoopRecords()
}
class ToolExecutor {
+executeTool()
+loadMcpTools()
+unloadMcpTools()
}
class LoopDetector {
+record(tabId, name, args, result)
}
ReactLoop --> ToolExecutor : "调用工具"
ReactLoop --> LoopDetector : "轮末喂入记录"

图表来源

章节来源

循环检测算法(多模式) ​

  • 重复检测(窗口制)
    • 相同 toolName+args+result 在窗口内重复达到阈值即软提醒,超过停止阈值硬停。
  • ref 枚举循环
    • query_elements 专用:非法页、重读且结果不变、乱序跳页累计可疑计数,超阈硬停。
  • ABAB 振荡
    • 最近尾迹 A,B,A,B 交替判定,全交替硬停,部分交替软提醒。
  • 失败作用域
    • 白名单工具(interact_element/fill_form/select_dropdown/keyboard_input/file_upload)对同一目标连续失败达阈值硬停。
  • 无进展滚动
    • scroll_to(target=top/bottom/coordinates) 报告未移动多次硬停。
  • 预算控制
    • 全局提醒预算达到阈值硬停,避免多模式软提醒累积导致长时无进展。
flowchart TD
Rec["record(tabId,name,args,result)"] --> Nav{"是否导航重置信号?"}
Nav --> |是| Reset["重置页面状态"]
Nav --> |否| Window["入窗/入尾迹"]
Window --> Repeat["重复检测"]
Window --> RefEnum["ref 枚举更新"]
Window --> FailScope["失败作用域"]
Window --> Scroll["无进展滚动"]
Repeat --> CheckStop{"达到停止阈值?"}
RefEnum --> CheckStop
FailScope --> CheckStop
Scroll --> CheckStop
CheckStop --> |是| Stop["返回 stop(reason,params)"]
CheckStop --> |否| Nudge["收集软提醒"]
Nudge --> Budget["预算计数"]
Budget --> |超阈| Stop
Budget --> |未超| None["返回 none"]

图表来源

章节来源

子任务管理与执行 ​

新增:检查点节流系统 ​

  • createCheckpointThrottle
    • 实现智能节流和尾随落盘机制,确保数据不丢失
    • 支持强制落盘和取消操作
    • 通过身份比对防止陈旧回调执行

新增:部分进度摘要 ​

  • buildSubtaskPartialSummary
    • 从执行日志中提取已完成节点的产出摘要
    • 支持节点数量和字符数限制
    • 自动截断超长内容

新增:滚动更新机制 ​

  • recordSubtaskPartialProgress

    • 将部分进度摘要滚动写入进度表
    • 保护已成功的整子任务记录不被覆盖
    • 支持追加模式用于完成度校验重跑
  • createSubtaskPartialProgressWriter

    • 创建滚动写入器,基于内容变化触发更新
    • 避免基于计数的节流失效问题
    • 集成父 checkpoint 落盘机制

新增:上下文构建 ​

  • composeSubtaskInheritedContext
    • 组装子任务的继承上下文
    • 包含父历史摘要、工作笔记、前序子任务结果
    • 集成上次尝试的已完成现场

子任务重放预防 ​

  • shouldSkipSubtaskReplay

    • 精确判断是否跳过子任务重放
    • 只允许整个子任务成功的记录被跳过
    • 进行中记录必须正常重跑
  • isSubtaskReplaySkipped

    • UI层检测子任务是否因防重放而跳过
    • 扫描所有日志条目而非仅第一条
    • 严格布尔值验证防止脏数据误判
flowchart TD
Plan["plan_task 结果"] --> Strategy{"strategy"}
Strategy --> Seq["sequential/dependency"]
Strategy --> Par["parallel"]
Seq --> ExecSeq["顺序执行 executeSingleSubtask"]
Par --> ExecPar["dispatchSubtasksParallel 并发受限池"]
ExecSeq --> CheckReplay{"shouldSkipSubtaskReplay?"}
ExecPar --> CheckReplay
CheckReplay --> |是| SkipUI["UI显示跳过标记"]
CheckReplay --> |否| ExecSubtask["执行子任务"]
ExecSubtask --> ProgressWriter["createSubtaskPartialProgressWriter"]
ProgressWriter --> PartialSummary["buildSubtaskPartialSummary"]
PartialSummary --> RecordProgress["recordSubtaskPartialProgress"]
RecordProgress --> Checkpoint["触发父checkpoint落盘"]
Checkpoint --> Done["onDone 进度回写/Checkpoint"]
Done --> Verify["完成度校验 annotateOneSubtaskCompletion"]
Verify --> Rerun{"rerunEnabled?"}
Rerun --> |是| Directive["缺项指令追加 user 消息"]
Directive --> ReRun["reactLoop 再跑一轮"]
ReRun --> |否| Result["返回子任务结果"]

图表来源

章节来源

反思机制:shouldReflect / buildReflectionPrompt / reflectOnResult ​

  • shouldReflect
    • 子任务内部不触发;存在 plan_task、工具失败、或工具调用次数≥2 时触发。
  • buildReflectionPrompt
    • 提取用户问题、工具执行详情、计划信息,输出结构化 JSON 评分维度。
  • reflectOnResult
    • 评估/修订解耦:先轻量评估,低于质量阈值才发起修订调用;支持多轮,记录 reflectionLog,最终决策 passed/revised/needs_improvement。
flowchart TD
Start(["后置反思入口"]) --> Should{"shouldReflect(executionLog, taskContext)?"}
Should --> |否| Skip["跳过反思"]
Should --> |是| Build["buildReflectionPrompt(messages, answer, executionLog)"]
Build --> CallEval["callApi(prompt, maxTokens)"]
CallEval --> Parse["parseReflectionResult(rawContent)"]
Parse --> Decision{"overallScore >= qualityThreshold?"}
Decision --> |是| Pass["passed"]
Decision --> |否| Revise["buildRevisionPrompt + callApi(revise)"]
Revise --> ParseRev["parseRevisionAnswer(refinedAnswer)"]
ParseRev --> Apply{"refinedAnswer 可用?"}
Apply --> |是| Revised["revised (wasRevised=true)"]
Apply --> |否| Needs["needs_improvement"]
Pass --> End(["返回 content/reflectionLog/status"])
Revised --> End
Needs --> End

图表来源

章节来源

错误恢复与检查点 ​

新增:检查点节流系统详解 ​

  • createCheckpointThrottle
    • 实现窗口内的多次请求合并成一次"尾随落盘"
    • 支持三种操作:request(reason, force)、cancel()、isPending()
    • 通过 identity 比对防止陈旧回调执行
    • 自捕获异常确保定时器回调不会抛出未处理拒绝
flowchart TD
Request["checkpointThrottle.request(reason)"] --> Force{"force=true?"}
Force --> |是| Immediate["立即落盘"]
Force --> |否| Throttle{"时间间隔<throttleMs?"}
Throttle --> |是| Merge["合并请求,更新原因"]
Throttle --> |否| Schedule["安排尾随落盘"]
Merge --> Pending["等待下次保存"]
Schedule --> TrailingFlush["尾随落盘"]
Immediate --> Complete["完成"]
TrailingFlush --> Complete

图表来源

检查点保存与恢复 ​

  • 检查点保存
    • 初始、plan_task 完成、tools_completed、final_answer、error/user_cancelled 等时机保存;节流 1500ms,子任务不保存。
  • 恢复流程
    • resumeReactLoopFromCheckpoint 读取 IndexedDB,清理不完整消息配对,注入恢复提示,重新调用 reactLoop,携带 checkpoint 状态(taskState/subtaskPlan/subtaskProgress/notesState)。
  • 异常处理
    • AbortError 传播取消语义;StreamIdleTimeout 本地化提示;HTTP 400 上下文超限自愈(最多 3 次,逐档更激进裁剪)。
flowchart TD
CPSave["saveCheckpointNow(reason, force)"] --> Persist["IndexedDB 写入 + 读回验证"]
CPRead["getReactCheckpoint(sessionId)"] --> Clean["cleanupIncompleteMessagePairs"]
Clean --> Inject["注入恢复提示/用户指导"]
Inject --> ReRun["reactLoop(..., resumeState)"]
ReRun --> Clear["clearCheckpoint(sessionId)"]

图表来源

章节来源

子任务超时预算计算增强 ​

新增:智能预算分配算法 ​

  • computeSubtaskLoopTimeoutMs
    • 移除了硬编码的900秒上限,改为基于配置的灵活预算分配
    • 引入60秒最小预算下限(SUBTASK_TIMEOUT_MIN_BUDGET),防止子任务刚启动就被终止
    • 支持父任务剩余时间的实时约束,确保子任务预算不超过父任务实际剩余
    • 按比例预留父任务收尾时间(5%,范围30秒到5分钟)

新增:大并发场景优化 ​

  • 当pendingSubtaskCount ≥ 116时,60秒最小预算下限接管,总和可能超过父剩余
  • 设计取舍:宁可超额也不饿死,防止大规模并发场景下的资源饥饿
  • 严格的父预算约束:任何情况下子任务预算都不超过父任务实际剩余

新增:React循环升级接线 ​

  • 改进了父任务实时剩余时间的传递机制
  • 使用getter函数替代静态快照,确保预算计算的实时性
  • 移除了旧的remainingTimeMs静态字段,改用getRemainingTimeMs()
flowchart TD
Input["computeSubtaskLoopTimeoutMs(parentRemainMs, configLoopTimeoutMs, pendingSubtaskCount)"] --> CapCheck{"配置有效?"}
CapCheck --> |是| UseConfig["使用配置作为上限"]
CapCheck --> |否| DefaultConfig["使用默认配置"]
UseConfig --> ParentCheck{"有父预算?"}
DefaultConfig --> ParentCheck
ParentCheck --> |否| ReturnConfig["直接返回配置值"]
ParentCheck --> |是| HardCap["hardCap = max(0, parentRemainMs)"]
HardCap --> Reserve["reserve = clamp(hardCap * 0.05, 30s, 5min)"]
Reserve --> Share["share = ceil(pendingSubtaskCount)"]
Share --> PerChild["perChild = max(0, hardCap - reserve) / share"]
PerChild --> Budget["budget = min(max(60s, perChild), hardCap)"]
Budget --> Final["return min(config, floor(budget))"]
ReturnConfig --> End["结束"]
Final --> End

图表来源

章节来源

观察结果字段优先级改进 ​

新增:observation字段优先机制 ​

  • buildSubtaskPartialSummary函数现在优先读取observation字段,result字段作为兜底
  • 生产环境中tool_exec节点的产出正文写在observation字段,不再写result
  • 保持向后兼容:如果observation缺失,自动回退到result字段

新增:字段契约明确化 ​

  • 明确区分生产环境字段(observation)和历史兼容字段(result)
  • 测试用例覆盖了observation优先、result兜底的完整路径
  • 防止历史代码回归:任何破坏observation优先逻辑的代码都会触发测试失败

章节来源

依赖关系分析 ​

  • react-loop.js 依赖
    • tool-executor.js:工具定义、执行、MCP/RAG 动态注册。
    • loop-detector.js:多模式循环检测。
    • react-reflection.js:后置反思与子任务反思。
    • completion-verifier.js:完成度校验编排。
    • subagent-depth.js:嵌套深度计数。
    • state/config/stream-controller/token-counter 等基础设施。
graph LR
RL["react-loop.js"] --> TE["tool-executor.js"]
RL --> LD["loop-detector.js"]
RL --> RR["react-reflection.js"]
RL --> CV["completion-verifier.js"]
RL --> SD["subagent-depth.js"]
RL --> UI["chat-manager.js"]

图表来源

章节来源

性能与预算控制 ​

  • Token 预算与上下文压缩
    • 动态计算 reactTokenBudget(上下文窗口 - 实际 system prompt - 工具定义 - 输出预留 - 安全余量),阈值 80% 触发批量压缩,保留最近 2 轮原文,其余轮次一次 LLM 调用结构化摘要;仍超标则权重裁剪(反思 > 工具结果 > 普通消息)。
  • 工具结果截断与卸载
    • MAX_TOOL_RESULT_TOKENS=6000,优先卸载到 Agent workspace(保留完整可回读),失败则智能截断。
  • 流式空闲超时
    • StreamIdleTimeout 保护,前端显示"思考中"状态行就地更新为"重试中"。
  • 子任务并发与超时
    • dispatchSubtasksParallel 使用 Set 跟踪在途任务,size 恒等于真实并发数;computeSubtaskLoopTimeoutMs 限制子任务整体超时。
  • 新增:子任务超时预算优化
    • 移除了硬编码的900秒限制,改为基于配置的灵活预算分配
    • 引入60秒最小预算下限,防止子任务刚启动就被终止
    • 支持父任务剩余时间的实时约束,确保预算合理性

章节来源

调试与故障排查 ​

  • 常见问题
    • 工具确认弹窗不出现:检查 keepalive port 是否存在、INTERACTION_DISPLAYED 回执是否送达、会话归属匹配。
    • 子任务卡住:检查子任务是否被 cancel、是否触发循环检测硬停、是否完成度校验 rerunEnabled 配置不当。
    • 上下文超限 400:查看 contextHealAttempts 自愈次数与 trimMessagesByBudget 裁剪比例。
    • MCP 工具未生效:确认 loadMcpTools 是否成功、服务器是否禁用、mcpToolIds 去重。
    • 新增:检查点保存失败:检查 createCheckpointThrottle 是否正确初始化,tail flush 是否正常触发。
    • 新增:子任务重放问题:确认 shouldSkipSubtaskReplay 逻辑,检查 progressHooks.progress 是否正确传递。
    • 新增:子任务超时预算异常:检查 computeSubtaskLoopTimeoutMs 的参数传递,确认父任务剩余时间是否正确获取。
    • 新增:观察结果字段问题:确认observation字段是否正确填充,result字段是否作为兜底正常工作。
  • 诊断要点
    • 执行日志节点 status 是否为 processing/failed/cancelled,observation 是否被截断。
    • loop-detector 的 nudge/stop 原因与 params。
    • reflection 的 overallScore 与 decision(passed/revised/needs_improvement)。
    • checkpoint 是否落盘成功(read-back 验证)。
    • 新增:子任务进度摘要:检查 buildSubtaskPartialSummary 输出的节点数量和内容。
    • 新增:UI显示问题:确认 isSubtaskReplaySkipped 是否正确识别 skippedReplay 标记。
    • 新增:预算计算问题:检查computeSubtaskLoopTimeoutMs的计算结果是否符合预期,特别是60秒下限和父预算约束。

章节来源

结论 ​

ReAct 推理循环通过 reactLoopImpl 将"思考-行动-观察"主循环与工具执行、循环检测、子任务管理、反思机制与错误恢复有机整合。其设计强调:

  • 安全性:敏感操作确认、不可信内容包装、内网访问门控。
  • 鲁棒性:检查点持久化与恢复、上下文超限自愈、流式空闲超时。
  • 可扩展性:MCP/RAG 工具动态注册、完成度校验编排、反思策略解耦。
  • 性能:Token 预算与批量压缩、工具结果卸载、并行子任务并发受限。

重大改进:本次更新引入了全新的检查点节流系统和子任务中断处理机制,显著提升了系统的鲁棒性和用户体验。新增了子任务超时预算计算的增强功能,移除了硬编码的时间限制,引入了智能的60秒最小预算下限机制,改进了父任务实时剩余时间的传递机制,并优化了观察结果字段的优先级处理。新的机制确保了数据不丢失,提供了细粒度的进度跟踪,并改进了用户界面的可视化反馈。

附录:扩展指南 ​

章节来源