【免费下载链接】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() 方法 就是主循环的入口。每一轮用户消息进来后,流程大致是:
- 前置上下文压缩检查:历史太长时先把早期对话压缩成摘要,避免上下文膨胀(compaction.mjs)。
- 思考:调用主模型(角色
main),模型要么直接给出回答,要么发出工具调用(Read/Glob/Grep/Edit/Write等)。 - 执行工具:所有工作区访问都走唯一的端口实现 NodeFsHost——路径先做词法边界检查,再用
realpath防止符号链接越界;写文件前有expectedHash防篡改和自动备份。 - 回灌结果:工具结果按唯一 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 开关后,一次请求依次经过:
- 主 Agent 常规 ReAct 回答(与不开启时完全一致)→ 落盘
baseline消息; - 门控判断 → 基线提取 → 初始观点板;
- 子问题拆解 + 并发回答;
- 探索 ReAct:调查 → 发散 → 核查 → 整理,重复 5 轮;
- 终稿由同一探索 Agent 输出(
Finish或直接回答),再由varina_delta角色吸收发散结果、重新回答原问题,生成吸收增量后的补充回答; - 观点板、事实账本、候选方案、未解决问题沉淀为
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
相关推荐
IPython架构深度解析:REPL循环、Jupyter Kernel与ZeroMQ如何协同工作
IPython架构深度解析:REPL循环、Jupyter Kernel与ZeroMQ如何协同工作 IPython 是 Python 增强版交互式外壳(Inter
开发工具CLI深度拆解 WebBrain 内部架构:Agent 循环、Service Worker 与 Content Script 如何协作
深度拆解 WebBrain 内部架构:Agent 循环、Service Worker 与 Content Script 如何协作 WebBrain 是一个开源的
oh-my-cli 架构剖析:Agent 循环、工具层与安全闸如何协同工作的完整指南
oh my cli 架构剖析:Agent 循环、工具层与安全闸如何协同工作的完整指南 oh my cli 是一个基于 Node.js 22 + TypeScri
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考