编者按:AI 编码 Agent 的使用方式,正在从「人手动写 Prompt、逐轮推进任务」,转向「人设计循环,让系统持续调度 Agent」。Addy Osmani 所说的 Loop Engineering(循环工程),核心是搭建一套能自动发现任务、分配任务、检查结果、记录进度并决定下一步的工作流。
这个循环大致由五个模块组成:Automations(定时发现和分诊任务)、Worktrees(隔离多个并行开发环境)、Skills(沉淀项目知识和团队惯例)、Plugins/Connectors(接入 GitHub、Linear、Slack、数据库等真实工具)、Sub-agents(让执行者和审查者分离),再加上一个外部记忆层,如 Markdown 文件或 Linear 看板,用来保存状态与进展。
文章提醒,Loop Engineering 的意义不只是「让 AI 多跑几轮」,而是把工程师的判断力前置到系统设计中。循环可以显著放大开发者的工作杠杆,但不会替代验证、理解和判断。真正的风险,也不在于使用循环,而在于把循环当成逃避理解代码和系统的借口。未来与 AI 编程协作的关键能力,或许不再只是写出一个好 Prompt,而是设计可靠、可验证、可持续运行的 Agent 工作流。
以下为原文:
Loop engineering(循环工程)正在取代你作为「给智能体写提示词的人」的角色。你要设计一个系统,让这个系统替你去提示智能体。这里的 loop(循环)可以理解为一种递归目标:你定义一个目的,AI 便不断迭代,直到任务完成。它大致由五个构件组成,而 Claude Code 和 Codex 现在都已经具备了这五个构件。
我相信,这可能就是我们未来与编码智能体协作的方式。不过,这一切仍处于早期阶段,我也保持怀疑。你绝对需要谨慎对待 token 成本,因为不同使用模式下,成本差异可能非常巨大,尤其取决于你是「token 富裕」还是「token 紧张」。你还需要有某种机制,确保质量不会下降。关于「AI 垃圾产出」(slop)的担忧也是合理的。话虽如此,我们还是来看看这到底是怎么回事。
@steipete 最近说过一句话:「你不应该再给编码智能体写提示词了。你应该设计一些循环,让这些循环去提示你的智能体。」类似地,Anthropic 的 Claude Code 负责人 @bcherny 也说:「我现在已经不再提示 Claude 了。我有一堆 loop 在运行,它们会提示 Claude,并自己判断下一步该做什么。我的工作就是写 loop。」
那么,这到底是什么意思?
过去大概两年里,你想让编码智能体做点什么,基本方式就是写一个好提示词,并提供足够多的上下文。你输入一句话,阅读返回结果,再输入下一句话。智能体是一个工具,而你一直握着这个工具,一轮接一轮地推动它。这个阶段某种程度上已经结束了,至少有些人认为它即将结束。
现在,你构建的是一个小系统:它会自己发现工作、分配任务、检查结果、记录完成情况,然后决定下一步要做什么。也就是说,你让这个系统去驱动智能体,而不是由你亲自一遍遍提示它。我之前写过它的「近亲」——agent harness engineering(智能体运行框架工程),也就是为单个智能体搭建运行环境;以及 factory model(工厂模型),也就是构建软件的系统。Loop engineering 则位于 harness 之上一层。它像 harness,但会按定时器运行,会生成小助手,并且会自我喂养。
让我意外的是,这现在已经不再只是「工具层面」的问题了。一年前,如果你想要一个 loop,你得写一大堆 bash 脚本,然后永远维护这堆脚本。那是你自己的东西,也只属于你自己。现在,这些组件已经直接内置在产品里了。Steinberger 列出的能力几乎可以一一对应到 Codex 应用里,也几乎同样可以对应到 Claude Code 里。一旦你意识到它们的形态是一样的,你就不会再纠结到底该用哪个工具,而是会去设计一个 loop:无论你坐在哪个工具里,它都能继续运转。
五个构件,以及一些说明
一个 loop 需要五样东西,外加一个用来记住信息的地方。我先列出来,再逐一对应。
第一,Automations(自动化任务):按计划触发,自动进行发现和分流。
第二,Worktrees(工作树):让两个并行工作的智能体不会互相踩到对方的文件。
第三,Skills(技能):把项目知识写下来,避免智能体每次都靠猜。
第四,Plugins and connectors(插件和连接器):让智能体接入你已经在使用的工具。
第五,Sub-agents(子智能体):一个负责提出方案,另一个负责检查方案。
然后是第六样东西:memory(记忆)。它可以是一个 Markdown 文件,也可以是一个 Linear 看板,或者任何独立于单次对话之外、能够保存「已完成事项」和「下一步事项」的地方。听起来简单到不像重要的事,但这是每一个长期运行的智能体都依赖的同一套技巧。我在 long-running agents 里也详细写过:模型在每次运行之间都会遗忘,所以记忆必须放在磁盘上,而不是放在上下文里。智能体会忘,但代码仓库不会。
现在,两款产品都已经具备这五个构件。

