写作归档
循环工程:Loop Engineering · 主图
循环工程:Loop Engineering

循环工程:Loop Engineering

类型
文章
日期
2026/10/05
阅读
15 分钟
字数
4,040

循环工程指用自建系统替代人工向编码 agent 输入提示词。文章提出循环由五个模块加记忆组成:自动化负责按计划发现和分类任务,工作树保证并行 agent 互不干扰,技能记录项目知识避免重复解释,插件与连接器让 agent 接入 issue 追踪、数据库等真实工具,子 agent 分离创作者与检查者,记忆则以 markdown 或看板形式存于磁盘,因为模型会遗忘而仓库不会。Codex 和 Claude Code 均已内置这些模块,形态相同,因此重点不在选工具,而在设计可跨工具运行的循环。作者也提醒,验证责任、理解债务和认知投降仍由人承担,循环设计比提示词工程更难,杠杆点已转移。

原文:Loop Engineering.

搬运来源:磊叔的AI知识库

前言

循环工程师用你自己设计的系统来代替你作为“向 agent 输入 prompt 的人”的角色。 你设计的系统会代替你完成这个工作,这里的循环可以被视为一个递归的目标:你定义一个目的,AI反复迭代直到完成,它呆滞由五个构建模块组成,而Claude Code 和 Codex 现在都拥有这五个模块。

我在甘心这可能是我们未来使用编码agent的方式,不过,现在还为时尚早,我对此持有怀疑态度,而且你必须小心 token 成本(如果你token充裕或匮乏,使用模式可能会有天壤之别)。你还需要一些方法来确保质量不下降,并且对“slop”(粗糙输出)的担忧也是合理的。话虽如此,让我们来探讨一下这到底是怎么回事。

@steipete 最近说过:”你不应该在手动给编码 agnet 写 prompt 了,你应该设计一个循环来为你向 anget 输入 prompt。” 类似的,Anthropic 的 Claude code 负责人 也说过:“我不再手动给 Claude 写 Prompt 了,我运行着一些循环,它们负责给 Claude 写 prompt 并决定做什么。我的工作是写循环!”

那么,这到底是什么意思?

过去两年里,你从编码 agent 那里得到结果的方式,就是写一个好的 prompt(提示词)并提供足够的上下文。你输入一些东西,阅读返回的结果,然后再输入下一个东西。Agent 是一个工具,你全程握着它,一轮又一轮地进行交互。这部分工作基本结束了,或者至少有些人认为它将会结束。

现在,你构建一个小型系统:它负责发现任务,分配任务,检查结果,记录已完成的工作,然后决定下一步做什么。你让这个系统替你去“操作” agent,而不是你自己来做。

概念变体

工厂模型:编码代理如何改变软件工程

构建软件的系统。循环工程则位于 harness(工作台)上一层。你的 harness(工作台)按时运行,它会产生小助手,并且自我驱动。

让我惊讶的是,这已经不再单纯是一个工具层面的问题了。一年前,如果你想要一个循环,你得敲一堆 bash 脚本,并且要一直维护那堆脚本,它只属于你自己。而现在,这些模块就直接内置在产品里了。Steinberger 列出的清单几乎完全对应着 Codex 应用,然后又几乎完全对应着 Claude Code。一旦你注意到它们的形态是相同的,你就不会再纠结于用哪个工具,你只需设计一个无论你身处哪个工具都能正常工作的循环。

五个模块

需要五个东西,加上一个用来记录状态的地方。我先列出来,然后再做映射。

  1. 自动化(Automations):能按计划自动运行,自行进行发现和分类。

  2. 工作树(Worktrees):确保并行工作的两个 agent 不会互相干扰。

  3. 技能(Skills):用于记录项目知识,避免 agent 只能靠猜测。

  4. 插件与连接器(Plugins and Connectors):将 agent 与你已有的工具连接起来。

  5. 子 Agent(Sub-agents):让一个 agent 负责构思,另一个不同的 agent 负责检查。

第六个东西是记忆(memory)。一个 markdown 文件,或者一个 Linear 看板,任何独立于单个会话之外的东西,用它来记录已完成和下一步的任务。听起来简单得不值一提,但这是所有长期运行 agent 都依赖的同一个技巧,模型在运行间隙会忘记一切,所以记忆必须存储在磁盘上,而不是上下文中。Agent 会忘记,但仓库(repo)不会。两个产品现在都拥有这五个模块。长程运行的 Agent

记忆对比.png

名称上可能略有差异,但功能是相同的。让我逐一说明,因为说实话,细节决定了循环是能够稳健运行,还是会悄无声息地四处泄露。

自动化 -> 核心命脉

