代理循环:为何最佳 AI 编码工作流是循环而非提示
本文探讨了代理循环(Agentic Loops)在 AI 编码中的核心作用,强调通过“行动→检查→重复”的小步迭代模式替代传统的一次性提示,以提升代码质量、安全性和可审计性。文章详细介绍了八个经过实战检验的循环模式及其关键设计原则。
大多数人在使用 AI 编码时仍然遵循着一种快节奏但缺乏记忆的模式:写一个提示,得到一段代码,大致看一眼,粘贴,然后祈祷。这种方法在小任务中或许可行,但一旦变更规模超出上下文窗口、风险超过一次差异、或者错误可能看起来合理时,就会失效。
真正通过代理交付实际工作的团队已经悄然转向一种不同的形态——不是提示,而是循环。
代理循环的核心很简单:行动 → 通过硬性门控检查 → 重复,直到收敛信号指示停止。代理每次只做一个微小改动,自动化门控决定该改动是否有效,循环持续运行——积累成功、回滚失败,并在没有值得做的改动时自动停止。有趣的部分并非代理本身,而是围绕它构建的框架,使得数千次自主小步行动变得安全。
我们刚刚发布了一组名为“Agentic Loops”的技能包,包含八个经过实战考验的编码代理循环模式。本文旨在解释其背后的理念。
一次性提示的天花板
要求代理一次性“修复所有失败的测试”或“将代码库迁移到新 API”总会遇到同样的障碍:
- 上下文溢出:一个涉及 200 个文件的重构无法放入上下文,代理只能猜测看不见的部分。
- 无法审查:单次提示产生的 600 行差异没有人会认真阅读,最多只是扫一眼就凭信心合并。
- 奖励看似正确实则错误:没有门控检查,代理的自信成了验收标准,但自信不等于正确。
- 没有停止机制:像“查找错误”这样的任务只运行一次就停止,无论是否找到了全部问题。
循环解决了上述所有问题——不是通过让代理变得更聪明,而是将工作单元从“一次大跃进”转变为“许多小步、经过检查的步骤”。
三个不变原则
每个有效的代理循环,无论任务是什么,都遵循同样的三条规则。跳过任何一条,循环就会退化为昂贵的忙碌工作,或者更糟——造成自信的破坏。
1. 每次迭代都有硬性自动化门控
门控是整个循环的核心。它是一个确定性的检查,代理无法通过辩解绕过:测试套件的退出码、tsc --noEmit 返回零、评估分数没有下降、每批次行数对账等。
规则:未通过门控的变更视为未发生。回滚,不合并。正是门控使得让十个代理并行编辑四十个文件成为安全之举——因为只有绿灯的变更才会落地。
2. 每次迭代只有一个可归属的变更
将“修复这四件事”打包成一个步骤,当两项通过、两项倒退时,你无法判断是哪个编辑导致了什么。代理开始用散弹枪式编辑来移动数字,你会失去头绪。
一次一个变更,一次门控运行,一次裁决。单独步骤更慢,但整体更快,因为每一步都可独立审查和回滚。当出问题时,你可以通过 git bisect 精确定位到具体行,而不是调试半成品。
3. 诚实的收敛信号
没有停止条件的循环要么永远运行,要么随意停止。解决办法是量化进展并依此停止:跳过率超过 50%、失败测试数降为零、漏洞发现器连续 K 轮无新发现、评估分数达到平台期。
这里的纪律是诚实的跳过。当页面已经完善,正确的输出是“没有改动,原因如下”——而不是强行做一个微不足道的调整来显得忙碌。一个知道何时完成的循环抵得上十个硬撑的循环。
循环能捕获而提示永远无法发现的问题
一个具体例子:我们将自我改进循环指向一个生产环境的管理面板——截取每个页面的屏幕截图,查看它,做出一个小改进,运行 tsc 加 eslint,然后重复。经过多轮迭代,它产生了大约 85 项改进,并且每批次数都通过了门控检查。
但最精彩的时刻并非打磨。某一轮,屏幕截图工具——同时也在监听未捕获的页面错误——发现了一个设置标签页渲染出了框架的整页崩溃屏幕。API 健康检查一直显示绿色,因为崩溃是客户端的。人类浏览缩略图可能会错过它。循环自动捕获了它,我们获得了实际错误(Cannot read properties of undefined (reading 'memes')),跟踪到一个状态合并错误,并从根源上修复了它——现在该工具将永久标记该类错误。
这就是回报:循环不仅完成工作,它还建立了一个棘轮,防止回归再次发生。
八个模式对应八项任务
该模式是通用的,门控和收敛信号随任务变化。技能包涵盖以下八种:
- 自我改进:截图 → 改进一项 → 测试;门控:
tsc0 /eslint0;停止条件:跳过率 > 50% - 测试与修复:运行测试 → 修复第一个失败 → 重新运行所有;门控:测试退出码;停止条件:失败计数归零
- 漏洞搜索:多样化发现者 → 怀疑者验证 → 修复;门控:通过对抗性审查 + 可复现;停止条件:K 轮无新发现
- 迁移:侦察站点 → 转换每个 → 验证;门控:每个文件类型检查 + 运行时;停止条件:未迁移残留归零
- 评估驱动:提议一项变更 → 重新运行评估 → 如果更好则保留;门控:无分数回归;停止条件:开发分数平台期
- 研究综合:收集 → 批评差距 → 填补;门控:每个主张引用已读来源;停止条件:评论家未发现差距
- 有测试的重构:小结构变更 → 完整测试套件;门控:套件每一步后均为绿色;停止条件:达到目标结构
- 数据回填:批次 → 检查点 → 验证 → 继续;门控:每批次不变性 + 对账;停止条件:游标完成且源等于目标
值得特别指出一些容易被误解的模式:
漏洞搜索成败取决于两个细节。发现者必须视角多样——给每个发现者不同的镜头(正确性、安全性、并发、泄漏),否则五个相同的发现者只会对同一个明显的空指针解引用达成一致。验证必须是对抗性的——要求“确认此漏洞”的验证者会随意盖章看似合理的废话;而要求“反驳此漏洞,默认反驳,仅在有具体复现时确认”的验证者会给出可信的结果。一个细微但致命的点:去重不仅要针对已确认的发现,还要针对所有见过的发现——否则每个被拒绝的发现都会被重新发现,循环永远不会枯竭。
测试与修复模式是故意偏执的。代理可能会通过删除断言来让测试通过。因此,循环每次迭代都会比较测试文件,拒绝任何缩小或削弱测试的变更。它一次只修复一个失败,然后重新运行整个套件(修复第一个失败常常会破坏第五个失败),并检测“卡住”——同一失败签名出现两次意味着升级,而非永远循环。
有测试的重构有一个不变原则:每一步的行为完全相同。如果测试套件很薄弱,代理会在触及结构之前编写特征测试,将当前行为(包括 bug)固定下来。然后它采取微小的步骤,使每一步都独立通过测试并可回滚。一旦需要修改测试才能通过,它就停止:那是以重构为名的行为变更。
数据回填建立在幂等性之上。一个处理一千万行数据的六小时工作可能被中断,因此每个批次必须安全地重新运行(通过键进行 upsert,绝不要盲目插入),并且游标必须在每个批次后设置检查点——因短暂故障从零重启意味着任务永远无法完成。它边运行边验证,并在最后进行源与目标的核对,因为“循环不再报错”不等于“所有数据都正确”。
如何构建你自己的循环
你不需要一个框架。你需要三样东西,以及诚实连接它们的纪律:
- 选择一个无法争辩的门控:退出码、类型检查、评估分数、行数。如果你说不出门控的名字,你就没有循环——你只有一种感觉。
- 使工作单元尽可能小:一个失败、一个页面、一个调用点、一个批次。可归属且可回滚。
- 量化收敛并尊重它:计数某个趋向于零的东西。让循环告诉你它完成了——当它这样做时,相信它。
然后,如果工作规模较大,就进行扇出:多个代理,每个拥有不同的切片(不同文件、不同页面),各自在执行任何提交前通过相同的门控。并行自主性之所以安全,完全是因为门控的存在。这就是全部诀窍。
结论
过去一年代理生产力的飞跃并非源于更聪明的模型写出更好的单次答案,而是源于一个认识:让一个足够好的代理采取一千个小而经过检查的步骤,比要求一个伟大的代理迈出完美的一步走得更远。
提示产生一个工件。循环产生一个过程——一个在你睡觉时仍在工作、拒绝交付未通过检查的内容、并在完成时诚实告知你的过程。
上述八个模式现已发布在 SkillDB 上,每个都包含哲学、循环图、可运行驱动、来之不易的陷阱以及确保安全的精确门控。让你的代理指向 Agentic Loops 包,给它一个循环去运行吧。