☰
Varina架构全貌深度图解:Agent循环、ReAct工具循环与后置探索引擎是如何协同的
2026/10/29 18:59:40 网站建设 项目流程

【免费下载链接】Varina

项目地址:https://gitcode.com/gh_mirrors/ah/Varina
点击查看免费下载

Varina 是一个面向机制设计的开源创作 Agent(创意代理)。它的核心由三部分组成:Agent 主循环(一次对话的有界 ReAct 工具循环)、后置探索引擎(常规回答完成后的深度发散阶段),以及连接二者的门控与核查机制。本文将用通俗语言图解这三条主线如何协同工作,并标注关键源码位置,帮你快速建立对 Varina 架构的完整认知。

一分钟看懂 Varina 架构总览

Varina 的设计原则是:主产品是 Agent,不是 workflow。依赖方向严格分层——Web 工作台、CLI、MCP 三种入口都汇到同一个AgentService,再进入AgentSession的有界工具循环;后置探索引擎则挂在常规回答完成之后。

官方架构文档给出了这张总览图(ARCHITECTURE.md):

Web / CLI / MCP | v AgentService ── SessionStore | v AgentSession (conversation + bounded tool loop) | \ v v CodebaseHost Post-ReAct Varina stage | | v v NodeFsHost Gate → Baseline extraction → Decomposition → Subproblem answers | v Exploration ReAct / | \ Read/Glob/Grep Diverge UpdateBoardItem | | Seats → Dedup +→ FactLedger | | +→ MeetingBoard | v Finish / final answer

读这张图只需记住一句话:主 Agent 负责"读项目、给出常规回答";后置探索引擎负责"围绕同一问题多视角反复发散、核查、整理"。下面逐层拆解。

第一层:Agent 主循环(ReAct 工具循环)是怎么转的

AgentSession的 turn() 方法 就是主循环的入口。每一轮用户消息进来后,流程大致是:

  1. 前置上下文压缩检查:历史太长时先把早期对话压缩成摘要,避免上下文膨胀(compaction.mjs)。
  2. 思考:调用主模型(角色main),模型要么直接给出回答,要么发出工具调用(Read/Glob/Grep/Edit/Write等)。
  3. 执行工具:所有工作区访问都走唯一的端口实现 NodeFsHost——路径先做词法边界检查,再用realpath防止符号链接越界;写文件前有expectedHash防篡改和自动备份。
  4. 回灌结果:工具结果按唯一 ID 与调用 1:1 配对,塞回对话,进入下一轮思考。整个循环受maxToolIterations(默认 100 次)与取消信号限制,直到模型不再调用工具、给出最终回答。

这就是经典的ReAct 工具循环:思考 → 行动 → 观察 → 再思考,有界、可取消、每一步都持久化。

体积闸门:超大工具结果"落盘"而不是"截断"

主循环有一个很精妙的设计:工具结果进对话前必须过体积闸门(tool_result_budget.mjs)。规则是:

维度阈值
单条 Grep 结果20,000 字符
单条其他工具结果50,000 字符
单轮工具结果合计200,000 字符
落盘后回给模型的预览2,000 字符

超过阈值时不是简单截断丢信息,而是把完整内容写入工作区.varina/tool-results/,对话里只保留persisted_path和预览,模型需要细节时自己用Read取回。另外listFiles/grep默认跳过.varina目录,避免运行时数据污染检索结果。

会话管理:互斥、取消与中断恢复

AgentService 负责会话创建、单会话互斥(同一会话同时只允许一轮处理)、取消和事件广播。进程重启后,处于运行态的会话会被标记为interrupted,避免自动重复调用模型——这对付费的模型调用是个重要的省钱保护。持久化状态中不包含 API Key。

第二层:后置探索引擎是怎么被启动的

关键点:后置探索引擎不是主 Agent 的一个工具。即使开启 Varina 开关,常规回答的 prompt、工具集、ReAct 过程完全不变;深度探索只在常规回答完整落盘之后才启动(runPostReact)。

启动前有一道门控(Gate),分两步:

  • 判断:由独立的决策网关(真实模式下是 Jev 决策网关,只提交状态并读取START / ASK概率,不生成用户可见文本)评估"这个问题值不值得深度探索";未配置凭据时回退到本地varina_gate角色模型。
  • 裁决:VarinaGateController 采用刻意不对称的策略——不确定时默认启动(uncertain_defaults_to_start);只有当判断明确认为"显然与深度探索无关"(如一句问候)时才弹出让用户确认,避免浪费模型调用。

第三层:探索引擎内部,从基线到多席位发散

门控通过后,ExploreDesignEngine.run() 按固定顺序推进:

基线提取:把常规回答变成初始观点板

先用结构化提取器(角色baseline_extraction)把刚才的常规回答解析为任务框架、用户约束、假设和一批观点,写入观点板(MeetingBoard),标记为 round 0。基线观点不受后续每轮 0–3 条贡献上限的影响——也就是说,探索是在已有回答之上增量推演,而非推倒重来。

