Loop Engineering:用循环系统取代手动 Prompt
Loop engineering(循环工程)的核心思想是:取代你自己去 Prompt Agent,转而设计一个系统来替你做这件事。 这里的“循环”可以理解为一个递归目标——你定义一个目的,AI 反复迭代直到完成。它大致由五个构建模块组成,而 Claude Code 和 Codex 现在都已经具备了这五个模块。
我相信这可能代表了我们与编程 Agent 协作方式的未来。不过现在还早,我仍然持怀疑态度,而且你必须小心 token 成本(你的 token 预算充裕还是紧张,使用模式会截然不同)。你仍然需要某种方式来确保质量不会下降,对“AI slop”的担忧是合理的。话虽如此,让我们来看看这到底是什么。
@steipete 最近说:“你不应该再去手动 Prompt 编程 Agent 了。你应该设计循环来替你 Prompt Agent。“同样,Anthropic Claude Code 负责人 @bcherny 也说过:“我不再手动 Prompt Claude 了。我有循环在运行,它们负责 Prompt Claude 并搞清楚该做什么。我的工作是编写循环。”
好吧,这些话到底是什么意思?
过去两年里,从编程 Agent 获得产出的方式是:你写一个好 Prompt,分享足够的上下文。你输入一条,读一下返回的结果,再输入下一条。Agent 是一个工具,你从头到尾都握着它,一轮接一轮。这个阶段差不多结束了,或者至少有些人认为即将结束。
现在的做法是:你构建一个小系统,由它来发现工作、分配任务、检查结果、记录完成情况,然后决定下一步。你让这个系统去驱动 Agent,而不是你自己。我之前写过这个概念的近亲——agent harness engineering(Agent 约束工程),即构建单个 Agent 运行的环境;还有 factory model(工厂模型)——构建软件的系统。Loop engineering 位于 harness 之上一层。它是 harness,但按定时器运行,它会衍生小帮手,并自行获取信息。
让我惊讶的是,这已经不再是一个工具问题了。一年前,如果你想要一个循环,你得写一大堆 bash 脚本,然后永远维护那堆脚本,而且只有你自己用。现在这些组件直接内置于产品中。Steinberger 列出的清单几乎完全映射到 Codex 应用,然后也几乎同样映射到 Claude Code。一旦你注意到它们的结构是一样的,你就不再争论该用哪个工具了——你只需要设计一个循环,无论你碰巧坐在哪个工具里都能工作。
五个组件,以及一些补充说明
一个循环需要五样东西,外加一个记住状态的地方。让我先列出来,然后逐一映射。
- Automations(自动化) — 按计划自动运行,自行发现和分类工作。
- Worktrees(工作树) — 让两个并行工作的 Agent 不会互相踩脚。
- Skills(技能) — 把项目知识写下来,让 Agent 不再瞎猜。
- Plugins & Connectors(插件和连接器) — 把 Agent 接入你已经使用的工具。
- Sub-agents(子 Agent) — 让一个负责产出想法,另一个负责检查。
然后是第六样东西:记忆(Memory)。一个 Markdown 文件,或一个 Linear 看板,任何存在于单次对话之外、记录已完成和待办事项的东西。听起来简单到不值一提。但这是每个长时间运行的 Agent 都依赖的技巧,我在 long-running agents 中详细讨论过:模型在两次运行之间会忘记一切,所以记忆必须存在于磁盘上而不是上下文中。Agent 会忘记,但仓库不会。
两个产品现在都具备了全部五个组件。

