Loop Engineering

循环工程取代了手动提示编码代理的方式,通过设计自动化循环系统让代理自主迭代工作,但工程师仍需保持对代码的理解和审查以避免质量下降。

Loop engineering is replacing yourself as the person who prompts the agent. You design the system that does it instead. A loop here can be thought of a recursive goal where you define a purpose and the AI iterates until complete. I believe this may be the future of how we work with coding agents. However, its still early, I’m skeptical and you absolutely have to be careful about token costs (usage patterns can vary wildly if you are token rich or poor), so I want to unpack what it is and what it means.

循环工程正在取代你作为提示智能体的人。你设计系统来代替你完成这项工作。 这里的循环可以被视为一种递归目标:你定义一个目的,然后AI反复迭代直到完成。我相信这可能是我们与编码智能体协作的未来方向。不过,这仍然处于早期阶段,我持怀疑态度,而且你绝对必须对Token消耗保持警惕(Token富足或贫乏会导致使用模式天差地别),所以我想拆解一下它是什么以及意味着什么。


Peter Steinberger recently said: “You shouldn’t be prompting coding agents anymore. You should be designing loops that prompt your agents.” Similarly, Boris Cherny, head of Claude Code at Anthropic, said “I don’t prompt Claude anymore. I have loops running that prompt Claude and figuring out what to do. My job is to write loops”.

Peter Steinberger最近:“你不应该再给编码代理写提示了。你应该设计循环,让循环来提示你的代理。”类似地,Anthropic公司Claude Code负责人Boris Cherny表示:“我不再提示Claude了。我有一些循环在运行,它们提示Claude并决定下一步做什么。我的工作是写循环。”

Okay, so what does any of that mean?

好吧,那这一切又是什么意思呢?

For like two years the way you got something out of a coding agent was you wrote a good prompt and shared enough context. You type a thing, you read what came back, you type the next thing. The agent is a tool and you are holding it the entire time, one turn after the other. That part is kind of over, or at least some think it’s going to be.

差不多有两年的时间,从编码代理那里获取结果的方式就是写一个不错的提示词,并提供足够的上下文。你输入内容,阅读返回的结果,再输入下一项。代理是一个工具,你全程握着它,一轮接一轮地操作。这部分基本上结束了,或者至少有些人认为它即将结束。

Now you build a small system that finds the work, hands it out, checks it, writes down what is done and then decides the next thing, and you let that system poke the agents instead of you. I wrote before about the cousin of this, agent harness engineering, which is making the environment one single agent runs inside and the factory model - the system that builds the software. Loop engineering sits one floor above the harness. The harness but it runs on a timer, it spawns little helpers, and it feeds itself.

现在你构建一个小型系统:它负责查找任务、分配任务、检查任务、记录已完成内容,然后决定下一步做什么。你让这个系统去催促各个智能体,而不是由你亲力亲为。我之前写过它的变体:智能体框架工程,也就是构建单个智能体运行的环境;还有工厂模型,即构建软件的系统。而循环工程比框架高一个层级:框架在定时器上运行,生成小帮手,并自我供给。

The thing that surprised me is this is not really a tool thing anymore. A year ago if you wanted a loop you wrote a pile of bash and you maintained that pile forever and it was yours and only yours. Now the pieces just ship inside the products. Steinberger’s list maps almost exactly onto the Codex app, and then almost the same onto Claude Code. And once you notice the shape is the same you stop arguing about which tool, you just design a loop that still works no matter which one you happen to be sitting in.

让我惊讶的是,这已经不再是什么工具层面的问题了。一年前,如果你想要一个循环,你得写一堆bash脚本,然后永无止境地维护它,它只属于你一个人。现在这些模块直接集成在产品里了。Steinberger的列表几乎完美对应Codex应用,然后又几乎原样映射到Claude Code。一旦你发现它们的形态其实一模一样,你就不会再争论该用哪个工具,而是直接设计出一个无论你碰巧用哪个工具都能正常工作的循环。

The five pieces, and then notes

