翻译 | Loop Engineering:循环工程
原文作者:Addy Osmani
原文链接:Loop Engineering
发布日期:2026 年 6 月 7 日
译者注:全文翻译,保留原文结构与所有内链引用。
循环工程的核心是——你不再是那个亲自向 Agent 输入指令的人,你设计一个系统来代替你做这件事。
这里说的"循环"可以理解为一个递归目标——你定义一个目标,AI 不断迭代直到完成。我相信这可能是我们未来与编程智能体协作的方式。但现在还很早期,我持怀疑态度,你绝对要小心 Token 成本(Token 充裕还是拮据,使用模式会天差地别),所以我想拆解一下这到底是什么,意味着什么。
Peter Steinberger 最近说:"你不应该再向编程智能体输入指令了。你应该设计让智能体自动运行指令的循环。"同样,Anthropic 旗下 Claude Code 的负责人 Boris Cherny 说:"我已经不再向 Claude 输入指令了。我有循环在运行——它们向 Claude 输入指令并决定该做什么。我的工作是写循环。"
好的,这到底是什么意思?
过去两年,你从编程智能体获取结果的方式是——写一个好 Prompt,提供足够的上下文。你输入一个东西,阅读返回结果,再输入下一个东西。智能体是一个工具,你全程握住它,一轮接着一轮。这部分可以说已经结束了,至少有些人这么认为。
现在你构建一个小系统——它自己发现问题、分配工作、检查结果、记录完成情况,然后决定下一步做什么。你让这个系统去驱动智能体,而不是你自己。我之前写过一个相关概念——Agent Harness Engineering(智能体挂载工程),它是单个智能体运行的执行环境。还有 Factory Model——构建软件的系统。循环工程比挂载工程高一层——它按时运行,它产出子助手,它自我供养。
让我惊讶的是,这已经不是纯粹的工具问题了。一年前,想搞一个循环你得写一堆 Bash 脚本并永远维护它,它是你一个人的。现在这些能力直接内建在产品里。Steinberger 列出的能力清单几乎一一对应 Codex,也几乎一一对应 Claude Code。一旦你发现底层的结构是一样的,你就不会再争论用哪个工具——你只需要设计一个循环,不管坐在哪个工具里它都能跑。
五个组件,外加一个记忆
循环需要五样东西,再加一个记东西的地方。我先列出来,再展开对照。
Automations(自动化)——按计划触发,自己去做发现和分类。
Worktrees(工作树)——两个智能体并行工作不会互相踩踏。
Skills(技能)——把项目知识写下来,智能体就不用瞎猜了。
Plugins & Connectors(插件与连接器)——把智能体接入你已经在用的工具。
Sub-agents(子智能体)——一个想点子,另一个检查它。
然后是第六样东西,记忆。一个 Markdown 文件、一个 Linear 看板——任何存在于单次对话之外的、记录了什么已完成、什么待做的东西。听起来太简单了不值得关注,但这是每一个长期运行智能体依赖的同一个技巧,我在 Long-Running Agents 中详细讲过——模型在每次运行之间会忘掉一切,所以记忆必须在磁盘上,不能只在上下文中。智能体会忘,代码仓库不会。
两个产品现在都具备了这五样东西。
Codex vs Claude Code 对照表
| 组件 | 循环中的角色 | Codex | Claude Code |
|---|---|---|---|
| Automations | 计划触发 + 发现 + 分类 | Automations 标签页:选项目、Prompt、频率、环境;结果进入 Triage 收件箱;/goal 用于直到完成为止 | 定时任务和 cron、/loop、/goal、hooks、GitHub Actions |
| Worktrees | 隔离并行特性 | 内建 worktree per thread | git worktree、--worktree 标识、子智能体 isolation: worktree |
| Skills | 固化项目知识 | Agent Skills(SKILL.md),通过 $name 或隐式调用 | Agent Skills(SKILL.md) |
名称有点区别,但能力是一回事。让我一个一个展开,因为细节才是循环能站住还是悄悄崩盘的地方。
Automations:循环的心跳
Automations 让循环成为一个真正的循环,而不是你手动跑过一次就完事的东西。在 Codex 中,你在 Automations 标签页里创建一个——选项目、选 Prompt、设置频率、选择在本地 checkout 还是后台 worktree 上运行。有发现的运行结果进入 Triage 收件箱,没发现的自动归档——这个设计不错。OpenAI 内部用它们做无聊但重要的事:每天的问题分类、CI 失败的摘要、写提交简报、追踪上周引入的 Bug。一个 Automation 可以调用一个 Skill——你只需触发 $skill-name,而不是把一堵墙那么大的指令贴进调度里让以后没人会去更新。
Claude Code 通过调度和 hooks 达到同样的效果。你可以用 /loop 按间隔执行 Prompt 或命令,可以调度 cron 任务,可以在智能体生命周期的特定节点通过 hooks 触发 shell 命令,或者推到 GitHub Actions 让它在你合上笔记本后继续运行。思路一模一样——你定义一个自主任务,给它一个频率,发现的结果来找到你,而不是你到处去检查。
还有一个值得了解的第二类会话内原语,它更接近这篇文章的核心主题。/loop 按频率重新运行。/goal 持续运行直到你写下的条件确实满足——每一轮之后会有一个独立的小模型检查你是否完成了,所以写代码的智能体不是给它打分的智能体。你输入类似"test/auth 下所有测试通过且 lint 干净"这样的条件然后走开。Codex 也有同样的功能,也叫 /goal,它会跨多个轮次持续工作直到可验证的停止条件满足,支持暂停、恢复和清除。同样的原语,两个工具都有——这差不多是整篇文章的模式。
所以这是发现工作的部分。循环的其余部分是对工作采取行动。
Worktrees:并行不乱套
一旦你让超过一个智能体同时运行,文件冲突就会成为故障。两个智能体写同一个文件,和两个工程师不商量就提交同一行代码完全是一个坑。Git Worktree 解决这个问题——它是同一个仓库的不同分支上的独立工作目录,共享同一个仓库历史,所以一个智能体的编辑根本碰不到另一个的 checkout。
Codex 将 Worktree 支持直接内建,多个线程同时操作同一个仓库互不干扰。Claude Code 通过 git worktree、--worktree 标识(让一个会话在独立 checkout 中打开)和子智能体上的 isolation: worktree 设置(每个助手拿到一个全新的 checkout,完成后自己清理)实现同样的隔离。我在 Orchestration Tax 中写过关于人的那一面——Worktrees 消除了机械冲突,但你仍然是天花板,你的 review 带宽决定了你能真正跑多少个,不是工具。
Skills:不再每次重新解释你的项目
Skill 是让你不再像金鱼一样每个会话都重新解释一遍项目上下文的方法。两个工具用同一种格式——一个文件夹里放着 SKILL.md(内含指令和元数据),外加可选的脚本、参考文件和资源。Codex 在你用 /skills 显式调用时运行一个 Skill,或者当你的任务与 Skill 描述匹配时自动触发——这就是为什么一个简洁但精确的描述比一个"聪明"的描述更好。Claude Code 同样的方式,我在 Agent Skills 中写过这个模式。
Skills 也是让意图不再反复消耗你的地方。我在 Intent Debt 中论述过:智能体每次启动都是冷的,它会用自信的猜测填满你意图中的任何空洞。Skill 就是被写到外面的那份意图——约定、构建步骤、"我们不这样做的原因是因为那次事件"——写一次,智能体每次运行都读得到。没有 Skills,循环每个周期都从零推导你的整个项目;有了 Skills,它在某种程度上是积累的。
有一件事要分清楚:Skill 是编写格式,Plugin 是你如何发布和分发的。当你想跨仓库共享一个 Skill 或把几个打包在一起时,你把它打包成 Plugin。Codex 是这样,Claude Code 也是这样。
Plugins & Connectors:循环接触你的真实工具
一个只能看到文件系统的循环是个小循环。Connectors(基于 MCP 构建)让智能体能读你的 Issue 跟踪器、查数据库、调用预发布 API、在 Slack 里丢消息。Codex 和 Claude Code 都说 MCP,所以你在一个工具上写的 Connector 在另一个上通常也能用。Plugin 把 Connectors 和 Skills 打包在一起,让你的同事一键安装你的整套配置,而不是靠记忆重建整件事。
这就是"这个修复应该这样改"和"循环自己开了 PR、关联了 Linear 票、CI 绿了之后自己 ping 了频道"之间的区别。Connectors 是循环能在你的真实环境里行动、而不是告诉你它如果能做的话会做什么的原因。
Sub-agents:让制造者和检查者分开
循环里最有用的结构性设计,毫无疑问,是把写的和查的分开。那个写了代码的模型给自己作业打分时太温柔了。第二个智能体——不同的指令,有时甚至不同的模型——能抓住第一个智能体说服自己没问题的那些东西。
Codex 只在你要求时才启动子智能体,同时运行,然后把结果折叠回一个回答。你在 .codex/agents/ 中用 TOML 文件定义自己的 Agent,每个有名称、描述、指令,可选的模型和推理强度——所以你的安全审查器可以是高强度推理的大模型,而你的探索器可以是个快速的只读工具。Claude Code 用 .claude/agents/ 中的子智能体和 Agent Teams 传递工作做同样的事。两者中最常用的分工是:一个 Agent 探索、一个实施、一个对照规格验证。
我写过两次这个观点:一次作为 Code Agent Orchestra,一次作为 Adversarial Code Review。它在循环中之所以特别重要,是因为循环在你不看的时候运行,所以一个你真正信任的验证者是你能走开的唯一原因。子智能体确实消耗更多 Token(每个都做自己的模型和工具工作),所以把钱花在值得第二次意见的地方。这也是 Claude Code 的 /goal 在底层做的事——一个全新的模型决定循环是否完成,而不是做工作的那个模型——制造者和检查者分离应用到了停止条件本身。
一个完整循环长什么样
把这些拼在一起,单一线程就变成一个小型控制面板。这是我反复使用的一种结构:
一个 Automation 每天早上在仓库上运行。它的 Prompt 调用一个 Triage Skill——读取昨天的 CI 失败、开放的 Issue、最近的提交——把发现写进一个 Markdown 文件或 Linear 看板。对于每一个值得处理的发现,线程打开一个隔离的 Worktree,派出一个子智能体起草修复方案,再派出第二个子智能体对照项目 Skills 和现有测试审查那个方案。
Connectors 让循环能自己打开 PR 并更新票。循环处理不了的任何东西落进我的 Triage 收件箱。State 文件是整个事物的脊梁——它记住什么被尝试过、什么通过了、什么仍然开放——所以明天早上的运行从今天停下的地方继续。
看看你实际做了什么。你设计了一次。你没有向任何一个步骤输入指令。这就是 Steinberger 的观点在现实中实现了——而且无论是在 Codex 还是 Claude Code 中,都是同一个循环,因为组件是一样的。
循环不会为你做的事情
循环改变了工作方式,它没有把你从工作中删除。而且有三个问题,随着循环越来越好,反而变得更尖锐,而不是更容易。
验证还是得你来。 一个无人值守的循环也是一个无人值守犯错的循环。你把验证子智能体从制造者拆出来的全部原因,就是为了让循环说的"完成了"有点意义——即便如此,"完成"只是一个声明,不是证据。我一直重复 Code Review in the Age of AI 中的同一句话:你的工作是交付你确认能用的代码。
你的理解仍然会腐烂——如果你允许的话。 循环越快地交付你没写过的代码,存在的东西和你真正理解的东西之间的鸿沟就越大。这就是理解债务。一个顺畅的循环只会让它增长更快——除非你阅读循环产生的内容。
最舒服的姿势也是最危险的姿势。 当循环自动运行时,你很容易放弃自己的判断,接受它给出来的一切。我把这称为认知投降。当你带着判断力设计循环,设计本身就是解药;当你为了逃避思考而设计循环,同样的行动产生完全相反的结果。
构建循环。保持工程师的本色。
我认为这是我们的工作将如何演变的预览。不过,如果我自己不审查代码,或者完全依赖自动化循环来修复问题,我的产品质量一定会下降。我最终可能会陷入一个恶性循环,不断把自己挖进更深的坑。
动手设置好你的循环,但不要忘记直接向你的智能体输入指令也同样有效。关键是在二者之间找到合适的平衡。
同样的循环在不同的人手里会产生截然不同的结果。一个人用它来更快地推进自己深度理解的工作,另一个人用它来完全避免理解工作本身。循环不知道这二者的区别。你知道。
这就是为什么循环设计比 Prompt 工程更难,而不是更容易。Cherny 的观点不是工作变简单了,而是杠杆支点发生了转移。
构建循环。但要以一个打算继续保持工程师身份的人的方式去构建它——而不仅仅是那个按启动按钮的人。