让 AI Agent 自己跑完整轮——自主循环的五种姿势
最开始用 AI 写代码,我的习惯是一问一答:让它写函数,看结果,再让它改。后来我意识到,绝大多数开发动作其实是有固定节奏的——实现、清理、验证、提交——把这个节奏写成脚本,让 Agent 自己把一轮跑完,效率会有质的飞跃。
这篇文章整理了我在实践中积累的几种「自主循环」模式,以及我在每种模式上踩过的坑。
从最简单的姿势开始:顺序流水线
claude -p 是 Claude Code 的非交互模式,执行完退出。把几个 -p 调用串成 shell 脚本,就是最简单的自主循环:
#!/bin/bash
set -e
# 第一步:实现
claude -p "根据 docs/spec.md 用 TDD 方式实现功能,先写测试再写实现。"
# 第二步:清理(见下文)
claude -p "检查工作区变更,删除冗余的类型测试、过度防御的 check、被注释的代码。跑一遍测试确认没有破坏。"
# 第三步:验证
claude -p "跑完整的 build + lint + test,修复任何失败,不要新增功能。"
# 第四步:提交
claude -p "为所有暂存变更生成符合规范的 commit message 并提交。"每一步都是独立的上下文窗口,干净、可预期。set -e 保证任何步骤失败都停下来,不会把烂摊子带到下一步。
这个模式够用的场景比我想象的多:一个功能分支、一次批量重构、一轮安全扫描,都可以这么跑。
一个反直觉的原则:别用负向指令,加一个清理步
我之前的做法是在实现 prompt 里加约束:「不要写测试框架行为的用例」「不要加过度的 null check」。结果适得其反——模型变得畏手畏脚,连该写的边界测试也跳过了。
正确做法是让实现步骤自由发挥,然后加一个独立的清理步(De-Sloppify Pass):
不要用负向指令限制实现步骤,而是让它充分发挥,然后用独立的清理 Agent 专门删除冗余产物。两个上下文窗口分别聚焦「生产」和「精简」,比一个身兼二职的窗口质量更高。
这个道理推广开来就是:同一个上下文窗口不适合同时扮演「作者」和「审稿人」。作者有偏见,他倾向于为自己写的东西辩护。把审稿单独拆出来,让一个没有写过这段代码的 Agent 来看,发现的问题会多很多。
跨迭代的上下文桥接
用 -p 模式跑循环有一个内在限制:每次调用都是全新上下文,上一轮知道的事情这一轮全忘了。
解决办法是文件系统当桥梁。一个 SHARED_TASK_NOTES.md 记录进度、已解决的问题、下一步要做什么;每一轮开始时读它,结束时更新它。这不是什么高深技巧,但很多人忘记做这一步,然后在第三轮发现 Agent 在重复第一轮已经修过的问题。
同理,如果循环涉及 CI/CD,要把失败的 log 主动写入文件喂给下一轮,不要期望 Agent 自己去找。给它上下文,而不是让它重新侦探。
需要并行时:DAG 分解 + 合并队列
当一个功能大到需要多个 Agent 并行实现不同模块,顺序流水线就不够用了。这时候需要更复杂的编排:
- 先把工作拆成依赖图(DAG)——哪些单元没有依赖可以并行,哪些必须等前者落地。
- 每个单元在独立的 worktree 里跑,彼此不干扰文件系统。
- 合并队列做序列化——并行实现,但串行落地,每次合并前 rebase 到最新 main,跑完整测试。
合并冲突不可避免。关键是带着冲突上下文重试,而不是盲目重跑。把冲突的文件 diff、失败的测试输出一起喂给下一次实现,Agent 才能有针对性地处理,而不是凭空猜测。
这套模式的成本比顺序流水线高得多,只有在「多个独立模块确实可以并行、且合并风险可控」时才值得上。
在复杂度光谱上找对自己的位置
五种模式按复杂度排:单步 -p、持久会话 REPL、规格驱动的并行生成、带 CI 门禁的连续 PR 循环、RFC 驱动的 DAG 多 Agent 编排。
决策树很简单:
- 单一聚焦变更 → 顺序流水线
- 需要生成大量同类变体 → 并行规格驱动
- 多天迭代、需要 CI 反馈 → 连续 PR 循环
- 多模块并行、有 RFC 文档 → DAG 编排
大多数日常工作落在前两档。我见过的最常见错误是上来就搭 DAG,然后在编排层花了大量时间,实际代码质量反而不如一个清晰的顺序流水线。
一句话心法
自主循环的复杂度要匹配任务复杂度,而不是匹配你对「AI 工程」的想象。