五件作品,以及注释

A loop needs five things and then one place to remember stuff. Let me list it first and then map it.

一个循环需要五个要素,以及一个存储信息的地方。让我先列出它们,再进行映射。

  1. Automations that go off on a schedule and do discovery and triage by themselves.
  2. Worktrees so two agents working in paralell dont step on each other.
  3. Skills to write down the project knowledge the agent would otherwise just guess.
  4. Plugins and connectors to plug the agent into the tools you already use.
  5. Sub-agents so one of them has the idea and a different one checks it.
  1. 自动化:按计划触发,自动完成发现和分类工作。
  2. 工作树:让两个并行工作的代理互不干扰。
  3. 技能:记录项目知识,避免代理仅凭猜测行事。
  4. 插件和连接器:将代理接入您已使用的工具。
  5. 子代理:一个负责提出想法,另一个负责检验。

Then the sixth thing, the memory. A markdown file, or a Linear board, anything that lives outside the single conversation and holds what’s done and what is next. Sounds too dumb to matter. But it’s the same trick every long running agent depends on and I went into it in long-running agents, the model forgets everything between runs so the memory has to be on disk and not in the context. The agent forgets, the repo doesnt.

第六件事,记忆。一个 markdown 文件,或者一个 Linear board,任何存在于单次对话之外并能记录已完成和接下来任务的东西。听起来蠢到似乎无关紧要。但这是每个长时运行代理都依赖的相同技巧,我在长时运行代理一文中深入讨论过,模型在每次运行之间会遗忘所有内容,因此记忆必须存储在磁盘上,而不是上下文中。代理会遗忘,而仓库不会。

Both products have all five now.

两款产品现在都拥有全部五个了。

PrimitiveJob in the loopCodex appClaude Code
Automationsdiscovery + triage on a scheduleAutomations tab: pick project, prompt, cadence, environment; results land in a Triage inbox; /goal for run-until-doneScheduled tasks and cron, /loop, /goal, hooks, GitHub Actions
Worktreesisolate parallel featuresBuilt-in worktree per threadgit worktree, --worktree, isolation: worktree on a subagent
Skillscodify project knowledgeAgent Skills (SKILL.md), invoked with $name or implicitlyAgent Skills (SKILL.md)
Plugins / connectorsconnect your toolsConnectors (MCP) plus plugins for distributionMCP servers plus plugins
Sub-agentsideate and verifySubagents defined as TOML in .codex/agents/Task subagents in .claude/agents/, agent teams
Statetrack what’s doneMarkdown or Linear via a connectorMarkdown (AGENTS.md, progress files) or Linear via MCP

The names are a bit different here and there but the capability is the same thing. Let me go one by one because honestly the details are where a loop either holds together or quietly leaks everywhere.

名称上有些地方稍有不同,但功能是一样的。让我逐个来看,因为说实话,细节之处往往决定了一个循环要么运转良好,要么处处悄然泄漏。

Automations, this is the heartbeat

自动化,这是核心

Automations are what make a loop an actual loop and not just one run you did once. In the Codex app you make one in the Automations tab and you pick the project, the prompt it will run, how often, and if it runs on your local checkout or on a background worktree. The runs that find something go to a Triage inbox, and the runs that find nothing just archive themselves wich is nice. OpenAI uses them internally for boring stuff like daily issue triage, summarising CI failures, writing commit briefings, hunting bugs somebody added last week. And an automation can call a skill, so you keep the recurring thing maintainable, you fire $skill-name instead of pasting a giant wall of instructions into a schedule that nobody will ever update.

自动化功能让循环成为真正的循环,而不只是你执行过一次的单次运行。在 Codex 应用中,你可以在 Automations 标签页创建自动化,选择项目、要运行的提示词、运行频率,以及是在本地检出上运行还是在后台工作树上运行。找到结果的运行会进入 Triage 收件箱,没找到结果的运行则自动归档,这点很不错。OpenAI 内部用它来处理枯燥的任务,比如每日问题分类、汇总 CI 失败信息、编写提交简报、排查上周别人引入的 bug。而且自动化可以调用技能,这样你就能保持周期性任务的可维护性——直接执行 $skill-name 而不是把一大段指令粘贴到没人会更新的计划里。

