Addy Osmani (@addyosmani)
2026-06-09
D
原文
---
title: "循环工程(Loop engineering)"
author: "Addy Osmani (@addyosmani)"
source_url: "https://x.com/addyosmani/status/2064127981161959567"
published_at: "2026-06-08T23:30:34.000Z"
fetched_at: "2026-06-11T04:29:33Z"
updated_at: "2026-06-11T04:38:41Z"
language: "zh"
review_status: "draft"
---

# 循环工程(Loop engineering)
**循环工程(Loop engineering)就是把你从「给 agent 写 prompt 的那个人」这个角色上换下来。改由你来设计那套替你做这件事的系统。** **这里说的 loop,可以理解成一个递归目标——你定义一个目的,AI 就一直迭代直到完成。** 它大致由五块积木组成,而 Claude Code 和 Codex 如今都凑齐了这五块。
我相信这*或许*就是我们和 coding agent 协作方式的未来。不过现在还很早,我自己也持怀疑态度,而且你绝对*必须*当心 **token 成本**(取决于你 token 充裕还是紧张,用量模式会差得离谱)。你也仍然需要*某种*办法保证质量不掉,关于 slop(粗制滥造的产出)的担心是站得住脚的。话虽如此,咱们还是来看看这到底是怎么回事。
@steipete 最近[说](https://x.com/steipete/status/2063697162748260627):「你不该再给 coding agent 写 prompt 了。你应该去设计那些给你的 agent 写 prompt 的 loop。」类似地,Anthropic 的 Claude Code 负责人 @bcherny 也[说](https://x.com/rohanpaul_ai/status/2063289804708835412):「我不再给 Claude 写 prompt 了。我让一堆 loop 跑着,由它们给 Claude 写 prompt、琢磨该做什么。我的工作是写 loop。」
好,那这些话到底是什么意思?
差不多有两年时间,你想从一个 coding agent 那儿拿到点东西,靠的是写一个好 prompt、给够上下文。你敲一段,读它返回什么,再敲下一段。agent 是个工具,而你自始至终都攥着它,一轮接一轮。这种玩法基本上要过去了,至少有些人觉得它会过去。
现在你搭一个小系统:它找出要做的活、把活分派出去、检查结果、记下做完了什么,然后决定下一件事——你让这个系统去催那些 agent 干活,而不是你自己去催。我之前写过跟它很相近的一个东西,[agent harness 工程](https://addyosmani.com/blog/agent-harness-engineering/),也就是把单个 agent 跑在里头的那个环境造出来,还有[工厂模型](https://addyosmani.com/blog/factory-model/)——那套造软件的系统。loop 工程比 harness 高一层。它就是 harness,只不过跑在定时器上,会生出小帮手,还会自己喂自己。
让我意外的是,这已经不再真是一个工具层面的事了。一年前你想要一个 loop,得写一大堆 bash,然后永远维护那堆东西,它是你的、也只属于你一个人。现在这些零件直接内建进产品里了。Steinberger 列的那张清单,几乎一对一地落在 Codex app 上,然后又几乎原样落在 Claude Code 上。一旦你注意到形状是一样的,你就不再纠结用哪个工具了,你只管设计一个 loop,让它不管你眼下用的是哪一个都照样能跑。
### **这五块零件,然后是一些备注**
一个 [loop](https://x.com/reach_vb/status/2063713960495558940) 需要五样东西,再加一个记东西的地方。我先把它列出来,再逐一对应。
1. **Automations**,按计划自动触发,自己去做发现和 triage。
2. **Worktrees**,让两个并行干活的 agent 不会互相踩脚。
3. **Skills**,把项目知识写下来,否则 agent 只能瞎猜。
4. **Plugins 和 connectors**,把 agent 接进你本就在用的工具里。
5. **Sub-agents**,让其中一个出主意、另一个来检查它。
然后是第六样,记忆。一个 markdown 文件,或者一块 Linear board,任何活在单次对话之外、记着做完了什么和接下来做什么的东西。听起来蠢得不值一提。但这正是每个长时间运行的 agent 都依赖的同一个把戏,我在[长时间运行的 agent](https://addyosmani.com/blog/long-running-agents/) 里展开讲过——模型在两次运行之间会忘掉一切,所以记忆必须落在磁盘上,而不是待在上下文里。agent 会忘,仓库不会。
两个产品现在都凑齐了这五样。

这儿那儿的叫法稍有不同,但能力是同一回事。让我一个一个过,因为说实话,细节才是一个 loop 到底是稳稳兜住、还是悄悄到处漏水的分水岭。
### **Automations,这是心跳**
Automations 才是让一个 loop 成为真正的 loop、而不只是一次性运行的东西。在 Codex app 里,你在 Automations 标签页里建一个,挑好项目、它要跑的 prompt、多久跑一次,以及它跑在你的本地 checkout 上还是某个后台 worktree 上。找到东西的那些运行会进一个 Triage 收件箱,啥也没找到的运行就自己归档了,这点挺好。OpenAI 内部就拿它们干些枯燥的活,比如每天的 issue triage、汇总 CI 失败、写 commit 简报、揪出上周某人埋下的 bug。而一个 automation 可以调用一个 skill,这样你就能让这个反复跑的东西保持可维护——你触发 `$skill-name`,而不是把一大堵墙的指令糊进一个永远不会有人去更新的计划里。
Claude Code 殊途同归,靠的是调度和 hooks。你可以用 `/loop` 按间隔跑一个 prompt 或命令,可以排一个 cron 任务,可以用 hooks 在 agent 生命周期的某些节点触发 shell 命令,或者你想让它在你合上笔记本之后还接着跑,就把整套东西推到 GitHub Actions 上。一模一样的思路:你定义一个自主任务,给它一个节奏,发现的东西自己送上门来,于是不必你绕来绕去地去查。
还有一个值得知道的会话内原语,它跟整篇文章要讲的东西更贴近。`/loop` 按节奏重跑。`/goal` 则一直跑下去,直到你写的某个条件真的为真为止,而且每一轮之后会有一个单独的小模型来检查你是不是完成了——这样写代码的那个 agent 就不是给它打分的那个。你给它类似「test/auth 下所有测试通过、lint 干净」这样的东西,然后走开就行。Codex 有同样的东西,也叫 `/goal`,它跨多轮一直干,直到某个可验证的停止条件成立,带 pause、resume 和 clear。同一个原语,两个工具都有,这差不多就是整篇文章的套路。
所以这部分是把活浮出水面的那一环。loop 的其余部分,是对这些活下手的那一环。
### **Worktrees,别让并行变成一团乱**
你一旦跑起不止一个 agent,文件就开始打架,这就成了失败点。两个 agent 写同一个文件,跟两个工程师事先谁也没打招呼就往同样的行里提交,是一模一样的头疼事。一个 git worktree 能解决它,它是一个独立的工作目录,待在自己的分支上、共享同一份仓库历史,于是一个 agent 的改动根本碰不到另一个的 checkout。
Codex 把 worktree 支持直接内建进去,于是好几个线程同时怼同一个仓库也不会互相撞上。Claude Code 用 git worktree 给你同样的隔离:一个 `--worktree` 标志在自己的 checkout 里开一个会话,还有一个 `isolation: worktree` 设置,你把它贴在某个 subagent 上,每个小帮手就拿到一份用完会自我清理的全新 checkout。我在[编排税](https://addyosmani.com/blog/orchestration-tax/)里写过这一切里属于人的那一面——worktree 拿掉了机械层面的碰撞,但**你**仍然是天花板,你的 review 带宽决定了你实际能跑几个,不是工具决定的。
### **Skills,让你不必每一次都从头解释你的项目**
skill 是你不必像条金鱼一样、每次会话都把同样的项目上下文重新解释一遍的办法。两个工具用同样的格式:一个文件夹,里头一个 SKILL.md,装着指令和 metadata,然后是可选的 scripts、references、assets。Codex 在你用 `$` 或 `/skills` 调用它时跑一个 skill,或者当你的任务跟 skill 的描述匹配上时它自己跑——这正是为什么一句又精准又无聊的描述胜过一句机灵的描述。Claude Code 做法相同,我在 [agent skills](https://addyosmani.com/blog/agent-skills/) 里把这套模式写过。
skill 也是让「意图」不再一遍遍向你收费的地方。我在[意图债](https://addyosmani.com/blog/intent-debt/)里论证过,一个 agent 每次会话都从冷启动开始,它会用一个自信的猜测填上你意图里的任何窟窿。一个 skill 就是把那份意图写在外面:那些约定、那些构建步骤、那句「我们不这么干,是因为出过那一次事故」,写一次,放在 agent 每次运行都会读到的地方。没有 skill,loop 每个周期都把你整个项目从零重新推导一遍;有了 skill,它就有点像在复利滚雪球。
有一点要拎清楚:skill 是写作格式,而 plugin 是你分发它的方式。当你想跨多个仓库共享一个 skill、或者把几个打包到一起时,你就把它们封装成一个 plugin。在 Codex 里成立,在 Claude Code 里也成立。
### **Plugins 和 connectors,让 loop 碰到你真正的工具**
一个只能看见文件系统的 loop 是个很小的 loop。Connectors(建在 MCP 之上)让 agent 读你的 issue tracker、查一个数据库、打一个 staging api、往 Slack 里丢一条消息。Codex 和 Claude Code 都讲 MCP,所以你为其中一个写的 connector,在另一个里通常直接就能用。而 plugins 把 connectors 和 skills 捆到一起,于是你的队友一步就装上你的整套配置,而不是凭记忆把整个东西重搭一遍。
这就是「这是修复方案」的 agent,和「自己开了 PR、关联了 Linear ticket、CI 一绿就 ping 一下频道」的 loop 之间的差别。connectors 正是 loop 能在你真实环境里动手的原因,而不只是告诉你「如果它能、它会怎么做」。
### **Sub-agents,让动手的那个离检查的那个远点**
一个 loop 里最有用的结构性手段,没有之一,就是把写的那个和检查的那个分开。写代码的那个模型,给自己的作业打分时实在太宽厚了。一个带着不同指令、有时还是不同模型的第二个 agent,能逮住第一个把自己说服了的那些东西。
Codex 只在你要求时才生出 subagent,让它们同时跑,然后把结果折回成一个答案。你把自己的 agent 定义成 `.codex/agents/` 里的 TOML 文件,每个带一个名字、一段描述、一份指令,以及可选的 model 和 reasoning effort,于是你的安全审查员可以是个高强度跑的强模型,而你的探索者是个快速、只读的小东西。Claude Code 也一样,用 `.claude/agents/` 里的 subagents,还有在彼此之间传递工作的 agent team。两个工具里通常的分工都是:一个 agent 探索,一个实现,一个对着 spec 验证。
这个观点我已经讲过两次,一次叫[代码 agent 交响乐团](https://addyosmani.com/blog/code-agent-orchestra/),一次叫[对抗式代码评审](https://addyosmani.com/blog/adversarial-code-review/)。它之所以在一个 loop 里尤其要紧,是因为 loop 在你没盯着的时候跑,所以一个你真正信得过的验证者,是你能走开的唯一理由。subagents 确实更烧 token,因为每个都得做自己的模型和工具活,所以把它们花在「第二意见值得为之买单」的地方。这其实也基本上就是 Claude Code 的 `/goal` 在底下干的事——一个全新的模型来判定 loop 是不是完成了,而不是那个干完活的模型,把「动手者和检查者分开」用到了停止条件本身上。
### **一个 loop 长什么样**
把它们拼到一起,一个单独的线程就变成了一个小小的控制面板。这是我一直在用的一种形状。
一个 automation 每天早上在仓库上跑。它的 prompt 调用一个 triage skill,去读昨天的 CI 失败、还开着的 issue、最近的 commit,把发现写进一个 markdown 文件或一块 Linear board。对于每一个值得做的发现,这个线程开一个隔离的 worktree,派一个 sub-agent 去起草修复,再派第二个 sub-agent 对着项目 skills 和现有测试评审那份草稿。
connectors 让 loop 开 PR、更新 ticket。loop 搞不定的任何东西,都落进给我的 triage 收件箱。状态文件是整个东西的主心骨,它记着试过什么、过了什么、还有什么开着,于是明早的运行从今天停下的地方接着来。
然后看看你实际上干了什么。你设计了它一次。那些步骤你一个都没去 prompt。这就是 Steinberger 的整个观点变成了现实,而且在 Codex 里和在 Claude Code 里是同一个 loop,因为零件是同样的零件。
### **loop 仍然没替你做的事**
**loop 改变了工作,它没有把你从工作里删掉。** 而且有三个问题,是随着 loop 变好而变得更尖锐、不是更轻松。
**验证仍然在你身上。** 一个无人值守跑着的 loop,也是一个无人值守地在犯错的 loop。你把验证者 sub-agent 从动手者那儿分开,整个理由就是让 loop 那句「做完了」有点分量,可即便如此,「完成」是一个声明,不是一个证明。我一直在重复[AI 时代的代码评审](https://addyosmani.com/blog/code-review-ai/)里的那句话:你的工作是交付你确认过能跑的代码。
**你的理解仍然会烂掉,如果你由着它。** loop 越快地交付你没写的代码,「存在的东西」和「你真正搞懂的东西」之间的鸿沟就越大。这就是[理解债](https://addyosmani.com/blog/comprehension-debt/),一个顺滑的 loop 只会让它涨得更快,除非你去读 loop 造出来的东西。
而且是的,那个舒舒服服的姿态,多半就是有风险的那个。当 loop 自己跑起来,人会特别想干脆别再有自己的看法,它丢回来什么就照单全收。我把那个叫[认知投降](https://addyosmani.com/blog/cognitive-surrender/)。设计这个 loop,在你带着判断力去做时是解药,在你为了逃避思考而去做时是助燃剂——同一个动作,相反的结果。
### **搭好这个 loop。继续当那个工程师。**
我觉得这是我们工作会如何演变的一段预告。话虽如此,如果我不亲自评审代码,或者我完全依赖自动化的 loop 去修它,我的产品质量会受损。我多半会落进一个向下的螺旋,不停地把自己往一个更深的坑里挖。
话虽如此,尽管去搭你的 loop,但别忘了直接给你的 agent 写 prompt 仍然有效。关键全在于找到那个对的平衡。
loop 还会因人而异、给出不同的结果。两个人搭出一模一样的 loop,可以得到完全相反的结果。一个人用它在自己深刻理解的工作上跑得更快。另一个人用它来彻底逃避去理解那份工作。loop 分不出这个差别。你分得出。
这正是为什么 loop 设计比 prompt 工程更难,而不是更容易。Cherny 的观点不是说工作变容易了。而是说,那个杠杆点挪了位置。
**搭好这个 loop。但要像一个打算继续当工程师的人那样去搭它,而不是只当那个按下启动键的人。**