循环工程(Loop Engineering)落地实施完全指南
前言
仔细阅读了《Loop Engineering: The Anthropic Playbook for Designing Systems That Prompt Your Agents》.
让我更进一步理解了Loop Engineering。其中感触最深的是:
循环使生成变得廉价,而使判断力变得稀缺
that loops make generation cheap and leave judgment scarce).
循环不是一种被工具本身能力固化的工具。它会不加改变地放大你带来的任何东西:带来理解,它就放大理解;带来懒惰,它就放大懒惰。它是一个忠实的乘号,它乘以的是人本身。
A loop is not a tool whose quality is fixed by the tool. It is so strong that it amplifies, unchanged, whatever one brings: bring understanding and it amplifies understanding; bring laziness and it amplifies laziness. It is a faithful multiplication sign, and what it multiplies is the person.
分享出来和大家一起学习。
1. 核心定义
循环工程(Loop Engineering)不是教你如何更好地提示 AI,而是教你如何设计一个能自动提示 AI、自我运转并自我纠错的系统。 它的目的是将人类从“执行者”(在循环内)变为“设计者”(在循环外)。循环并非简单的定时重跑,而是一个能自我发现工作、隔离执行、独立验证、持久记忆并自动调度的闭环系统。
2. 底层基础:六大核心组成部分
这是搭建循环所需的“物理硬件”或基础设施。在实施前,请务必确认您的系统是否具备了这六个“器官”。按从底层保障到上层调度的逻辑排列如下:
| 部件 (Part) | 物理形态 / 实现方式 | 解决什么问题? |
|---|---|---|
| 1. 记忆 | 磁盘上的持久化状态文件(如 state/triage.md 或数据库记录)。 |
对抗失忆:代理的上下文窗口一关就会忘记一切,但磁盘不会。它让循环隔夜还能记得昨天的进度和结论。 |
| 2. 技能 | 项目根目录下的 SKILL.md 文件(存储永久性项目知识)。 |
偿还“意图债务”:不用每天早上一遍遍告诉代理“这个项目是干嘛的、代码规范是什么、陷阱在哪里”。 |
| 3. 连接器 | 基于 MCP 协议的外部接口(连接 Jira、GitHub、Slack、数据库、浏览器)。 | 拓展视野:让循环能看到文件系统之外的世界(读取工单、发送通知、操作网页截图)。 |
| 4. 子代理 | 独立运行的其他 Agent 实例(通常一个负责写代码,一个负责审查)。 | 实现“裁判分离”:防止生成器自我审查时的“灯下黑”。 |
| 5. 工作区 | git worktree 生成的多个独立目录。 |
解决并行冲突:每个任务拥有自己的文件夹,多个代理同时修改代码也不会互相踩踏。 |
| 6. 自动化 | 定时器(Cron)或触发器(Webhook,如 GitHub Actions)。 | 赋予生命:让循环“活”起来,而不是一个需要手动点击运行一次的僵硬脚本。 |
好的,我将为您详细展开五个动作的说明,从设计意图、实施要点到常见反模式逐一拆解,便于您在实际构建循环时能准确落地。
3. 循环的五个动作:详细操作指南
这五个动作不是可选项,而是必须全部安装的强制流程。缺少任何一个,循环就会退化为第五章节所列举的五种失败模式之一。
3.1. 动作一:发现(Discovery)
一句话定义:让代理自行找到“今天该做什么”,而不是人类告诉它。
设计意图:发现是循环的“眼睛”。如果这一步做得不好,后续四个动作再漂亮,也只是在错误的事情上浪费算力。人类的价值不应消耗在“指派任务”上,而应集中在“判断结果是否正确”上。
实施要点:
| 要点 | 具体做法 |
|---|---|
| 触发源 | 读取 CI 失败记录、新提交的 Issue、最近的 Commit、监控告警、收件箱中的未处理请求。 |
| 承载形式 | 将“读什么、怎么判断优先级”封装进 技能(Skill),即 SKILL.md 文件,而非直接粘贴到 Cron 脚本中。 |
| 判断标准 | 对每个候选条目回答三个问题:① 可操作吗(还是噪音)?② 阻塞发布吗(优先级)?③ 已在处理中吗(去重)? |
| 输出格式 | 生成结构化的发现列表(如表格),写入状态文件供下一轮使用。 |
常见反模式(盲目循环):
- ❌ 人类每天早上手动告诉循环“修 Bug #123、#456、#789”。
- ❌ 发现逻辑硬编码在自动化脚本中,导致维护困难。
- ✅ 正确做法:循环自行读取数据源,自主裁定今日工作清单。
检查清单:你的循环是否能在无人干预下,独立输出一份“今天值得做的事情”清单?
3.2. 动作二:移交(Handoff)
一句话定义:将每个发现的任务安全、隔离地移交给执行代理。
设计意图:移交是循环的“手臂”。它的核心目的是隔离。如果多个代理同时修改同一份代码,会产生无法解决的合并冲突。移交的质量决定了并行效率的上限。
实施要点:
| 要点 | 具体做法 |
|---|---|
| 隔离载体 | 每个任务使用独立的 git worktree(工作区),即 claude --worktree fix/<slug>。 |
| 任务粒度 | 每个工作区只负责一个原子性任务(如“修复登录超时”),不要将多个不相关修复塞进同一个工作区。 |
| 启动参数 | 每个工作区启动时带入该任务专属的上下文(相关文件路径、预期目标、停止条件)。 |
| 清理机制 | 任务完成后自动归档或删除工作区,避免磁盘膨胀。 |
常见反模式(混乱循环):
- ❌ 五个代理同时修改同一个目录,编辑相互覆盖,合并时一团乱麻。
- ❌ 任务粒度太粗(一个工作区修了三个不相关的 Bug),导致验证和回滚困难。
- ✅ 正确做法:每个任务独立工作区,互不干扰;每个工作区只做一件事。
检查清单:你的循环是否能在并行运行5个代理时,依然保持代码库整洁、无冲突?
3.3. 动作三:验证(Verification)
一句话定义:用独立的、持怀疑态度的另一个代理来检查生成器的输出,能说“不”。
设计意图:验证是循环的“刹车片”和“良心”。这是五个动作中最关键也最容易被跳过的一个。经验证明,生成器审查自己的代码会不自觉地自我表扬(“看起来没问题”)。验证的本质是引入对抗性视角,打破生成器的“自我说服链”。
实施要点:
| 要点 | 具体做法 |
|---|---|
| 角色分离 | 评估器必须是独立的子代理,与生成器使用不同的系统指令(System Prompt),甚至不同的底层模型。 |
| 验证方式:行动而非阅读 | 评估器不能只看代码文本。它必须实际执行:跑测试、启动页面、点击按钮、截图、检查 DOM。评判的基准是“它跑得对吗?”,而非“它看起来对吗?”。 |
| 默认立场 | 评估器的默认态度是 “假定代码是坏的,直到被证明是好的”。持怀疑态度是它的第一天职。 |
| 停止条件(/goal) | 使用 /goal 命令设定明确的成功标准(如“所有测试通过且 lint 干净”),并由第三个全新模型来裁决是否达成,而非生成器自己说了算。 |
| 制造者-检查者原则 | 源自银行业的“双人复核”原则:写代码的人和审核代码的人不能是同一个。 |
常见反模式(点头循环):
- ❌ 生成器写完代码后,调用
go test看到全绿就宣称“验证通过”。 - ❌ 让同一个代理既写代码又做 Code Review。
- ❌ 评估器仅凭肉眼阅读代码,从不实际运行。
- ✅ 正确做法:换入一个独立代理,让它实际运行你的应用(如用 Playwright 点按钮),凭事实证据下结论。
检查清单:你的循环是否曾经对任意一个输出说过“不”?如果几百轮以来它从来没有拒绝过任何东西,那你的验证环节可能根本不存在。
3.4. 动作四:持久化(Persistence)
一句话定义:将本轮的状态、结论、产出物保存到对话之外的持久存储中。
设计意图:持久化是循环的“记忆硬盘”。代理的上下文窗口一刷新就失忆,如果结果只活在聊天记录里,循环就永远在原地打转。持久化让循环具备累积性——今天的结论是明天的基础。
实施要点:
| 要点 | 具体做法 |
|---|---|
| 状态文件 | 将每个发现及其处理进度写入 ./state/triage.md 或类似的 Markdown / JSON 文件。 |
| 外部同步 | 通过连接器(Connector)自动更新 Jira 工单状态、创建 GitHub PR、向 Slack 发送通知。 |
| 提交回仓库 | 状态文件应被 git 跟踪并提交,确保跨日、跨机器可读。 |
| 记忆 ≠ 上下文 | 清晰区分两者:上下文是代理本轮看到的、用完即清的数据;记忆是磁盘上永久保存的、跨轮次存续的状态。 |
常见反模式(健忘循环):
- ❌ 把所有结论只写在聊天窗口里,第二天刷新后一切归零。
- ❌ 状态文件只存在于本地,没有提交到仓库,云端调度器读取不到。
- ✅ 正确做法:每轮结束前,将关键发现、已完成项、待办项、阻碍项全部写入磁盘并提交。
检查清单:你的循环是否能在你合上电脑一周后重新开机时,准确记得上周干到哪一步了?
3.5. 动作五:调度(Scheduling)
一句话定义:让循环“活”起来——按定时或事件自动触发下一轮,无需人类点击“运行”。
设计意图:调度是循环的“心脏起搏器”。没有调度,你拥有的只是一份写得不错的脚本,需要你手动拉绳才能动一下。调度让循环从“工具”变成“员工”。
实施要点:
| 要点 | 具体做法 |
|---|---|
| 本地调度 | 使用 /loop 命令(如 /loop 5m check deploy),适合需要高频(分钟级)访问本地文件的场景。代价:机器必须保持开机且会话打开。 |
| 云端调度 | 使用 GitHub Actions cron(如 0 6 * * *)或 Cloud Routines。适合真正“睡觉时运行”的场景。代价:最小间隔通常 1 小时,且每次全新克隆,看不到本地进程。 |
| 触发形式 | 除定时外,也可通过事件触发(如 @机器人的 Slack 消息、Emoji 反应、Webhook)。 |
| 调度载体 | 调度器应调用技能(claude --skill),而非一大段脚本,以便维护和复用。 |
| 混合模式 | 成熟循环通常两者兼用:本地做高频内测(如每分钟检查 dev server),云端做夜间清扫(如凌晨三点扫描全库)。 |
常见反模式(手动循环):
- ❌ 循环跑得再好,但人类忘了点“运行”,它就安静地躺平。
- ❌ 把本地
/loop当成“无人的云端作业”,一关机就傻眼。 - ✅ 正确做法:根据任务性质选择合适的调度器——本地高频率,云端真自主。
检查清单:你的循环能否在你休假一周、电脑关机的情况下,每天依然自动运行并产出成果?
4. 运行机制:五个动作如何在六大部件上实施
有了上面的“基础设施”,循环运转时的 5 个动作 就不再是抽象的概念,而是对 6 个部件 的具体调用和组合。
| 动作 (Moves) | 动作目标 | 依赖哪些部件实施? | 具体实施逻辑(如何调用部件) |
|---|---|---|---|
| 1. 发现 (找活干) |
让系统自动判断今天该修什么 Bug,而非人告诉它。 | 技能 + 连接器 | 自动化触发 技能(SKILL.md);技能指示代理使用 连接器 去读取 CI 失败日志、Jira 工单和 Git 提交记录。 |
| 2. 移交 (分配任务) |
把发现的任务安全地派发给“工人”代理。 | 工作区 | 为每个发现的任务,利用 git worktree 创建一个独立的工作区。保证每个代理只在自己的目录里改代码。 |
| 3. 验证 (质量把控) |
确保代码正确,杜绝自我陶醉。 | 子代理 + 连接器 | 生成器写完代码后,换入另一个子代理(评估器);评估器通过连接器实际运行测试或打开浏览器截图,凭事实判断而非凭感觉阅读。 |
| 4. 持久化 (存档记忆) |
将结果和状态记下来,防止刷新丢失。 | 记忆 + 连接器 | 将进度和结论写入磁盘 记忆(Markdown文件);通过连接器自动更新工单状态、创建 PR,同步到外部系统。 |
| 5. 调度 (闭环循环) |
让整个流程在无人干预下自动进入下一轮。 | 自动化 | 自动化(如 Cron)作为总开关。本轮结束后,由它决定何时触发下一轮的“发现”动作。 |
5. 开箱即用:最小可行的循环工程样例
这是论文提供的“麻雀虽小,五脏俱全”的完整骨架。您可以直接复制此模板启动您的第一个循环。
# 1. 调度 (Scheduling) -- 依赖【自动化】部件
# 文件: .github/workflows/triage.yml
on:
schedule:
- cron: '0 6 * * *' # 每天早上6点(云端)运行
jobs:
triage:
runs-on: ubuntu-latest
steps:
# 2. 发现 (Discovery) -- 依赖【技能】+【连接器】部件
- name: 读取CI失败和待处理Issue
run: claude --skill morning-triage
# 3. 持久化 (Persistence) -- 依赖【记忆】部件
# 技能会自动写入 ./state/triage.md 并提交回仓库
# 4. 移交 (Handoff) + 验证 (Verification)
# 依赖【工作区】+【子代理】部件
- name: 并行修复
run: |
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. 人工审核 (Human Review) -- 最后的防线
# 注意:PR是打开的,但【绝不自动合并】,不确定的放入 ./inbox/
您必须自定义的部分:
- 技能文件 (
.claude/skills/morning-triage/SKILL.md):告诉代理去读哪些 CI 日志、哪些 Issue,以及如何判断优先级。 - 状态文件 (
./state/triage.md):记录上一轮发现了什么,处理到了哪一步。
5.1. 启动顺序建议
论文明确建议:不要一上来就追求“五个全装 + 大规模并行”。安全的成长路径是:
| 阶段 | 实施内容 | 目标 |
|---|---|---|
| 第1周 | 调度 + 发现 + 持久化 | 先让循环能每天早上自动读 CI、写状态文件,证明“它能找到活”。 |
| 第2周 | 添加验证(评估器 + /goal) | 最关键的一步。先不要开并行,用单任务证明“它能对坏输出说‘不’”。 |
| 第3周 | 添加移交(工作区) | 在验证已可靠的前提下,开启多任务并行。 |
| 长期 | 调优评估器的判断标准 | 不断强化“刹车片”,这是最值得投入精力的地方。 |
核心原则:先证明它能停住,再让它跑起来。 一个不会拒绝的循环,跑得越快,离灾难越近。
6. 避坑指南:对 Loop Engineering 的 5 大常见错误理解
在实际操作中,您的循环并不一定会因为代码写得好而成功,反而会因为观念上的偏差而失败。以下是论文指出的五个致命误区:
| 错误理解(误区) | 导致的结果(反模式) | 正确理解与解法 |
|---|---|---|
| 误区1:验证就是加个单元测试 | “点头循环”:代理写完代码自己跑一遍测试就说“没问题”。结果累积了一堆测试通过但实际逻辑错误的垃圾代码。 | 验证必须“换人”:必须用另一个独立子代理,且让它实际运行行为(如 Playwright 截图检查 UI),而非仅凭阅读代码。 |
| 误区2:循环跑起来就行,结果不重要 | “健忘循环”:结果只存在聊天窗口,窗口一关,第二天循环忘了昨天干了啥,从头再来。 | 记忆必须持久化:所有结论必须写入磁盘文件(Markdown/数据库)。代理会忘,但仓库(Git)不会。 |
误区3:本地 /loop 就是“睡觉时运行” |
“手动循环”:合上笔记本盖子,循环就停了。你以为它在云端跑,其实它在等你开机。 | 区分本地与云端:本地适合高频短任务(需开机);云端适合夜间长跑(如 GitHub Actions),但云端通常看不到本地文件且间隔 >1 小时。 |
| 误区4:找活干也是人的事 | “盲目循环”:循环只负责写代码,但每天做什么活还是人脑决定。省了手脚,没省大脑。 | 必须自动化“发现”:让代理自己去读 CI 报告、新 Issue 来决定今天修什么,而不是人类告诉它“修 Bug #123”。 |
| 误区5:循环做决策,我当甩手掌柜 | “认知投降”:因为循环太靠谱,你放弃了思考,看不懂它改的代码。出大故障时,你完全失控。 | 永远留一扇门:设置人工检查点(如绝不自动合并 PR)。循环是放大镜,放大你的判断力,也放大你的懒惰。 |
7. 终极准则:两条必须遵守的“黄金铁律”
-
生成器与评估器必须分离。
这是循环的“刹车片”。如果没有独立的评估器(即另一个子代理),您的循环就是一台没有刹车的跑车。先证明它能停住一个坏的结果,再放手让它去跑一百个好结果。 -
永远不要移除人工审核点,并设置预算上限。
在运行前设置每日 Token 上限和最大重试次数,防止一个死循环 Bug 烧光账户余额。同时,永远不要删除检查点(如要求人工点击合并 PR)。那个检查点,是您保持工程师控制权、避免被机器“架空”的最后一道门。
- 点赞
- 收藏
- 关注作者
评论(0)