自动化是将循环变成真正持续运行的循环,而不是一次性运行的关键。在 Codex 应用中,你在自动化(Automations)标签页创建一个自动化,然后选择项目、它将要执行的 prompt(提示词)、运行频率,以及它是在你的本地检出环境运行还是在后台工作树上运行。有结果的运行会进入分类(Triage)收件箱,而没有结果的运行则会自行归档,这很人性化。OpenAI 内部将其用于一些枯燥的任务,如每日 issue 分类、总结 CI 失败原因、编写 commit 简报、查找上周别人引入的 bug。自动化还可以调用一个 skill(技能),这样你就可以让重复性任务变得可维护,通过调用$skill-name来代替将一大段指令粘贴到一个没人会更新的日程表中。

Claude Code 通过调度(scheduling)和钩子(hooks)实现了同样的功能。你可以使用 /loop 按时间间隔运行一个 prompt(提示词)或命令,你可以调度一个 cron 任务,你可以使用 hooks 在 agent 生命周期的特定时刻触发 shell 命令,或者如果你想让它在关闭笔记本电脑后继续运行,你可以将整个过程推到 GitHub Actions。思路完全相同:你定义一个自主任务,给它设定一个节奏,结果会反馈给你,这样你就不需要亲自去检查了。

还有一个值得了解的会话内原语,它更接近这篇文章的核心。 /loop 按一定节奏重新运行。 /goal 则会持续运行,直到你写的条件变为真,每轮之后,一个独立的较小模型会检查任务是否完成,这样就避免了自己写的代码自己评分。你给它一个类似“test/auth 目录下所有测试通过且 lint 检查干净”的条件,然后就可以放手了。Codex 也有同样的功能,也叫 /goal,它会跨轮次持续工作,直到一个可验证的停止条件成立,并支持暂停、恢复和清除。相同的原语,两个工具都有,这正是贯穿本文的模式。

所以,这是让任务浮现出来的部分。循环的其余部分则负责处理这些任务。

工作树 -> 让并行不陷入混乱

Codex 内置了对 worktree 的支持,因此多个线程可以同时操作同一个仓库而不会互相干扰。Claude Code 通过 git worktree 提供同样的隔离机制,使用 --worktree 标志可以在其自己的检出环境中打开一个会话,还可以在子 agent 上设置 isolation: worktree 配置,让每个助手获得一个全新的、用后即清理的检出环境。我在the orchestration tax(编排开销)中写过这方面的人为因素,worktree 消除了机械层面的冲突,但你自己仍然是瓶颈,你的审查带宽决定了你实际能运行多少个 agent,而不是工具本身。

技能 -> 让你不必每次都从头解释项目

Skill(技能)让你不必像金鱼一样,每次会话都重新解释同一个项目上下文。两个工具都使用相同的格式:一个文件夹,内含 SKILL.md 文件(包含指令和元数据),以及可选的脚本、参考资料、资源文件。当你用 $ 或 /skills 调用时,Codex 会运行一个 skill,或者当你的任务匹配该 skill 的描述时,它会自动运行——这就是为什么一个精准但枯燥的描述胜过花哨的描述。Claude Code 的实现方式相同,我在agent skills(Agent 技能)中记录了这种模式。

Skill(技能)也是让你不必反复支付“意图成本”的地方。我在the intent debt(意图债务)中论证过,agent 每次会话都是从“冷启动”开始,它会用自信的猜测来填补你意图中的任何空白。Skill 就是将意图写在外部:约定、构建步骤、“我们之所以不这样做是因为某次事件”,这些只写一次,但 agent 每次运行都会读取。没有 skill,循环每次都必须从零开始推导你的整个项目;有了 skill,它就能产生累积效应。

有一点需要搞清楚:skill 是编写格式,而 plugin(插件)是你的分发方式。当你想要跨仓库共享一个 skill 或打包几个一起使用时,可以将它们打包成一个 plugin。这在 Codex 和 Claude Code 中都是如此。

插件与连接器 -> 让循环触达工具

一个只能访问文件系统的循环是非常受限的。基于 MCP 构建的连接器,能让 agent 读取你的 issue 追踪器、查询数据库、调用 staging API、在 Slack 中发送消息。Codex 和 Claude Code 都支持 MCP,因此你为一个工具编写的连接器通常可以无缝用于另一个。Plugin(插件)将连接器和 skill 打包在一起,这样你的队友可以一键安装你的整个设置,而不是凭记忆重新构建一切。

这就是一个能说“这是修复方案”的 agent,与一个能自动打开 PR、关联 Linear 工单,并在 CI 通过后自动在频道中发消息的循环之间的区别。连接器是让循环能够在你真实的环境中执行操作,而不仅仅是告诉你它“如果能够”会做什么的关键。

子Agnet -> 让创作者和检查者分离