Claude Code gets to the same place but through scheduling and hooks. You can run a prompt or a command on a interval with /loop, you can schedule a cron task, you can fire shell commands at certain points in the agent lifecycle with hooks, or you push the whole thing to GitHub Actions if you want it to keep running after you close the laptop. Same idea exactly, you define an autonomous task, you give it a cadence, and the findings come to you so you are not the one going around checking.

Claude Code 通过调度和 hooks 达到同样的效果。你可以用 /loop 按时间间隔运行提示或命令,可以安排 cron 任务,可以在智能体生命周期的特定节点通过 hooks 触发 shell 命令,或者把整个流程推到 GitHub Actions 上,这样你合上笔记本后它也能继续运行。思路完全一样:定义一个自主任务,设定一个节奏,结果会自动反馈给你,你就不用自己到处检查了。

There is a second in-session primitive worth knowing, and it’s the one closer to what this whole post is about. /loop re-runs on a cadence. /goal keeps going until a condition you wrote is actually true, and after every turn a separate small model checks whether you are done, so the agent that wrote the code isnt the one grading it. You give it something like “all tests in test/auth pass and lint is clean” and walk away. Codex has the same thing, also called /goal, it keeps working across turns until a verifiable stopping condition holds, with pause and resume and clear. Same primitive, both tools, wich is kind of the pattern for this whole article.

有一个值得了解的第二个会话内原语,它更接近这篇文章的主题。/loop 按固定间隔重新运行。/goal 持续运行直到你编写的条件真正成立,并且每次轮次结束后,一个独立的小模型会检查你是否完成,这样编写代码的智能体不会自己评判结果。你给它类似“test/auth 中的所有测试通过且 lint 无报错”这样的条件,然后就可以放手了。Codex 也有同样的功能,也叫 /goal,它会跨轮次持续工作,直到一个可验证的停止条件成立,并支持暂停、恢复和清除。两个工具使用相同的原语,这也是整篇文章的一个模式。

So this is the part that surfaces the work. The rest of the loop is what acts on it.

所以,这部分就是呈现工作成果的部分。循环的其余部分则是对其进行操作。

Worktrees so paralell doesnt turn into chaos

并行不乱的秘诀:工作树

The second you run more than one agent the files start colliding, that becomes the failure. Two agents writing the same file is the exact same headache as two engineers committing to the same lines and nobody talked to each other first. A git worktree fixes it, its a separate working directory on its own branch sharing the same repo history, so one agent’s edits literally can not touch the other one’s checkout.

你一旦运行多个代理,文件就会开始冲突,这就会导致失败。两个代理写同一个文件,就跟两个工程师在没有事先沟通的情况下提交到同一行代码一样令人头疼。git worktree 解决了这个问题,它是一个独立的工作目录,位于自己的分支上,共享同一个仓库历史,因此一个代理的编辑根本不会影响到另一个代理的检出内容。

Codex builds the worktree support right in so several threads hit the same repo at once and dont bump into each other. Claude Code gives you the same isolation with git worktree, a --worktree flag to open a session in its own checkout, and a isolation: worktree setting you stick on a subagent so each helper gets a fresh checkout that cleans itself up after. I wrote about the human side of all this in the orchestration tax, the worktrees take away the mechanical collision but YOU are still the ceiling, your review bandwith decides how many you can actually run, not the tool.

Codex 原生内置了工作树支持,这样多个线程可以同时访问同一个仓库而互不冲突。Claude Code 通过 git worktree、一个 --worktree 标志(用于在独立检出中打开会话),以及一个 isolation: worktree 设置(可附加到子代理上,使每个助手获得一个全新的、用后自动清理的检出)来提供同样的隔离机制。我在编排税一文中讲述了这一切中的人为因素:工作树消除了机械冲突,但真正的瓶颈仍然是你自己——你的审查带宽决定了你实际能运行多少个代理,而不是工具本身。