它们的命名有些地方不同,但能力本质上是同一回事。下面我逐一说明,因为说实话,一个 loop 最终是稳定运转,还是悄悄到处漏水,关键都在细节里。
Automations:这是 loop 的心跳
Automations 是让 loop 真正成为 loop 的东西,而不是你某次手动运行过的一次性任务。在 Codex 应用里,你可以在 Automations 标签页里创建一个自动化任务,选择项目、它要运行的提示词、运行频率,以及它是在你的本地 checkout 里运行,还是在后台 worktree 里运行。那些发现了问题的运行结果会进入 Triage inbox(分流收件箱),没发现问题的运行则会自动归档,这一点挺好。OpenAI 内部也会用它来做一些枯燥但必要的事情,比如每日 issue 分流、总结 CI 失败原因、撰写 commit 简报、追踪上周有人引入的 bug。自动化任务还可以调用 skill,所以你可以让反复运行的任务保持可维护:触发 $skill-name,而不是把一整墙的说明文字粘贴进一个以后没人会更新的计划任务里。
Claude Code 也能达到同样效果,只是路径不同:它通过调度和 hooks 实现。你可以用 /loop 按固定间隔运行一个提示词或命令,也可以安排一个 cron 任务,还可以在智能体生命周期的某些节点用 hooks 触发 shell 命令。如果你希望它在你合上电脑后继续运行,也可以把整套东西推到 GitHub Actions 上。思路完全一样:你定义一个自主任务,给它一个节奏,让发现结果来到你面前,而不是由你到处去检查。
还有一个值得了解的会话内原语,它更接近本文真正讨论的核心。/loop 会按节奏重复运行;/goal 则会持续执行,直到你写下的某个条件真正成立。每一轮之后,都会由一个单独的小模型来判断任务是否完成,所以写代码的智能体并不是给自己打分的那个。你可以给它一个条件,比如「test/auth 里的所有测试都通过,并且 lint 干净」,然后离开。Codex 也有同样的能力,同样叫 /goal。它会跨轮次持续工作,直到某个可验证的停止条件成立,并支持暂停、恢复和清除。同一个原语,两款工具都有。这基本就是本文反复出现的模式。
所以,Automations 负责把工作浮出水面。loop 的其余部分,则负责处理这些工作。
Worktrees:让并行不至于变成混乱
一旦你运行不止一个智能体,文件冲突就会成为失败点。两个智能体同时写同一个文件,本质上就和两个工程师在没有沟通的情况下修改同一行代码一样麻烦。git worktree 可以解决这个问题。它是在独立分支上的一个单独工作目录,但共享同一个代码仓库历史,因此一个智能体的修改从物理上就无法碰到另一个智能体的 checkout。
Codex 直接内置了 worktree 支持,所以多个线程可以同时处理同一个仓库而不会相互冲撞。Claude Code 也可以通过 git worktree 实现同样的隔离:你可以用 --worktree flag 在独立 checkout 中打开一个会话,也可以在 subagent 上设置 isolation: worktree,让每个小助手拿到一个全新的 checkout,并在结束后自动清理。我在 the orchestration tax 里写过这件事的人类侧面:worktrees 能消除机械层面的冲突,但你依然是上限。真正决定你能同时运行多少智能体的,不是工具,而是你的 review bandwidth(评审带宽)。
Skills:让你不必每次都重新解释项目
Skill 是一种机制,让你不必每次会话都像金鱼一样重新解释同一套项目上下文。两款工具使用的格式相同:一个文件夹,里面有一个 SKILL.md,保存说明和元数据;此外还可以有可选脚本、参考资料和资源文件。Codex 会在你用 $ 或 /skills 调用时运行一个 skill,也会在你的任务匹配该 skill 描述时自动运行。这也是为什么一个紧凑、朴素的描述,往往比一个聪明花哨的描述更好。Claude Code 的做法也是一样的,我在 agent skills 里写过这个模式。
Skills 也是让意图不再一遍遍消耗你的地方。我在 intent debt 里说过,智能体每次会话开始时都是冷启动的,只要你的意图里有空白,它就会用自信的猜测把空白填满。Skill 就是把这种意图写在外部:项目约定、构建步骤、「我们不这么做是因为以前发生过那次事故」等等,都一次性写在一个智能体每次运行都会读取的地方。没有 skills,loop 每一轮都要从零重新推导你的整个项目;有了 skills,它就有点像在复利增长。
有一点需要分清:skill 是编写格式,plugin 则是分发方式。当你想在多个代码仓库之间共享一个 skill,或者把几个 skill 打包在一起时,你会把它们封装成一个 plugin。Codex 如此,Claude Code 也是如此。
Plugins and connectors:让 loop 接触你的真实工具
一个只能看到文件系统的 loop,是一个很小的 loop。Connectors 基于 MCP 构建,可以让智能体读取你的 issue tracker、查询数据库、调用 staging API,或者在 Slack 里发消息。Codex 和 Claude Code 都支持 MCP,所以你为其中一个写的 connector,通常也能在另一个里使用。Plugins 则会把 connectors 和 skills 打包在一起,让你的队友一次安装完整配置,而不是凭记忆重建整套东西。
这就是「一个智能体告诉你『这是修复方案』」和「一个 loop 自己打开 PR、关联 Linear ticket,并在 CI 通过后通知频道」之间的区别。Connectors 之所以重要,是因为它们让 loop 能在你的真实环境里行动,而不只是告诉你「如果我能做,我会这么做」。
Sub-agents:让制造者远离检查者
在一个 loop 里,最有用的结构性设计,远远是把「写的人」和「检查的人」拆开。写代码的模型太容易在给自己的作业打分时表现得过于宽容。另一个带着不同指令、有时甚至使用不同模型的智能体,能够抓住第一个智能体自我说服后忽略的问题。
Codex 只会在你要求时生成 subagents,它们会并行运行,然后把结果合并回一个答案。你可以在 .codex/agents/ 里用 TOML 文件定义自己的 agents:每个 agent 都有名称、描述、指令,以及可选的模型和推理强度。因此,你的安全审查员可以是一个高强度推理的强模型,而你的探索者则可以是一个快速、只读的轻量模型。Claude Code 也通过 .claude/agents/ 里的 subagents 和 agent teams 实现类似能力,让多个 agent 在彼此之间传递工作。两边最常见的分工都是:一个 agent 探索,一个 agent 实现,一个 agent 根据规范验证。
我已经两次阐述过这个观点:一次是在 code agent orchestra,另一次是在 adversarial code review。它在 loop 里尤其重要,是因为 loop 会在你没有盯着的时候运行,所以一个你真正信任的 verifier(验证者),是你敢于离开的唯一理由。Subagents 确实会消耗更多 token,因为每个 agent 都要进行自己的模型调用和工具调用,所以你应该把它们用在「第二意见值得付费」的地方。这基本上也是 Claude Code 的 /goal 在底层做的事:由一个新的模型判断 loop 是否完成,而不是让完成工作的那个模型来判断。也就是说,它把「制造者」和「检查者」的分离应用到了停止条件本身。
一个 loop 长什么样
把这些东西拼在一起,一条单独的线程就会变成一个小控制面板。下面是我经常使用的一种结构。
每天早上,一个 automation 在代码仓库上运行。它的提示词会调用一个 triage skill,读取昨天的 CI 失败、开放中的 issues、最近的 commits,并把发现写入一个 Markdown 文件或 Linear 看板。对于每一个值得处理的问题,线程会打开一个隔离的 worktree,派一个 sub-agent 草拟修复方案,再派第二个 sub-agent 根据项目 skills 和现有测试来审查这个方案。
Connectors 让这个 loop 可以自己打开 PR,并更新 ticket。任何 loop 处理不了的东西,都会进入 triage inbox,交给我处理。状态文件是整套系统的脊梁:它记住尝试过什么、什么通过了、什么仍然未完成。因此,第二天早上的运行会从今天停下的地方继续。
注意你真正做了什么。你只是设计了一次。那些步骤并不是你亲自逐条提示出来的。这就是 Steinberger 那句话的现实版本。而且,同一个 loop 可以运行在 Codex,也可以运行在 Claude Code,因为构件本身是同一套构件。
Loop 仍然不会替你做什么
Loop 改变了工作方式,但并不会把你从工作中删除。事实上,随着 loop 变得更强,有三个问题会变得更尖锐,而不是更容易。
验证仍然取决于你。一个无人值守运行的 loop,也可能是在无人值守地犯错。你之所以要把 verifier sub-agent 和 maker 拆开,就是为了让 loop 说「完成了」这句话多少有点意义。即便如此,「完成」仍然是一个主张,而不是证明。我在 code review in the age of AI 里一直重复同一句话:你的职责是交付你确认有效的代码。
如果你放任不管,你自己的理解仍然会腐烂。Loop 越快交付你没有亲自写的代码,你实际理解的东西和系统里真实存在的东西之间的差距就越大。这就是 comprehension debt(理解债)。如果你不阅读 loop 产出的东西,一个顺滑的 loop 只会让这种债务增长得更快。
而且,是的,最舒服的姿态很可能也是最危险的姿态。当 loop 能自己运行时,你很容易停止形成自己的判断,只是接受它返回的任何东西。我把这叫作 cognitive surrender(认知投降)。如果你带着判断力去设计 loop,它就是解药;如果你设计 loop 只是为了逃避思考,它就是加速剂。同一个动作,会带来完全相反的结果。
构建 loop,但仍然做工程师
我认为,这预示着我们未来工作的演化方向。话虽如此,如果我不亲自审查代码,或者完全依赖自动化 loop 去修复代码,我的产品质量就会受到损害。我很可能会陷入一种向下螺旋:不断把自己挖进更深的坑里。
所以,你当然可以去搭建自己的 loop,但别忘了,直接提示你的智能体依然是有效的。关键在于找到合适的平衡。
Loop 的结果也会因人而异。两个人可以构建完全相同的 loop,却得到截然相反的结果。一个人用它在自己深刻理解的工作上提速;另一个人用它来逃避理解工作本身。Loop 并不知道这两者之间的区别。你知道。
这就是为什么 loop design(循环设计)比 prompt engineering(提示词工程)更难,而不是更简单。Cherny 的意思并不是工作变轻松了,而是杠杆点转移了。
构建 loop。但要像一个仍然打算做工程师的人那样去构建它,而不是像一个只负责按下「开始」按钮的人。
[原文链接]