一个循环中最有用的结构性东西,远超过其他,是分离“编写者”和“检查者”。自己编写代码的模型在给自己打分时会过于宽容。第二个具有不同指令(有时是不同模型)的 agent,能够捕捉到第一个 agent 把自己说服而忽略的问题。

Codex 只在你要求时生成子 agent,它们并行运行,然后将结果合并到一个答案中。你可以在 .codex/agents/ 中以 TOML 文件定义自己的 agent,每个 agent 包含名称、描述、指令,以及可选的模型和推理努力程度(reasoning effort)。这样,你的安全审查者可以是配置了高推理努力度的强大模型,而你的探索者则是一个快速的只读 agent。Claude Code 使用 .claude/agents/ 中的子 agent 和在其间传递工作的 agent 团队实现了相同功能。两个工具中常见的分工是:一个 agent 负责探索,一个负责实现,一个负责对照规范验证。

我已经两次阐述过这个理由,一次是the code agent orchestra(代码 Agent 编排),一次是adversarial code review(对抗式代码审查)。之所以在循环内部它至关重要,是因为循环是在你不监控的时候运行的,一个你真正信任的验证者是你能够放心离开的唯一原因。每个子 agent 都有自己的模型和工具运行,所以确实会消耗更多 token,请在真正需要第二次意见时才使用它们。这基本上也是 Claude Code 的 /goal 在底层做的事:一个全新的模型(而不是执行工作的那个)来决定循环是否完成,将“创作者与检查者分离”应用到了循环停止条件本身。

一个循环具体长什么样

把所有东西组合起来,一个单一的线程就变成了一个小小的控制面板。下面是我一直在使用的一个形态。

一个自动化任务每天早上在仓库上运行。它的 prompt(提示词)调用一个分类 skill(技能),该 skill 读取昨天的 CI 失败记录、待处理的 issue、最近的 commit,并将发现写入一个 markdown 文件或 Linear 看板。对于每个值得处理的问题,该线程会打开一个隔离的 worktree,并派遣一个子 agent 去草拟修复方案,然后第二个子 agent 会对照项目 skill 和现有测试来审查这份草稿。

连接器让循环能够打开 PR 并更新 ticket。所有循环无法处理的事情都会进入我的分类收件箱。状态文件是这一切的核心,它记录了什么尝试过、什么通过了、什么还没处理,这样第二天早上运行就能从今天停止的地方继续。

看看你实际做了什么。你只设计了一次。你没有手动对任何步骤输入 prompt(提示词)。这就是 Steinberger 观点在现实中的体现,而且无论在 Codex 还是 Claude Code 中,这个循环都是相同的,因为其组成部分完全相同。

循环任然无法为你做到的事

循环改变了工作方式,但它不能将你从中移除。而且随着循环越来越好,三个问题实际上会变得更突出,而不是更简单。

验证责任还在你身上。 一个无人值守的循环,也是一个会无人值守地犯错的循环。你将验证子 agent 与创作者分离的全部理由,就是为了让循环声称的“完成”更有意义。即便如此,“完成”也只是一个宣称,而不是一个证明。我一直重复在code review in the age of AI(AI 时代的代码审查)中说过的同一句话:你的工作是将你确认能工作的代码发布上线。

你的理解力仍然会生疏,如果你放任自流的话。 循环将不是你写的代码越快地发布上线,系统存在的内容与你实际理解的内容之间的差距就越大。这就是comprehension debt(理解债务),一个流畅的循环只会加速这种增长,除非你去阅读循环产生的代码。

没错,最舒服的姿势可能也是最危险的姿势。 当循环自我运行时,你很容易停止拥有自己的观点,只是接受它返回的任何东西。我称之为cognitive surrender(认知投降)。当你带着判断力去设计循环时,它是解药;当你设计循环是为了避免思考时,它就是催化剂。同样的操作,相反的结果。

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

我认为这预示着我们未来的工作方式将如何演变。话虽如此,如果我不亲自审查代码,或者如果我完全依赖自动化的循环来修复问题,那么我的产品质量将会下滑。我很可能会陷入一个下降螺旋,不断地挖更深坑来填坑。

尽管如此,请放心去设置你的循环,但别忘了,直接给你的 agent 输入 prompt(提示词)仍然有效。关键在于找到正确的平衡。

循环的结果也可能因你而异。两个人可以构建完全相同的循环,却得到截然相反的结果。一个人用它来在自己深刻理解的工作上加快速度。另一个人则用它来避免理解工作本身。循环并不知道其中的区别。你知道。

这就是为什么循环设计比 prompt engineering(提示词工程)更难,而不是更简单的原因。Cherny 的观点不是说工作变容易了,而是说杠杆点(leverage point)转移了。

构建循环吧。但要像打算继续做一名工程师,而不仅仅是那个按下“开始”按钮的人那样去构建它。

0 条

还没有评论。

发表评论