Skills, so you stop explaining your project every single time

技能,这样你就不用每次都解释你的项目了

A skill is how you stop re-explaining the same project context every session like a goldfish. Both tools use the same format, a folder with a SKILL.md inside holding instructions and metadata, and then optional scripts, references, assets. Codex runs a skill when you call it with $ or /skills, or by itself when your task matches the skill description, wich is the reason a tight boring description beats a clever one. Claude Code does it the same way and I wrote the pattern up in agent skills.

技能就是让你不必每次会话都像金鱼一样重复解释相同项目背景的方法。两个工具都使用相同的格式:一个文件夹,里面包含一个SKILL.md文件存放指令和元数据,以及可选的脚本、参考资料、资源文件。Codex在你使用$/skills调用技能时运行它,或者当你的任务匹配技能描述时自动运行,这也是为什么一个严谨、枯燥的描述胜过花哨描述的原因。Claude Code也是如此,我已经将这个模式写在了agent skills中。

Skills are also where intent stops costing you over and over. I argued in the intent debt that an agent starts every session cold and it will fill any hole in your intent with a confident guess. A skill is that intent written down on the outside, the conventions, the build steps, the “we dont do it like this because of that one incident”, written one time where the agent reads it every run. Without skills the loop re-derives your whole project from zero every cycle, with skills it kind of compounds.

技能也是让你的意图不再反复消耗成本的关键。我在意图债务一文中指出,智能体每次会话启动时都从零开始,它会用自信的猜测填补你意图中的任何空白。而技能就是将意图以文字形式记录在外——那些约定、构建步骤,以及”那次事故之后我们不这样做”的经验教训——只需写一次,智能体便会在每次运行时读取。没有技能,循环每次都要从零推导整个项目;有了技能,它就形成了复利效应。

One thing to keep straight, the skill is the authoring format and a plugin is how you ship it. When you want to share a skill across repos or bundle a few together you package them as a plugin. True in Codex, true in Claude Code.

有一点要明确:技能(skill)是创作格式,而插件(plugin)是交付方式。当你想跨仓库共享一个技能或将几个技能打包在一起时,就把它们封装成插件。这一点在 Codex 中成立,在 Claude Code 中同样成立。

Plugins and connectors, the loop touches your real tools

插件和连接器,循环触及你的真实工具

A loop that can only see the filesystem is a tiny loop. Connectors, wich are built on MCP, let the agent read your issue tracker, query a database, hit a staging api, drop a message in Slack. Codex and Claude Code both speak MCP so the connector you wrote for one usually just works in the other. And plugins bundle connectors and skills together so your teammate installs your setup in one go instead of rebuilding the whole thing from memory.

只能看到文件系统的循环是个很小的循环。基于 MCP 构建的连接器,能让代理读取你的问题追踪器、查询数据库、访问预发布 API、在 Slack 里发送消息。Codex 和 Claude Code 都支持 MCP,因此你为其中一个编写的连接器通常也能直接用在另一个上。而插件将连接器和技能打包在一起,这样你的队友就能一次性安装你的配置,而不必凭记忆重新搭建整套系统。

This is the difference between an agent that says “here is the fix” and a loop that opens the PR, links the Linear ticket and pings the channel once CI is green by itself. The connectors are the reason the loop can act inside your actual environment instead of just telling you what it would do if it could.

这就是一个说“这是修复方案”的智能体与一个循环之间的区别:后者会自动创建 PR、关联 Linear 工单,并在 CI 变绿后自行在频道中提醒。连接器是让循环能够在你的实际环境中行动,而不仅仅是告诉你“如果它能做它会做什么”的原因。

Sub-agents, keep the maker away from the checker

子代理,让制造者远离检查者

The most useful structural thing in a loop, by far, is splitting the one who writes from the one who checks. The model that wrote the code is way too nice grading its own homework. A second agent with different instructions and sometimes a different model catches the stuff the first one talked itself into.

