Skip to main content
普通 agent loop 让模型自己判断”做完了没”。Native Loop 把这个判断权收归 Runtime,用一套可校验的机制逼循环走向真正完成——模型只负责想和干,Runtime 负责判断是否完成。这篇展开讲这套机制怎么工作。

普通 agent loop 的缺陷

一个典型的 agent loop 是模型主导的:
框架只提供工具,“done” 由模型自己判断。这留了三个缺口:
  • 自述完成幻觉:模型说”我做完了”,但实际没测、没改、甚至没碰代码。
  • 上下文失忆:长任务被压缩或中断后,模型靠猜恢复进度,丢失”做到哪了”。
  • 无限打转:同一个验证失败反复出现,模型不断”改”但语义上没进展。
Native Loop 针对这三个缺口,设计了五个收敛机制。

机制一:验收缺口回灌

普通 loop 失败时,模型用自由文本描述”哪里有问题”,下一轮自己回忆。Native 不允许这样——Verify 失败时,Runtime 从已校验的验收矩阵里派生出结构化的缺口:
  • 哪些验收项 failed(跑过但没通过);
  • 哪些验收项 missing(还没提供证据);
  • 哪些 required check 失败了。
这些缺口作为结构化输入交给下一轮 Build,强制模型先补这些缺口,而不是重新自由发挥。模型不需要在对话里维护”还差什么”的记忆——Runtime 替它记着,而且记得精确。

机制二:语义进展判定

这是防止”无限打转”的关键。普通 loop 里,模型改了文件就算”有进展”,于是可以一直改下去。Native 的标准更严: 只有以下情况才算语义进展
  • failed 的验收项减少了;
  • 失败的检查转绿了;
  • 缺失的证据补上、恢复有效了。
反过来,以下情况不算进展
  • 改了文件、重写了实现,但失败的验收集合没变;
  • 改了 implementation scope,但缺口还在;
  • 重写了说明文字,但检查还是红的。
判定进展的依据是结果语义(缺口是否减少),不是活动量(改了多少代码)。这样模型就没法靠”一直改代码”假装在修复。

机制三:失败签名与三段式停止

Runtime 给每个失败算一个签名:由当前契约 hash + 排序去重的失败验收项 + 失败检查项组成。同一个签名反复出现,触发递进的停止: 第 3 次停下时,允许模型用一次 override 换个思路再试——但必须带一个具体的新假设,且同一个签名不能重复 override。这是给强模型”换个角度”的空间,又不让它无限重试。

机制四:总失败预算

除了按签名的停滞检测,每个契约还有一个总预算:默认同一份需求最多 5 次 Verify 失败(可用 native.max_verify_failures 调)。 预算用完,Runtime 停下交还用户,一次说清当前证据和三个方向:
  • 放宽上限;
  • 修改已确认的需求;
  • 停下。
只有用户确认后的需求变更才会重置预算——普通的实现改动不会。这个设计让强模型能连续修复多轮,同时给它划了一条硬边界。

机制五:恢复依赖仓库状态

整个 loop 的状态不在对话里,而在磁盘上:
  • 验收条件和缺口 → comet-state.yaml、acceptance matrix;
  • 阶段内进度 → checkpoint;
  • 验证证据 → verification.md、receipt;
  • 实现范围 → implementation scope(内容哈希)。
会话中断后,模型重新进入时跑一次状态读取,就能精确恢复:当前在哪个阶段、还差哪些验收、上一次失败是什么。不依赖聊天记忆,所以上下文压缩或换设备都不会让 loop 失忆。

为什么不新增第五个阶段

Native 明确拒绝为这个 loop 造一个独立的”Loop Engine”阶段或新 CLI 命令。收敛逻辑直接织进现有的 Build ↔ Verify 状态机:Build 负责实现和修复,Verify 负责校验和派生缺口,Runtime 在两者之间驱动收敛。 这种克制本身是设计哲学:Loop Engineering 不是又一个 Loop Engine,而是让现有的四阶段状态机自带收敛能力——少一层抽象,少一处可能出错的状态。

一句话总结

普通 loop 是”模型判断 done”;Native Loop 是”Runtime 用内容寻址的证据、失败签名、语义进展判定和磁盘恢复,逼循环走向真正完成”。模型可以放手去干,因为跑不偏的保证在 Runtime,不在模型自觉。 想看这套机制在一次真实需求里怎么跑,见 Native 实战演练。想了解验证证据和修复上限的完整规则,见 验证证据与自主修复
最后修改于 2026年8月2日