Addy Osmani 是 Google Cloud AI 总监,此前在 Chrome 团队工作近 14 年,主导了 DevTools、Lighthouse、Core Web Vitals 等开发者工具。2024 年底转向 AI 方向,现负责 Gemini、Vertex AI 和 Agent Development Kit 的开发者生态。GitHub 近 5 万关注者,X 粉丝近 40 万,著有《Learning JavaScript Design Patterns》《Beyond Vibe Coding》等多部畅销书。近期活跃于 AI 编码方法论领域,提出循环工程、代理外壳工程、意图债务等概念,核心观点是 AI 放大工程师杠杆而非取代工程师。 循环工程(Loop Engineering)正成为与编码代理协作的新范式。核心思路是构建一个由自动化、工作树、技能、插件和子代理五个模块组成的自运行系统,让它按节奏自动发现任务、分配工作、检查结果并决定下一步,取代人类逐轮手动提示。Claude Code 和 Codex 目前均已内置这五项能力,且结构高度趋同。但作者同时警告:循环会加速「理解债务」积累,验证责任仍在人身上,用循环逃避思考比不用循环更危险。 以下为文章原文
循环工程(Loop Engineering)正在取代你自己作为提示代理的人。你不再亲自去提示代理,而是设计一个系统来替你完成这件事。这里的“循环”可以理解为一个递归目标:你定义一个目的,AI 不断迭代,直到任务完成为止。它大致由五个构建块组成,现在 Claude Code 和 Codex 都已具备这五个能力。 我相信这可能是我们与编码代理协作的未来方式。不过目前还很早期,我持怀疑态度,你必须非常小心token 成本(使用模式如果 token 丰富或贫乏,差异会极大)。同时,你仍然需要某种方式来确保质量不会下降,“slop”(低质量输出)的问题也是真实存在的。尽管如此,让我们来探索一下这到底是怎么回事。
@steipete 最近说:“你不应该再亲自提示编码代理了。你应该设计循环,让循环去提示你的代理。”
同样,Anthropic Claude Code 的负责人 @bcherny 也说:“我不再亲自提示 Claude 了。我有循环在运行,它们会提示 Claude 并决定下一步该做什么。我的工作是编写循环。”
那么,这到底是什么意思呢?
过去两年,你从编码代理那里获得输出的方式就是:写一个好的提示,提供足够的上下文。你输入一段内容,读完返回结果,再输入下一段。代理只是工具,你全程握着它,一轮接一轮地操作。这一部分已经过时了,或者至少有些人认为它即将过时。
现在,你构建一个小型系统,它会自动寻找工作、分配任务、检查结果、记录完成情况,然后决定下一步。你让这个系统去“戳”代理,而不是你自己亲自去做。我之前写过它的近亲——代理外壳工程(agent harness engineering),即为单个代理构建运行环境,以及工厂模式(factory model)——构建软件的系统。而循环工程比外壳再高一层:它像一个带定时器的外壳,会生成小助手,并自我喂养。
让我惊讶的是,这已经不再是单纯的“工具”层面了。一年前,如果你想做一个循环,你得写一大堆 bash 脚本,然后永远维护它,它只属于你一个人。现在,这些能力直接内置在产品里了。Steinberger 的清单几乎完全对应 Codex 应用,也几乎完全对应 Claude Code。一旦你发现形状是一样的,你就不再争论用哪个工具,而是直接设计一个循环——无论你在哪个工具里,它都能正常工作。
五个构建块 + 一个记忆位置
循环需要五个东西,外加一个记录状态的地方。我先列出来,然后逐一对应说明。
- 自动化(Automations):按计划自动触发,发现并分流任务。
- 工作树(Worktrees):让多个代理并行工作时不会互相踩踏。
- 技能(Skills):把项目知识写下来,避免代理每次都靠猜。
- 插件与连接器(Plugins and connectors):让代理接入你已有的工具。
- 子代理(Sub-agents):一个负责生成想法,另一个负责检查。
然后是第六个东西——记忆(Memory):一个 Markdown 文件、Linear 看板,或者任何存在于单次对话之外的东西,用来记录已完成的事和下一步要做什么。这听起来太简单以至于无关紧要,但它是所有长期运行代理的共同技巧。我在《长期运行代理》一文中详细讲过:模型在每次运行之间会忘记一切,所以记忆必须写在磁盘上,而不是放在上下文里。代理会忘,仓库不会。
两个产品现在都具备了这五个能力。
名称可能略有不同,但能力本质相同。下面我逐一拆解,因为细节决定了循环是稳固还是到处漏水。
1. 自动化——这是心跳
自动化让循环真正成为“循环”,而非你只跑一次的东西。在 Codex 应用里,你在“Automations”标签页创建一个自动化,选择项目、要运行的提示、运行频率,以及是在本地检出还是后台工作树上运行。发现问题的运行会进入 Triage(分流)收件箱,什么都没发现的就自动归档——这很贴心。OpenAI 内部就用它做日常琐事:每天分流 issue、总结 CI 失败、写提交简报、查找上周引入的 bug。自动化还可以调用技能,这样你就不用把一大段指令复制进计划里(没人会去更新它)。
Claude Code 通过调度和钩子实现同样功能。你可以用 /loop 按间隔运行提示或命令,可以设置 cron 任务,可以在代理生命周期的特定节点触发 shell 命令,也可以推到 GitHub Actions,让它在你关掉电脑后继续运行。理念完全一样:定义一个自治任务,给它一个节奏,结果会主动找你,而不是你四处去检查。
还有一个值得了解的会话内原语,它更接近这篇帖子的核心:/loop 是按节奏重跑,而 /goal 会一直运行,直到你写的条件真正成立。每次迭代后,会由一个独立的小模型检查是否完成——写代码的代理不负责给自己打分。你可以给它类似“test/auth 里的所有测试通过且 lint 干净”的条件,然后走开。Codex 也有同样的 /goal,支持暂停、恢复和清除。两个工具都一样,这正是整篇文章的模式。
自动化负责“把工作浮出水面”,循环的其他部分则负责处理它。
2. 工作树——并行不会变成混乱
只要你同时跑多个代理,文件就会冲突,这就是失败的开始。两个代理写同一个文件,和两个工程师往同一行代码提交却没提前沟通是一样的灾难。Git worktree 能解决这个问题:它是一个独立的目录,拥有自己的分支,但共享仓库历史,所以一个代理的修改不可能碰另一个代理的检出。
Codex 内置了 worktree 支持,多个线程可以同时操作同一个仓库而不碰撞。Claude Code 也通过 git worktree 提供相同隔离——用 --worktree 标志打开独立会话,或者在子代理上设置 isolation: worktree,每个助手都会获得一个干净的检出,用完自动清理。我在《编排税》一文中讲过人的那一面:worktree 解决了机械碰撞,但你仍然是天花板——你的审查带宽决定了你能同时跑多少个,而不是工具。
3. 技能——不再每次都重新解释你的项目
技能就是让你不再像金鱼一样每次会话都重新解释项目上下文的东西。两个工具都使用相同的格式:一个文件夹,里面有一个 SKILL.md,存放指令和元数据,还可以有可选的脚本、引用、资源。Codex 用 $ 或 /skills 调用技能,或者当任务匹配技能描述时自动调用(所以精确无聊的描述比花哨的更好)。Claude Code 也完全一样,我之前在《代理技能》一文中写过这个模式。
技能也是让“意图”不再反复付出代价的地方。我在《意图债务》一文中说过,代理每次会话都是冷启动,会用自信的猜测填补任何意图空白。技能就是把意图写在外面:约定、构建步骤、“我们不这么做是因为那次事故”……一次性写好,代理每次运行都会读到。没有技能,循环每次循环都要从零重新推导整个项目;有了技能,它就能复利增长。
注意区分:技能是编写格式,插件是打包分发方式。当你想跨仓库共享技能或打包多个技能时,就打包成插件。Codex 和 Claude Code 都是这样。
4. 插件与连接器——让循环触及你的真实工具
只能看到文件系统的循环是一个很小的循环。连接器(基于 MCP)能让代理读取你的 issue 追踪器、查询数据库、调用 staging API、在 Slack 发消息。Codex 和 Claude Code 都支持 MCP,所以你为一个工具写的连接器通常在另一个里也能直接用。插件则把连接器和技能打包在一起,队友一键安装你的整套配置,而不用从头重建。
这就是“代理说‘这是修复’”和“循环自己打开 PR、关联 Linear ticket、CI 绿了就 ping 频道”的区别。连接器让循环能在你的真实环境中行动,而不只是告诉你“如果能做的话它会做什么”。
5. 子代理——把“制造者”和“检查者”分开
循环里最有用的结构设计,就是把写代码的人和检查代码的人分开。写代码的模型给自己作业打分时太善良了。第二个代理用不同的指令(有时用不同模型),就能抓住第一个代理自己说服自己的那些问题。
Codex 只在你要求时生成子代理,同时运行,然后把结果合并。你在 .codex/agents/ 里用 TOML 文件定义代理,每个有名称、描述、指令、可选模型和推理强度——比如你的安全审查员可以用强模型+高强度,而探索者可以用快速只读模型。Claude Code 在 .claude/agents/ 里也一样,支持代理团队互相传递工作。通常的拆分是:一个探索、一个实现、一个对照规范验证。 我已经在《代码代理乐团》和《对抗式代码审查》两篇文章里两次讲过这个。循环里尤其重要,因为循环是在你不看的时候运行的,一个可信的验证者是你能放心走开的唯一理由。子代理会消耗更多 token(每个都要自己的模型和工具调用),所以只在第二意见值得付费的地方花钱。这也正是 Claude Code 的 /goal 在底层做的:用一个新鲜模型决定循环是否结束,而不是让写代码的那个模型自己判断——制造者/检查者拆分直接应用到了停止条件上。
一个典型的循环长什么样
把它们组合起来,一个线程就变成了一个小控制台。下面是我经常用的一个形状:
每天早上自动化在仓库上运行。它的提示调用一个分流技能,读取昨天的 CI 失败、开放 issue、最近提交,把发现写进 Markdown 文件或 Linear 看板。对于每个值得处理的问题,线程会打开一个隔离的工作树,派一个子代理起草修复,再派第二个子代理对照项目技能和现有测试进行审查。
连接器让循环自己打开 PR、更新 ticket。循环处理不了的就落在分流收件箱里等我。状态文件是整个循环的脊梁,它记住什么尝试过、什么通过了、什么还开放,所以明天早上会从今天停下的地方继续。
你真正做的事是什么?你只设计了一次。你没有亲自提示任何一步。这就是 Steinberger 那句话的真实体现。而且无论你在 Codex 还是 Claude Code 里,这个循环都是一样的,因为构建块完全相同。
循环仍然不能为你做的事
循环改变了工作,但并没有把你从工作中删除。随着循环越来越好,有三个问题反而会变得更尖锐,而不是更容易。
- 验证仍然在你身上。无人值守运行的循环,也会无人值守地犯错。你拆分验证子代理的全部理由,就是让循环的“完成了”有意义。但即使如此,“完成了”也只是声明,不是证明。我一直重复那句 AI 时代代码审查的名言:你的工作是交付你亲自确认能正常工作的代码。
- 你的理解仍然会腐烂,如果你允许的话。循环越快地交付你没写的代码,你和实际代码之间的差距就越大。这就是理解债务,一个顺畅的循环只会让它增长得更快,除非你去读循环产出的东西。
- 舒服的姿势往往是最危险的。当循环自己运行时,你很容易停止发表意见,只接受它给你的任何东西。我把这叫做认知投降。带着判断力设计循环是解药;为了逃避思考而设计循环则是催化剂。同一件事,结果相反。
建立循环。保持工程师身份。
我认为这是我们工作方式即将演变的预览。但如果我不亲自审查代码,或者完全依赖自动化循环来修复,我的产品的质量就会下滑。我很可能会陷入向下螺旋,不断把自己挖进更深的坑里。
话虽如此,去建立你的循环吧,但别忘了直接提示代理仍然有效。关键在于找到合适平衡。
循环的结果也完全取决于你。两个人用完全相同的循环,可能得到完全相反的结果。一个人用它在自己深刻理解的工作上加速;另一个人用它来完全避免理解工作。循环不知道区别,你知道。
这正是为什么循环设计比提示工程更难,而不是更容易。Cherny 的观点不是工作变容易了,而是杠杆点转移了。
建立循环。但要像一个打算继续做工程师的人那样去建立它,而不是只想按下“开始”按钮的人。