到目前为止,循环中最有用的结构性做法,是将编写者和检查者分开。编写代码的模型给自己批改作业时太宽容了。第二个智能体,带有不同的指令,有时是另一个模型,能捕捉到第一个智能体自我说服产生的那些问题。

Codex only spawns subagents when you ask, runs them at the same time and then folds the results back into one answer. You define your own agents as TOML files in .codex/agents/, each with a name, a description, instructions and optional model and reasoning effort, so your security reviewer can be a strong model on high effort while your explorer is some fast read-only thing. Claude Code does the same with subagents in .claude/agents/ and agent teams that pass work between them. The usual split in both is one agent explores, one implements, one verifies against the spec.

Codex 仅在您要求时才会生成子代理,同时运行它们,然后将结果汇总为一条回答。您可以将自定义代理定义为 TOML 文件,存放在 .codex/agents/ 中,每个代理包含名称、描述、指令,以及可选的模型和推理力度,这样您的安全审查员可以使用高推理力度的强模型,而探索者可以是一个快速只读的玩意儿。Claude Code 在 .claude/agents/ 中也采用了类似的方式使用子代理,以及可以在任务之间传递工作的代理团队。两者通常的分工是:一个代理负责探索,一个代理负责实现,还有一个代理对照规范进行验证。

I made this case twice already, once as the code agent orchestra and once as adversarial code review. The reason it matters specifically inside a loop is the loop runs while you are not watching, so a verifier you actually trust is the only reason you can walk away. Subagents do burn more tokens since each one does its own model and tool work, so spend them where a second opinion is worth paying for. This is also basically what Claude Code’s /goal does under the hood, a fresh model decides if the loop is done instead of the one that did the work, the maker and checker split applied to the stop condition itself.

这个案例我已经做过两次,一次是代码智能体编排,另一次是对抗性代码评审。它之所以在循环内部尤为重要,是因为循环在你未监控时持续运行,因此一个你真正信任的验证器,是你敢于放手的唯一理由。子智能体确实会消耗更多 token,因为每个子智能体都要独立完成自身的模型和工具调用,所以应当将它们用在值得为第二意见付费的地方。这也是 Claude Code 的 /goal 命令在底层的工作原理——由一个全新的模型来判断循环是否结束,而非由执行工作的模型来判定,即制作者与检查者的分工被应用到了停止条件本身。

What one loop looks like

一个循环的样子

Stick it together and a single thread turns into a little control panel. Here is one shape I keep using.

把它粘在一起,一根线就变成了一个小控制面板。这是我一直在使用的一种形状。

An automation runs every morning on the repo. Its prompt calls a triage skill that reads yesterdays CI failures, the open issues, the recent commits, and writes the findings into a markdown file or a Linear board. For each finding that is worth doing the thread opens an isolated worktree and sends a sub-agent to draft the fix, and a second sub-agent reviews that draft against the project skills and the existing tests.

每天早上,仓库中都会自动运行一个自动化任务。其提示词调用一个分类技能,该技能会读取昨日的CI失败记录、未关闭的问题以及最近的提交,并将发现的结果写入一个markdown文件或Linear看板中。对于每个值得处理的问题,线程会创建一个隔离的worktree,并派出一个子代理来起草修复方案,再由第二个子代理根据项目技能和现有测试对这份草案进行审查。

Connectors let the loop open the PR and update the ticket. Anything the loop can not handle lands in the triage inbox for me. The state file is the spine of the whole thing, it remembers what got tried, what passed, what is still open, so tomorrow morning the run picks up where today stopped.

连接器让循环可以打开PR并更新工单。循环无法处理的任何内容都会落入我的分类收件箱中。状态文件是整个流程的核心,它记住了哪些尝试过、哪些通过了、哪些仍然未完成,这样明天早上运行就会从今天停止的地方继续。

And look at what you actually did there. You designed it one time. You did not prompt any of those steps. Thats Steinberger’s whole point made real, and its the same loop in Codex or in Claude Code because the pieces are the same pieces.

