返回博客

持续 Agent 循环:别让它跑起来就不管了

大多数人第一次接触自主 Agent,都会被一件事迷住:它能连续跑很长时间,好像真的在「自主工作」。然后过一段时间就会被另一件事吓到:你回来一看,它在同一个错误上重试了三十次,什么都没做成,token 却烧掉了一大笔。

这两种体验之间的差距,就是「循环结构」设计的好坏。

先选对循环类型

不是所有的 Agent 任务都该用同一套循环。我用四个问题来做选型:

  • 需要严格的 CI 和 PR 把关 → 用持续集成驱动循环(每步都有 diff 检查、merge 门禁)
  • 任务本身需要分解成 RFC 再并行执行 → 用DAG 分解循环(先 plan,再 fan-out,再聚合)
  • 任务是开放性探索,需要大量并行生成再过滤 → 用无限并行循环(附 sample budget 限制)
  • 默认情况 → 用顺序循环(最简单,最容易调试)

选错类型带来的问题通常很隐蔽。比如把一个本该并行探索的任务硬套进顺序循环,结果每次都只能生成一条路径,收敛极慢;或者把一个简单的顺序任务包进 DAG,结果依赖关系管理比任务本身还复杂。

生产级循环的四层结构

光选对类型还不够。我在实际场景里沉淀出来的「能放心跑」的循环,通常有四层:

第一层:任务分解。把一个大目标拆成有明确接受标准的子任务。这一步的关键是「接受标准」——如果一个子任务完成的判定只有模型自己说了算,这个子任务就是隐患。每个子任务要有可验证的输出:文件存在、测试通过、API 返回特定状态码……总之要机器可判。

第二层:质量门。每轮循环结束前,跑一次质量检查,拦住没达标的输出,让它重来而不是往下传播。质量门的粒度要和子任务匹配——太宽松等于没有,太严格会让循环永远过不了。我的做法是先把门设宽,能跑通再逐步收紧。

第三层:eval 循环。区别于质量门(pass/fail 二元)的是,eval 是「这次比上次好了多少」。当你的任务是生成类的(写代码、写文案、生成配置),需要一个可量化的评估函数,让循环知道自己在进步还是在原地打转。

第四层:会话持久化。长时间运行的循环,session 会过期,上下文会断裂。把任务状态(已完成的子任务、当前进度、中间产物路径)外置成持久化存储,而不是只活在上下文里,是让循环能在中断后恢复的关键。

结构比提示词更重要

一个 Agent 循环能跑多远,主要由它的结构决定——分解粒度、质量门的位置、eval 函数的准确性。提示词优化是在结构稳定之后才有意义的精调手段,不是结构的替代品。

失控的四种模式

我把 Agent 循环常见的失控归纳成四类,每一类背后都有对应的结构缺失:

循环空转:一直在跑,但没有可见的进展。通常是质量门缺失,或者接受标准太模糊,模型不知道「完成」长什么样。

同根因反复重试:同一个错误,换了措辞重试了十几次,依然失败。根因没有被定位,每次重试都在重演。修复方式是在重试前强制做一次根因分析,把「发生了什么」写进下一轮的上下文,而不是直接把上一次的输出再扔回去。

合并队列卡死:DAG 循环里,某个节点的输出被依赖节点等待,但这个节点因为质量门没过被挂起——整个 DAG 冻结。需要超时机制和降级路径:等待超时后,把这个节点标记为「需要人工介入」,让其他分支继续跑。

成本失控:没有 token 预算上限,循环一直 escalate(切更贵的模型、把更多文档塞进上下文),成本指数级增长。这一条是我见过被低估最严重的风险。

失控后怎么恢复

一旦发现循环陷入上述任何一种模式,恢复的步骤是固定的:

  1. 先冻结循环,阻止它继续消耗资源。
  2. 跑一次 harness audit,看清楚现在到底卡在哪里——是哪个子任务、哪个质量门、还是哪个依赖关系。
  3. 把范围收缩到最小失败单元,不要试图一次修复所有问题。
  4. 用明确的接受标准重新 replay,这次在 prompt 里显式写清楚「这个子任务什么情况下算通过」。

顺序不能乱。很多人急着修提示词,但如果你不先弄清楚卡在哪里,改了提示词也不知道改没改对。

一句话心法

能持续跑的循环不是靠模型的「自主性」支撑的,而是靠结构——分解粒度、质量门、eval 函数、会话持久化,四个地方都到位了,「自主」才是真自主。