最近很火的 Loop Engineering 到底是什么
- Loop Engineering 由 Addy Osmani、Boris Cherny、Peter Steinberger 在 2026 年 6 月同一周各自独立撞上并命名:不再手动提示 AI,而是设计一套自动提示 AI 的系统,自己从「操作 AI」变成「设计驱动 AI 的系统」
- 一个循环由五步构成:发现任务、交接执行、独立验证、持久化状态、自动调度,五步缺任何一步都有对应的具名失败模式(点头循环/失忆循环/手动循环/盲循环/打结循环)
- 最关键也最容易被跳过的是验证:让 AI 给自己的输出打分会自我夸奖,必须换一个独立 agent 当挑刺专家,默认假设代码是坏的,要动手点页面截图,而不是只读代码
- Stripe 的 Minions 流水线每周合并超过 1300 个机器写的 PR,可靠性来自确定性约束(linter 强制跑、agent 绕不过),不是更大的模型
- 循环会悄悄积累四种代价:验证债、理解腐化、认知投降、Token 账单爆炸,四者互相强化,最后一起爆发,守门人始终是人的判断力
一周内,三个人撞上了同一件事
2026 年 6 月同一周内,Google Chrome 工程师 Addy Osmani、Anthropic 的 Claude Code 负责人 Boris Cherny、OpenClaw 作者 Peter Steinberger,各自没对过口风,却撞上了同一件事:他们已经不再手动提示 AI,而是在设计「自动提示 AI 的系统」。
为什么偏偏这一周冒出来
三个人没有商量,却在同一周伸手抓同一个词,不是巧合,是周围的工具悄悄越过了一道门槛。三个条件同时成熟:coding agent 已经可靠到能无人值守干完一个非平凡任务;调度原语刚出现在主流工具里;单次运行的成本掉到了反复跑也不算浪费。零件都齐了,「把它们组合起来」这个动作就对所有人同时变得显然。
名字滞后于实践好几个月:在有人叫它 Loop Engineering 之前,人们早就在写循环了,就像在「generator/evaluator 分离」有名字之前,团队早就在给一个写代码的 agent 配一个审代码的 agent。这条规律值得记住,下一个新词不会来自模型发布,会来自某个能力便宜到让一种过去想都不敢想的组合变成日常的那一刻。
它站在这四层的最上面
这些「XX 工程」不是互相取代,是一层摞一层,每层管的东西比下面大一号:从一句话,到一个上下文窗口,到一次运行,最后到一个能自己转的循环。点开每一层看它管什么、出错时炸多大。
Loop · 循环工程在最上面一层
Harness · 单次运行装备arm one run
Context · 上下文工程the window now
Prompt · 提示工程the words you write
把同一个 bug(agent 误读了某个函数的返回值)放到四层里看:越往上,发现得越晚,代价越大。到了循环层,这个误读被写进 state file,第二天当成事实读回,沿着它一层层往上盖,等有人去看时,那个错误假设已经成了承重墙。
这是循环工程里最该记住的一条直觉:错误的代价,等于它在被人发现前活过的轮数;而循环按构造就是一台「把轮数最大化」的机器。后面所有东西,evaluator、人工卡点、预算上限,存在的唯一目的,都是缩短「犯错」到「被发现」之间的距离。
一圈五步,缺哪步都会以固定方式坏掉
「循环」别误读成空转。每一轮都干具体的事:找到值得做的活、交给 agent、验证对不对、把状态存下来、再决定下一步。五步缺任何一步,循环要么不转,要么原地打转,而且会以一种有名有姓的方式坏掉。
下面用 Osmani 给自己搭的「早晨 triage 循环」当例子,逐步看每步干什么,以及跳过它会变成哪种循环。
这五步不是一张可选清单,是互相依赖的一个整体。纪律好的团队五步都装;匆忙的团队只装前两步(发现 + 交接),因为这两步产出看得见的输出,后三步产出的是「安全」,最容易被省掉。
搭一个循环,要凑齐六个零件
五步说的是「一轮里发生什么」,六个零件说的是「要让它转起来,手里得有什么」。两者一一对应:发现靠 skills,交接靠 worktrees,验证靠 sub-agents,持久化靠 memory,调度靠 automations。点开每张卡看它解决什么。
① Automations 自动化 调度
② Worktrees 隔离目录 交接
③ Skills / SKILL.md 发现
④ Connectors 接外部系统 持久化 / 发现
⑤ Sub-agents 拆开生成与评判 验证
⑥ Memory / state file 磁盘状态 持久化
就像几个厨师同时备菜,给每人一块独立砧板,各切各的互不碰手,共用一块砧板就会撞在一起。worktree 就是给每个并行的 agent 发一块自己的砧板。
六个零件都到位,循环就有了骨架:自动化让它动,worktree 让它不自相打架,skill 让它不重复劳动,connector 让它看见外面,sub-agent 让它自我纠错,memory 让它记得。但搭出骨架只是开始,同样这六个零件,两个人能搭出完全相反的东西,这是最后一节的话题。
最难的一步:为什么不能让 AI 给自己打分
循环最难的从来不是让 agent 跑起来,而是在里面放一个能说「不」的东西,而写代码的那个 agent,恰恰是最不可能说「不」的那个。
① 为什么它必然夸自己。让一个 agent 给自己刚产出的东西打分,它倾向于自信地夸,哪怕人一眼就看出质量平平,Anthropic 工程师 Prithvi Rajasekaran 在做长时运行应用时观察到这点。这不是智力问题:写这段代码的上下文里,已经塞满了「为什么要这么写」的理由,所以 agent 看自己的输出,看到的不是结果,是说服自己一路走到这里的那条链。放进循环里这毛病被放大:每一次「这够好了吗」都由刚写完的那个 agent 拍板,它一轮轮对自己点头,跑得越久离真实质量越远。
② 解法不是改作者,是换裁判。把 generator 调得更自我批判,这条路走不通,你没法要求一个作者跳出自己的视角。能做的是换一个独立 agent,从零看代码,带一套完全不同的指令,身上不沾任何自我说服。调一个独立的怀疑者,比把作者改成自我挑剔,容易太多。灵感来自 GAN(生成对抗网络):一个网络造,一个网络挑刺,搬到代码上就是一个写、一个审。
③ 只读代码还不够,得动手。如果 evaluator 只读代码,它判的是「这看起来对不对」,不是「这跑起来对不对」。在前端任务上,Rajasekaran 把 evaluator 接上 Playwright MCP,让它像 QA 一样真的打开页面、点按钮、截图、检查 DOM。判断依据从「这段 JSX 看着没问题」变成「我点了按钮,页面跳转了,截图在这」。顺手把底层模型也换掉,同一个模型换套指令,往往还带着同样的盲点。社区常用的一句校准:让 evaluator 默认假设代码是坏的,直到被证明不是,默认立场该是怀疑,不是信任。
④ maker-checker:最后那一锤由谁敲。Claude Code 用 /goal 把这个结构变成一个原语:给它一个条件,让它跑到条件满足为止。关键在于,每一轮结束后,由一个全新的小快模型判断条件是否达成,而不是正在干活的那个模型。这就是银行里用了几十年的 maker-checker 原则。
银行里录入一笔大额转账的人,和复核这笔转账的人,必须是两个人,这条规则在银行业沿用了几十年,叫 maker-checker。把它搬到循环里:写代码的 agent 和拍板「过没过」的模型,必须是两个,且后者从零开始、默认你写错了。
退回 generator 重写
进下一关
把 evaluator 落成配置,长这样,它的每一行都在执行上面四条:换个角色、默认坏、动手验、逐条说理由。
ROLE: Adversarial code reviewer.(对抗性审查者) ASSUME: this code is BROKEN until proven otherwise. # 默认代码是坏的,直到被证明相反 DO NOT praise. Find what fails. # 不许夸,只找哪里会崩 CHECK, in order: # 按顺序检查 1. Does it run? (execute, don't read) # 能不能跑:执行,别只读 2. Tests: run them, paste real output. # 跑测试,把真实输出粘出来 3. Edge cases the author skipped. # 作者跳过的边界情况 4. Does behavior match the ticket? # 行为符不符合工单 USE Playwright MCP: open the page, click, screenshot, inspect the DOM. Judge behavior, not intent. VERDICT: PASS only if every check holds. Otherwise REJECT + list each reason. # 全部通过才 PASS,否则 REJECT 并逐条列原因
/goal all tests in test/auth pass and the lint step is clean # 跑到「test/auth 全过 且 lint 干净」为止 # 注意:/goal 跑到条件满足为止,跟 /loop(每隔固定时间重跑)不是一回事
循环的下限,就由它的 evaluator 决定。generator 的水平决定循环能产出什么,evaluator 的水平决定它不会产出什么。把生成和评判从结构上拆开、把 evaluator 调成怀疑者、让它动手验、把最后一锤交给一个全新模型,这四步合起来,才是让一个循环长出「说不」能力的全部。
一个人的早晨,和 Stripe 每周 1300 个 PR
两个真实循环,规模差到极致,骨架却一样:一个触发器按下开始,一组约束把它锁在轨道上,末尾坐着一个人工卡点。「能在你睡觉时跑」从来不是模型多强,是这套骨架多稳。
Osmani 的早晨 triage
- 每天早上一个 automation 自己启动
- triage skill 读昨天挂的 CI、开着的 issue、最近的 commit
- 调的是一个 skill,不是粘进时间表的一坨指令
- 每个发现开一个 worktree:一个子 agent 起草、另一个对着 skill 和测试审
- connector 自动开 PR、更新工单
- 搞不定的进 inbox 等人,state file 让明天接着昨天
Stripe 的 Minions
- 每周合并 1300+ 个 PR,没有一行是人手写的
- 触发很轻:Slack 里 @ 一下 bot,或加个 emoji 反应
- 真正的功夫在模型醒来之前:一个确定性编排器先把上下文拼好
- 沙箱是 EC2 上的 Devbox,「牛而非宠物」,随用随换,上千 agent 同时跑不互撞
- 那 1300 个 PR 仍然由人 review:人没走,只是从写代码的桌子挪到了 review 的桌子
Stripe 最反直觉的一点:Minions 不是建在一个更强的模型上,它是开源工具 Goose 的一个 fork。它的核心主张是,可靠性来自约束的质量,不是模型的大小。架构上,确定性的关卡(蓝)和有创造性的 LLM 步骤(绿)交错咬合,能用确定逻辑解决的事,绝不交给概率模型,这条线画在哪,决定了循环可不可靠。(这一案例由 Stripe 工程师 Steve Kaliski 在 How I AI 播客披露。)
「在你睡觉时跑」到底靠什么
本地 /loop 和桌面定时任务,都得机器开着,关机就停。要在机器关着时也跑,正确答案是 Cloud Routines 或 GitHub Actions 的定时触发。三种方式各管一段:
| 调度方式 | 运行位置 | 机器要开着? | 会话要开着? | 最短间隔 | 能读本地文件? |
|---|---|---|---|---|---|
| 本地 /loop | 本机 | 要 | 要 | 1 分钟 | 能 |
| 桌面定时任务 | 本机 | 要 | 不要 | 1 分钟 | 能 |
| Cloud Routines / CI | 云端 | 不要 | 不要 | 1 小时 | 不能 |
要点不在挑哪个好,在于这两件是不同能力:本地调度 = 「我在的时候多跑几轮」,云调度 = 「我不在的时候也跑」。把本地重跑当成「无人值守」的全部,是最常见的误会,盖上笔记本的盖子,那个你以为自主的循环就悄悄停了。成熟的循环往往两种都用:本地管贴身的紧密检查,云端管过夜的整体扫一遍。
顺手说一句:命令是 Claude Code 的,能力不绑它
这篇里的命令是 Claude Code 的写法,但能力不是它独有的。Codex 用不同的名字提供同样六个器官:调度、跑到条件满足、并行隔离、子 agent、外部接入、显式调 skill,一个工具写的 connector 常常能原样挪到另一个上用。换哪条工具链,该问的都是「六个是不是都在」,不是「这个命令是哪家的」。
手把手:搭你的第一个循环
Stripe 那条流水线是终点,不是起点。第一个循环应该小到几乎不像个系统:一个到点就去查点东西的小玩意。下面五步可以照着抄,每步配命令和配置,最后凑成一个装齐六要素的最小完整循环。
① 起一个 /loop
v2.1.72 之后可用,它把同一个任务按间隔重跑。作用域是 session,重复任务 7 天后过期,跑在本机上,关机就停。三种用法:
/loop 5m check the deploy # 固定:每 5 分钟跑一次 /loop check the deploy # agent 自己定节奏 /loop # 读 .claude/loop.md 里的任务
② 用 skill 做自动发现:先 triage
光重跑一行不算循环。给它一个提示,每天早上看三样东西,列出值得处理的。「定时 + 自动发现」才算循环入门。发现的逻辑要写进 skill,不要写进时间表,cron job 里的指令没人更新就会腐烂,SKILL.md 可以维护、可以复用。
NAME: morning-triage WHEN: invoked each morning by automation. # 每天早晨由 automation 调用 READ: - CI runs that failed since yesterday # 昨天起挂掉的 CI - issues opened in the last 24h # 过去 24 小时新开的 issue - commits merged since the last run # 上次跑后合并的 commit JUDGE: for each item, is it worth acting on? Skip noise. Keep only actionable findings. # 逐条判断:现在可操作还是噪音?只留可动手的 OUTPUT: write findings + status to ./state/triage.md (one row per finding). # 写到 ./state/triage.md,每条一行
③ 加一个 state 文件
别把结果留在聊天窗口里。把每条发现、处理到哪一步,写进一个 markdown 文件(或一块 Linear 看板)。agent 会忘,repo 不会忘。
| finding | source | status | |-----------------|-----------|----------| | auth test flaky | CI #4821 | fixing | | null deref | issue 92 | PR open | | stale dep | commit a3 | inbox |
④ 加 /goal 评估器
最关键、也最容易被跳过的一步。/goal(v2.1.139 起)跑到一个条件满足为止,由一个不同的模型判断条件成没成。注意它和 /loop 不一样:/loop 是每隔固定时间重跑,/goal 是跑到达标为止,停止条件由一个全新的小模型判。配套放上节那个 reviewer.md(默认代码是坏的、动手验、逐条说理由),让它在每轮里挑刺。
/goal all tests in test/auth pass and the lint step is clean # 跑到「test/auth 全过 且 lint 干净」为止,由全新小模型判
⑤ 加 --worktree 并行隔离
用 --worktree(或 -w)给每个后台 agent 开一个独立 worktree,一个 worktree 对应一个任务,多个 agent 同时改代码不会撞文件。
claude --worktree fix/auth-test "draft the fix" claude --worktree fix/null-deref "draft the fix"
第一个循环的六要素清单
勾一勾,看自己装齐了没。前两条决定能不能跑,后四条决定跑起来出问题没人管。新手最常见的错误,就是只装前两个,结果是一个没人看、也没人能停、还在对自己点头的循环。
一个装齐六要素的最小循环
把清单落成代码,下面这段小到能一口气读完,却装着真循环需要的每个器官,只是缩小了。六个注释和六要素一一对应。
# 1. 调度 , 一个真触发器 on: schedule: - cron: '0 6 * * *' # 每天 06:00,云端跑 # 2. 发现 , 调一个 skill,不是一坨指令 run: claude --skill morning-triage # 3. 持久化 , 状态落盘 # skill 写 ./state/triage.md 并 commit 回 repo # 4. 交接 + 验证 , 一个发现一个 worktree,跑到达标 for finding in $(parse ./state/triage.md); do claude --worktree "fix/$finding" \ --goal "tests pass and lint is clean" \ "draft a fix for $finding" done # 5. 验证 , 每轮后由全新模型判 stop, # 外加一个 reviewer agent 专门挑刺 # 6. 人工 review , 留着的那扇门 # PR 只开不自动合并;拿不准的进 ./inbox/
六个都装齐,再小也是真循环;缺任何一个,它就是上一节那五种失败之一,换了身伪装。第一个循环最好小,但「说不」的检查和人工 review 卡点必须装满。
循环会偷偷记下四笔账
一个能自己跑的循环,同时也是一个能自己犯错的循环。它跑得越欢,错得越静。四种代价在它运行时悄悄累积,没有一个会当场报警。
用一个具体场景看四者怎么逐级触发:循环一夜开出 20 个 PR,测试全绿,表面看是大捷。但其中 3 个藏着测试覆盖不到的小 bug。
那 3 个埋下的错误,现在躺在一个你已经不完全看得懂的代码库里,由一个已经不看的人「守着」,直到某一个在生产环境里冒头才被发现。四种代价不是一份各自独立的风险清单,是同一个失败长出的四张脸,互相喂养,最后一起到期。
守门方法各有各的:
四者共享一个特点:循环跑着的时候,它们全是静默的。循环工程最迷人的地方,是让一个人干一个团队的活;最危险的地方也在同一处,团队会自己跟自己吵,一个人加一堆循环,很容易变成没人争论的回音室。守门人始终是人的判断力。
你仍然是工程师,不只是按按钮的人
同一套循环,两个人搭,可以走到相反的地方,而区别不在循环本身。
一个人用循环在自己已经吃透的事上跑得更快:他读代码,对方向有把握,循环放大的是他本就有的判断。另一个人用同一套循环,是为了再也不用去搞懂,六个月后,前者变得更强,后者成了一台自己读不懂的机器的守门人。
循环不是那种「质量由工具定死」的工具,它强到会原样放大你带进去的东西:带着理解去,它放大理解;带着懒惰去,它放大懒惰。它是一个忠实的乘法符号,乘的是搭循环的那个人。
循环让生成几乎免费:代码、计划、PR、修复,近乎白来。剩下稀缺的是判断:知道哪个计划对、哪一行该停、哪个输出跑起来没问题但根上是错的。循环能生成一百个选项,却没法真的选,或者说,它按「看起来合理」来选,而不是「实际正确」,这两者之间的缝,正是工程师存在的理由。所以循环工程没有让判断贬值,它剥掉了所有不需要判断的活,把判断留成唯一剩下的东西。工程师的价值,从「打字快、API 背得多、愿意搞样板代码」,移到了「知道哪条路对、哪行该停、哪个输出跑起来对但根上错」。
build the loop, but build it like someone who intends to stay the engineer, not just the person who presses go.Addy Osmani,《Loop Engineering》,2026 年 6 月