你看看你实际做了什么。你只设计了一次,后面的步骤一个都没提示过。这恰恰印证了施泰因伯格的全部论点,而在Codex或Claude Code里也是同一套循环——因为构成要素都一样。

What the loop still does not do for you

循环仍然无法为你做到的事情

The loop changes the work, it does not delete you from it. And three problems actually get sharper as the loop gets better, not easier.

循环改变了工作方式,但并未将你从中剔除。而随着循环的优化,三个问题实际上会变得更尖锐,而非更简单。

Verification is still on you. A loop running unattended is also a loop making mistakes unattended. The whole reason you split the verifier sub-agent from the maker is to make the loop’s “its done” mean something, and even then “done” is a claim and not a proof. I keep saying the same line from code review in the age of AI, your job is to ship code you confirmed works.

验证的责任仍旧在你身上。无人值守运行的循环,同时也是无人值守犯错的循环。你把验证子代理与制造者分开的全部原因,就是为了让循环中的“已完成”有意义,但即便如此,“完成”也只是一个声明,而非一个证明。我一直在重复 AI时代的代码审查 中的同一句话:你的工作是交付你确认能正常运行的代码。

Your understanding still rots if you allow it. The faster the loop ships code you did not write, the bigger the gap between what exists and what you actually get. Thats comprehension debt and a smooth loop just makes it grow faster unless you read what the loop made.

如果你放任自流,你的理解力依然会腐化。循环机制交付非你编写的代码越快,现有代码与你实际掌握的内容之间的鸿沟就越深。这就是理解债务,而一个顺畅的循环只会让这条鸿沟加速扩张——除非你花时间去阅读循环产出的内容。

And the comfortable posture is the dangerous one. When the loop runs itself its very tempting to stop having an opinion and just take whatever it gives back. I called that cognitive surrender. Designing the loop is the cure when you do it with judgement and the accelerant when you do it to avoid thinking, same action, opposite result.

而舒适的姿态往往最危险。当循环自行运转时,人会忍不住放弃自己的判断,只是被动接受它反馈的一切。我称之为认知投降。设计这个循环时,若带着审慎去执行,它就是解药;若为逃避思考而为之,它就成了助燃剂——同样的行为,截然相反的结局。

Build the loop. Stay the engineer.

构建循环。保持工程师本色。

I think this is a preview of how our work is going to evolve. That said, If I weren’t reviewing the code myself or if I relied entirely on automated loops to fix it my product’s quality would suffer. I’d likely end up stuck in a downward spiral, continuously digging myself into a deeper hole.

我认为这是我们工作将如何演变的一个预演。话虽如此,如果我不亲自审查代码,或者完全依赖自动化循环来修复问题,我的产品质量就会受损。我最终很可能陷入恶性循环,让自己越陷越深。

That said, go ahead and set up your loops, but don’t forget that prompting your agents directly is also effective. It’s all about finding the right balance.

话虽如此,尽管去设置你的循环吧,但别忘了直接提示你的智能体也同样有效。关键在于找到合适的平衡。

Loops can also result in different outcomes depending on you. Two people can build the exact same loop and get completely opposite results. One uses it to move faster on work they understand deeply. The other uses it to avoid understanding the work at all. The loop doesn’t know the difference. You do.

循环也可能因为你而产生不同的结果。两个人构建完全相同的循环,结果却可能截然相反。一个人用它来在自己深度理解的工作上快速推进。另一个人则用它来完全回避理解工作本身。循环本身并不知晓其中的区别。而你知道。

That’s what makes loop design harder than prompt engineering, not easier. Cherny’s point isn’t that the work got easier. It’s that the leverage point moved.

这就是为什么循环设计比提示工程更困难,而不是更简单。Cherny 的观点并非工作变得简单了,而是杠杆点转移了。

Build the loop. But build it like someone who intends to stay the engineer, not just the person who presses go.

构建循环。但要像打算一直做工程师的人那样去构建,而不是仅仅按下开始按钮的人。