子问题拆解与并发回答

ReAct 启动前,多席位(默认 5 席、最多 3 轮、共最多 20 题)把大问题拆成可独立回答的子问题,判重后并发逐题回答(每题默认 2 个回答),答案要素并入初始观点板(配置见 config.example.json)。

探索 ReAct 循环:三件专用工具

主体是 src/varina/react.mjs 中的独立 ReAct 循环,只有 6 个工具:

工具作用
Read/Glob/Grep自主调查项目资料(只读,无写文件工具)
Diverge触发一轮多席位发散:各席位拿到相同冻结背景和不同的思考任务卡,返回去重后的观点增量
UpdateBoardItem一次调用同时更新观点板和事实账本,省去单独的 RecordFact 往返
Finish提交回答原问题的终稿,校验方案只引用活跃、非子问题观点

循环的关键约束:默认要求完成 5 轮发散(exploration.rounds允许 1–5),提前交卷会被程序干预——自动追加一次合成的Diverge调用再继续;达到上限后Diverge返回ROUND_LIMIT。步数耗尽(默认 100 步)、取消或模型失败时,保留部分结果并明确标记未完成。

认知算子:40 张"思考任务卡"

Diverge内部的差异化来自 operators.mjs 中的40 个通用算子,分为前提、结构、对抗、反演、连接、简化、演化、主体八类。每个席位从不同类别抽取三张算子卡,在同一份问题、约束和已核实背景上思考。算子不是"创意家"之类的身份扮演,而是可检查的动作指令:找出被默认的前提、构造足以改变结论的反例、倒推失败原因……每张卡还要求讲清推导和适用边界,空泛的"换个角度想"不算完成。

事实核查:观点必须"有据可查"

发散产生的观点默认是未核查的。探索 Agent 用Read查证资料后,通过UpdateBoardItem把事实写入事实账本(FactLedger):confirmed/contradicted/partially_true必须引用本次实际读取过的路径、行范围、原文片段和文件哈希;资料不足用unknown。删除观点只标deleted,保留修订历史和事实,后续发散能看到删除原因——观点板因此是一本可回溯的"设计会议纪要"。

三条主线如何协同:一次请求的完整旅程

把前面串起来,开启 Varina 开关后,一次请求依次经过:

  1. 主 Agent 常规 ReAct 回答(与不开启时完全一致)→ 落盘baseline消息;
  2. 门控判断 → 基线提取 → 初始观点板;
  3. 子问题拆解 + 并发回答;
  4. 探索 ReAct:调查 → 发散 → 核查 → 整理,重复 5 轮;
  5. 终稿由同一探索 Agent 输出(Finish或直接回答),再由varina_delta角色吸收发散结果、重新回答原问题,生成吸收增量后的补充回答;
  6. 观点板、事实账本、候选方案、未解决问题沉淀为VarinaRunRecord,完整记录保存在会话的varina_runs中,工作台可按需回看。

值得注意的协同细节:同轮所有席位收到的公共消息完全一致(含仓库快照repository_snapshot_id和packet_token),席位特有的算子排在公共前缀之后——这保证了发散来自"角度差异"而非"信息差异"。

稳定性设计:预算、重试与恢复

  • 上下文压缩:探索循环的机械压缩只裁剪较早的读取/搜索正文;Diverge/UpdateBoardItem/Finish的调用与完整结果永不裁剪,预算耗尽时报EXPLORATION_CONTEXT_LIMIT而不是删历史硬撑(react.mjs)。
  • 统一重试判据:retry_policy.mjs 只对 408/409/429/5xx 重试,400 立即失败,模型调用统一走ModelGateway(model_gateway.mjs)。
  • 中断可恢复:探索运行态写入active_varina_runtime检查点,相同工具 ID 和参数不会重复执行;awaiting_varina_confirmation状态在重启后仍可继续。

上手与延伸阅读

  • 本地启动 Web 工作台:npm start(需 Node.js 22+,项目无第三方 npm 依赖),打开http://127.0.0.1:27333使用;
  • CLI 对话:npm run run -- --workspace <项目目录>;输入/varina可显式触发新一轮深度探索,/init生成工作区VARINA.md项目档案;
  • 作为 MCP 工具接入其他客户端:varina_chat对话、varina_design_architecture显式启动探索(mcp.mjs);
  • 模型角色与探索参数(轮次、席位、预算)都在 config.example.json 中,配置加载与旧版迁移逻辑见 config.mjs;
  • 回归测试覆盖旧配置迁移、模型回退、Web 会话、深度探索与 MCP 协议,运行npm test(test/)。

想深入细节,建议按 ARCHITECTURE.md 的章节顺序对照源码阅读:先AgentSession的主循环,再看gate.mjs的门控,最后进 explore_design.mjs 看发散与核查的完整实现。

【免费下载链接】Varina

项目地址:https://gitcode.com/gh_mirrors/ah/Varina
点击查看免费下载

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询