各个组件的名称可能略有不同,但能力是一样的。让我逐一展开,因为说实话,细节才是循环能稳住还是悄悄漏得到处都是的关键。
Automations:这是心跳
Automations 是让循环成为“循环”而不是“你做了一次就结束”的东西。在 Codex 应用中,你在 Automations 标签页创建一个自动化,选择项目、它将运行的 Prompt、频率,以及是在本地代码库还是后台 worktree 上运行。发现问题的运行会进入 Triage 收件箱,没发现问题的运行会自动归档——这很贴心。OpenAI 内部用它们来做那些枯燥的事情:每日 issue 分类、汇总 CI 失败、编写 commit 摘要、追踪上周有人引入的 bug。而且一个 automation 可以调用 skill,所以你把重复性任务维护好,只需触发 $skill-name 而不是在调度器里粘贴一大堆没人会去更新的指令。
Claude Code 通过调度和 hooks 到达同样的地方。你可以用 /loop 按间隔运行 Prompt 或命令,可以安排 cron 任务,可以在 Agent 生命周期的特定节点通过 hooks 触发 shell 命令,或者如果你想让它在关闭笔记本电脑后继续运行,可以把整个东西推到 GitHub Actions。完全一样的思路——你定义一个自主任务,给它一个节奏,发现的结果送到你面前,而不是你自己到处去查。
还有一个会话内的原语值得了解,它更接近这篇文章的核心。/loop 按节奏重新运行。/goal 则持续运行直到你写的某个条件真正成立——每轮之后,一个独立的小模型检查你是否完成了,所以写代码的 Agent 不是给自己打分的那个。你给它类似“test/auth 里所有测试都通过且 lint 干净”这样的条件,然后走开。Codex 有同样的东西,也叫 /goal,它跨轮次持续工作直到一个可验证的停止条件成立,支持暂停、恢复和清除。同样的原语,两个工具都有——这基本上是整篇文章的模式。
这就是浮现工作的部分。循环的其余部分是对工作采取行动的部分。
Worktrees:让并行不变成混乱
当你运行多个 Agent 的那一刻,文件就开始冲突——这就是失败的根源。两个 Agent 写同一个文件,和两个工程师提交到同一行代码却互不沟通,是完全一样的头疼事。git worktree 解决了这个问题——它是一个独立的工作目录,在自己的分支上,共享同一个仓库历史,所以一个 Agent 的编辑字面上不可能碰到另一个的检出。
Codex 直接内置了 worktree 支持,所以多个线程可以同时操作同一个仓库而不互相干扰。Claude Code 通过 git worktree 提供同样的隔离——一个 --worktree 标志在独立检出中打开会话,以及一个 isolation: worktree 设置用于子 Agent,让每个帮手都有一个用完自动清理的全新检出。我在 the orchestration tax 中写过这方面的人的因素——worktrees 解决了机械碰撞,但你仍然是天花板,你的 Review 带宽决定了你实际上能跑多少个,而不是工具。
Skills:别再每次都重新解释你的项目
Skill 是让你不再像个金鱼一样每次会话都重新解释项目上下文的方式。两个工具都用相同的格式——一个包含 SKILL.md 的文件夹,里面有指令和元数据,然后是可选的脚本、参考资料和资源。Codex 在你用 $ 或 /skills 调用时运行 skill,或者当你的任务匹配 skill 描述时自动运行——这就是为什么一个精确而无聊的描述比一个花哨的描述更好。Claude Code 的做法一样,我在 agent skills 中写过这个模式。
Skills 也是让你的意图不再反复花费成本的地方。我在 the intent debt 中论述过:Agent 每次会话都是从头开始的,它会用自信的猜测填补你意图中的任何空白。Skill 是把意图写在外面的方式——约定、构建步骤、“我们不这样做是因为那次事故”——写一次,Agent 每次运行都读。没有 skills,循环每个周期都从零重新推导你的整个项目;有了 skills,它就有点像复利了。
有一点要搞清楚:skill 是创作格式,plugin 是分发方式。 当你想跨仓库分享 skill 或把几个打包在一起时,你把它们封装成 plugin。Codex 如此,Claude Code 亦然。
Plugins 和 Connectors:循环触碰你的真实工具
一个只能看到文件系统的循环是一个很小的循环。Connectors(连接器)建立在 MCP 之上,让 Agent 能读取你的 issue 追踪器、查询数据库、访问 staging API、在 Slack 里发消息。Codex 和 Claude Code 都支持 MCP,所以你为一个写的连接器通常在另一个里也能直接用。而 plugins 把 connectors 和 skills 打包在一起,你的队友一次性安装你的整套配置,而不是从记忆中重建整个东西。
这就是“Agent 告诉你‘这是修复方案’”和“循环自己打开 PR、关联 Linear ticket、CI 通过后 ping 频道”之间的区别。Connectors 是循环能在你的实际环境中行动而不只是告诉你它会怎么做的理由。
Sub-agents:让制造者远离检查者
在一个循环中,到目前为止最有用的结构性设计,就是把写代码的和检查代码的分开。写代码的模型给自己的作业打分,实在太宽容了。 一个有着不同指令、有时还用不同模型的第二个 Agent,能抓住第一个 Agent 说服自己接受的那些东西。
Codex 只在你要求时才衍生子 Agent,并行运行它们,然后把结果合并为一个答案。你在 .codex/agents/ 中用 TOML 文件定义自己的 Agent,每个都有名称、描述、指令和可选的 model 与 reasoning effort——所以你的安全审查者可以是高 effort 的强模型,而你的探索者可以是某种快速的只读模型。Claude Code 通过 .claude/agents/ 中的 subagents 和在工作传递的 agent teams 做同样的事。两者中通常的分工是:一个 Agent 探索,一个实现,一个对照规格验证。
我已经两次论证过这一点,一次作为 the code agent orchestra,一次作为 adversarial code review。它在循环中特别重要的原因是:循环在你没看着的时候运行,所以一个你真正信任的验证者是你能走开的唯一理由。 子 Agent 确实会消耗更多 token,因为每个都有自己的模型和工具调用,所以把 token 花在值得第二意见的地方。这也基本上就是 Claude Code 的 /goal 底层做的事——一个新模型决定循环是否完成,而不是做工作的那个模型。制造者和检查者的分离,应用到了停止条件本身。
一个循环长什么样
把它们组合在一起,单线程就变成了一个小控制面板。这是我经常使用的一种形态。
一个 automation 每天早上在仓库上运行。它的 Prompt 调用一个 triage skill,读取昨天的 CI 失败、开放的 issue、最近的 commit,然后把发现写入一个 Markdown 文件或 Linear 看板。对于每个值得处理的发现,线程打开一个隔离的 worktree,派一个子 Agent 起草修复,第二个子 Agent 对照项目 skills 和现有测试审查这个草稿。
Connectors 让循环打开 PR 并更新 ticket。任何循环处理不了的东西进入我的 triage 收件箱。状态文件是整个系统的主心骨——它记住了什么被尝试过、什么通过了、什么还开着——所以明天早上的运行从今天停下的地方接续。
看看你实际做了什么。你只设计了一次。你没有任何一步是手动 Prompt 的。 这就是 Steinberger 的观点变成了现实,而且无论在 Codex 还是 Claude Code 里都是同样的循环,因为组件是一样的。
循环仍然替你做不了的事
循环改变了工作方式,它并没有把你从工作中删除。而且有三个问题实际上随着循环变得更好而变得更加尖锐,而不是更容易。
验证仍然在你身上。 一个无人值守运行的循环,也是一个无人值守犯错的循环。你把验证子 Agent 和制造者分开的全部理由,就是让循环的“完成了”有意义——即使如此,“完成了”是一个声明而不是证明。我一直重复着在 code review in the age of AI 中说的那句话:你的工作是发布你确认能用的代码。
你的理解力在你允许的情况下会衰退。 循环越快地发布你没写过的代码,存在的东西和你真正理解的东西之间的差距就越大。这就是 comprehension debt(理解债务),一个流畅的循环只会让它增长得更快——除非你去读循环产出的东西。
舒适的姿态可能恰恰是危险的姿态。 当循环自己运行时,非常诱人的做法是停止有自己的意见,直接接受它给你的任何东西。我称之为 cognitive surrender(认知投降)。设计循环在你有判断力时是解药,在你用它来逃避思考时是加速器——同一个动作,相反的结果。
构建循环。保持工程师的身份。
我认为这是我们工作方式演进的一个预览。话虽如此,如果我不亲自审查代码,或者完全依赖自动化循环来修复它,我的产品质量会受到影响。我可能会陷入下行螺旋,不断把自己挖进更深的坑里。
尽管如此,去搭建你的循环吧,但别忘了直接 Prompt 你的 Agent 仍然有效。关键在于找到正确的平衡。
循环也可能因为你的不同而产生不同的结果。两个人可以构建完全相同的循环,却得到截然相反的结果。一个用它来在自己深刻理解的工作上跑得更快。另一个用它来完全不用理解工作。循环不知道区别。你知道。
这就是让循环设计比 Prompt engineering 更难而不是更容易的原因。Cherny 的观点不是工作变得更简单了。而是杠杆的支点移动了。
构建循环。但要像一个打算继续保持工程师身份的人那样去构建,而不是像一个只负责按下启动按钮的人。
评论互动