Skip to main content

循环工程:速成课

15 个概念 · 从 agentic coding 到自提示系统

你已经学会了如何驾驭 coding agent。你给出指令,它读取文件、完成修改,然后由你检查结果。做完一轮,再做下一轮,如此继续。工具始终握在你手中。

现在想象一下,你不再一直握着它,而是构建一个小系统。每天早上,系统会自行启动,查看夜间发生了哪些变化,判断什么值得处理,把每项工作交给 agent,检查结果,并且只在真正需要人做决定时才来找你。你只构建一次,之后它会自行发出提示。

这就是循环工程。有价值的技能,从你写出的提示词转移到你设计的循环。本课会讲清循环由什么组成,以及如何分别在 Claude CodeOpenCode 中构建循环。两种工具走的是截然不同的路,却会到达同一个地方。

前置要求:Claude Code 与 OpenCode:速成课 那门课讲过计划模式、上下文管理、规则文件、技能、子 agent 和 MCP。本课默认你已经掌握这些内容。如果这些词对你还很陌生,请先完成那门课。循环工程直接建立在它之上。最好也完成过 Spec-Driven Development:循环的停止条件本质上是一份 spec,而那门课教你如何写好它。没有它,你仍然可以继续学习,但循环的质量最终取决于你能否准确写出条件。

第一次接触这些内容?用 2 分钟回顾你应该已经知道的知识
  • 计划模式:agent 先读取文件并提出计划,在你批准后才修改内容
  • 规则文件CLAUDE.md / AGENTS.md):简短、长期有效的项目说明,agent 会在每次会话开始时读取
  • 技能SKILL.md):保存起来、可重复使用的指令,只有任务匹配时 agent 才会加载
  • 子 agent:拥有独立上下文窗口的辅助 agent,完成一项工作后只把结果交回来
  • 连接器 / MCP:把 agent 接入外部工具的标准方式,例如 GitHub、Slack 或数据库
  • 上下文管理:保持对话精简;上下文越满,模型表现越差,成本也越高

如果其中任何一项对你来说是新的,请先完成 agentic coding 速成课。本课直接建立在它之上。

这个想法从何而来

到 2026 年年中,构建这些工具的人已经把话说得很直白。Claude Code 的创建者 Boris Cherny 这样描述:「I don't prompt Claude anymore. I have loops running that prompt Claude... my job is to write loops.」Peter Steinberger(OpenClaw)则说:「you should be designing loops that prompt your agents.」随后,Addy Osmani 为这种模式命名,并列出了它的组成部分。他们没有说工作变轻松了,而是说有价值的技能转移了。整门课都建立在这个观点上。(本课中的引文和论断都在结尾的 来源与延伸阅读 中列出出处。)

用一幅图看懂思维转变

左侧:逐轮提示。你输入,agent 回复,你阅读,再次输入,永远重复;工具始终握在你手中。右侧:循环。发现、实施、验证、提交构成一个自行发出提示的周期;你坐在人工关口,只审批高风险决定。图注:杠杆点从提示词转移到循环。

本课同时讲解两种工具,原因和上一门课相同:如果一项技术在两种工具中都能用,它就是一项真正的技能,而不是某个工具的窍门。 不过,这两种工具在这里确实不同,这种差异本身就是一课。Claude Code 现在把循环组件直接内置在产品里。OpenCode 提供的是更底层的一层,也就是一个由操作系统启动的工作者。你会看到两种方式,也会看到,即使接线方式不同,循环的结构仍然相同。

截至 2026 年 6 月为最新内容。这两种工具变化很快,Claude Code 的多项循环功能仍处于研究预览阶段。每次使用前,请运行 claude updateopencode upgrade。在依赖某个限制或参数前,先查看实时文档(code.claude.com/docsopencode.ai/docs)。

先诚实说明循环可以在哪里运行

真正的循环是无人值守的:你离开时,它会自行向自己发出提示。普通的 claude.ai 聊天框无法做到这一点,因为它始终在等你。在聊天中,就是调度器。要让真正的循环按计时器自行运行,需要能做到这一点的工具:Claude CodeOpenCodeCowork(参见 Cowork 速成课)。其中大多数是付费功能,目前也有多项处于研究预览阶段。你可以在任何地方学习和设计循环;要让它无人值守地运行,则需要上述工具之一。本课会讲两种 coding 工具。

「可我是在 claude.ai 中完成整门 Spec-Driven 课程的,也能在那里运行循环吗?」

这是个合理的问题,因为「claude.ai」实际上指两样东西。简短回答是:聊天不能运行循环,但同一个 claude.ai 账号中的 Claude Code 可以。

  • 聊天对话每一轮都在等你,无法按计划或事件自动触发。你可以手动反复提示,但这样一来,就是心跳,而循环要移除的正是这份工作
  • Claude Code 可以用同一个账号访问。它的云端 Routines(在 claude.ai/code/routines 创建)运行在 Anthropic 的服务器上,即使笔记本电脑已经关机、当地没有安装任何东西也能运行。因此,从这个意义上说,你确实可以「从 claude.ai」建立真正的无人值守循环。目前它需要付费套餐,并处于研究预览阶段
  • OpenCode 借助你自己的调度器(cron、GitHub Actions)实现同样的效果

因此,聊天适合设计和排练循环:起草技能、编写审查提示、固定停止条件、手动跑一轮。Claude Code 或 OpenCode 则负责运行循环。这正是完成 Spec-Driven Development 之后自然的下一步。

边读边试

从这里开始,几乎每个概念都可以在真实会话中运行,而不只是阅读。请在页面旁边打开一个终端(claudeopencode),学到一个概念就试一次。先用一个小型、可丢弃的 Git 仓库,这样循环就不会伤及你在意的内容。

本课涵盖什么

部分主题你会学到什么
1转变循环是什么、它的 6 个部分,以及构建循环的两条道路
2心跳让系统自行运行:会话内、运行到完成、定时、事件驱动
3主体隔离、知识、行动,以及执行者–检查者拆分
4脊柱能在多次运行之间保留下来的状态,也是人们最容易忘记的部分
5同一个循环,两种实现一个从晨间分流到 PR 的完整循环,使用真实文件在两种工具中分别构建
6继续做工程师token 成本、检查工作,以及随着循环变强而越来越严重的陷阱
练习练习项目由易到难,亲手构建 5 个循环

喜欢边做边学? 先阅读 第 5 部分,从头到尾看一遍完整循环,再回来理解各个组件。概念理解之后,请用 练习项目 亲手构建 5 个循环。

完整阅读约需两小时。完成第 5 部分和练习项目需要更久,这正是重点:你要构建循环,而不是走马观花。

哪些要记住,哪些要随用随查

本课贯穿着两个层次,而它们的寿命差异很大。内化第一层,查阅第二层。

  • 持久层。 循环的结构(一个心跳、4 个工作组件和一条脊柱)、执行者–检查者拆分,以及循环永远无法自动化的两个端点:意图(把你想要的结果说得足够准确,从而能够检查)和责任(对交付的内容负责)。这才是技能。无论下面的命令如何变化,它都成立
  • 机械层。 每个参数、路径、模型 ID 和命令名。这些工具每周都在更新,其中多项功能仍处于研究预览阶段。因此,请把每条具体命令当作实时文档的入口,而不是必须背下来的事实。如果本课与最新文档不一致,以文档为准

记住由 6 个部分组成的结构,忘掉每次按键,你就学会了循环工程。背下按键却错过结构,你学到的只是本月的 CLI。


📚 教学辅助

打开完整幻灯片

查看完整演示:循环工程速成课


第 1 部分:转变

1. 从提示到循环

过去大约两年里,从 coding agent 那里获得工作的方式很简单:写好提示词,给它足够的上下文,阅读返回的内容,再输入下一条指令。agent 是一种工具,你每次只使用一轮。

循环用系统取代了作为操作者的你。系统发现工作、分配工作、检查工作、记录所做的事,并决定下一步。它替你向 agent 发出提示。

那么,价值去了哪里?它没有消失,而是分到了循环无法自动化的两个端点:意图,也就是准确说明你想要什么,让结果可以被检查;以及责任,也就是为最终产出负责。循环自动化的是中间的步骤,两个端点仍属于你。你获得回报,是因为你能表达意图并作出判断,而不是因为你忽略了工作是如何完成的。

区别并不是「更大的提示词」,而是一种不同的工作结构:

提示(你已经熟悉的方式)循环(本课新增的方式)
你启动每一轮计划或事件启动每一轮
你阅读输出并决定下一步检查者检查输出,循环决定下一步
你停止输入时,它立刻停止你睡觉时,它仍会继续运行
一项任务、一次会话、占用你的全部注意力多次小型运行,大多无人值守,只在关口需要你的注意力

这不是魔法,也不是「设置好后就不用管」。 循环自行运行,也意味着它会自行犯错。本课的全部内容,都是为了构建一个你真正敢于放手运行的循环。这比提示更难,而不是更简单。回报是杠杆效应:一个设计良好的循环会反复替你工作,完成原本每次都得由你手动启动的任务。

2. 循环由什么组成

真正能自行运行的循环有 5 个部分和 1 条脊柱。其中 4 个部分已经在 agentic coding 课程中出现过,现在它们有了新的职责。

循环的组成。顶部并排 5 张能力卡:1 心跳,触发循环的计划;2 工作树,用隔离防止并行 agent 冲突;3 技能,只写一次的项目知识;4 子 agent,一个编写、另一个检查;5 通过 MCP 使用连接器,访问真实工具。下方贯穿着第 6 个元素:状态/记忆脊柱。模型会在每次运行中读写磁盘上的文件,因为模型会忘记不同运行之间的内容,而仓库不会。末端的人工关口把安全工作送去提交,把高风险决定送回给你。

  1. 心跳:启动循环的计划(或事件)。没有它,你拥有的只是一次运行,不是循环
  2. 工作树:提供隔离,让两个同时工作的 agent 不会覆盖彼此的文件
  3. 技能:只写一次的项目知识,让每次运行都不必从零开始
  4. 子 agent:执行者–检查者拆分。编写代码的 agent 不能同时负责给代码评分
  5. 连接器(MCP):让循环能在真实工具中采取行动(打开 PR、更新工单),而不只是提出建议

还有第 6 个部分,初学者最容易跳过:

  1. 状态 / 记忆,也就是脊柱。 磁盘上的文件(或 Linear 一类看板)保存已经完成和接下来要做的工作。模型会忘记不同运行之间的一切。脊柱让今天的运行知道昨天做过什么。没有脊柱,就没有循环,只会永远重复相同的第一步。

本课后面的每一节都会讲解一个组件,最后再用一个完整示例把它们连接起来。

3. 两条道路:内置组件与更底层的一层

这是两种工具真正不同的地方,也会塑造后面的全部内容。

通往同一种循环的两条路径。左侧,Claude Code 内置原语:slash-loop、slash-goal、Routines、claude -p、hooks、Channels、.claude/agents 和 --worktree;调度器、验证评分器和隔离都已内置,云端 Routines 即使在笔记本关闭时也能运行。右侧,OpenCode 提供更底层的一层:opencode run、serve 加 --attach、cron/launchd/Task Scheduler、GitHub Actions、自定义 agent 和 --format json;OpenCode 是工作者,你自行提供调度器,以操作系统或 GitHub 作为心跳。接线更多,控制也更多,而且不需要厂商云。底部文字:学习循环,而不是快捷键。

Claude Code 把循环组件内置在产品里。 心跳(/loop/schedule、云端 Routines)、带内置检查者的运行到完成(/goal)、隔离(--worktree)和事件输入(Channels)现在都是内置命令。一年前,你需要编写并维护一堆 shell 脚本才能实现这些功能;如今大多只需完成配置。

最重要的是 Routines:运行在 Anthropic 服务器上的云自动化,即使笔记本已经关闭也会继续运行,可由计划、API 调用或 GitHub 事件启动。便利的代价是账号级每日运行上限(请在 Routines 使用量界面查看当前上限,不要依赖固定数字),以及 Routines 仍处于研究预览阶段,未来可能变化。

OpenCode 提供更底层的一层。 它没有内置云调度器。OpenCode 是你调用的工作者,而心跳由你从操作系统或 CI 提供。

关键命令是 opencode run "<prompt>"。它不打开聊天界面,只运行一条提示,打印结果,然后退出。这条命令就是循环的一次心跳。要把它变成循环,可以用按计时器触发的东西包住它:cronlaunchd(macOS 和 Linux)、Task Scheduler(Windows),或带计划触发器的 GitHub Actions。这需要更多接线,但你能完全控制系统,可以使用已有机器运行,也不需要厂商云。

技能在于循环,而不是快捷键

请注意,两个标签页描述的是相同的 5 个部分。无论心跳是托管的 Routine,还是 cron 中的一行命令,心跳就是心跳。无论由 /goal 评分,还是由第二次 opencode run 完成,执行者–检查者拆分仍是同一个想法。只需学会一次循环的结构,就可以迁移。 这正是我们同时教授两种工具的原因。

我们将要到达的地方(先看完整循环)

在拆解各个组件之前,先看终点。你将在 第 5 部分 构建的循环只有 6 个朴素步骤:

every weekday at 9am:                 # 1. Heartbeat
read progress.md # 6. Spine (memory)
find overnight CI failures + issues # what to work on
for each one:
draft a fix in its own checkout # 2. Worktree
using the project's triage skill # 3. Skill
have a separate reviewer grade it # 4. Sub-agents (maker/checker)
if PASS: open a PR via GitHub # 5. Connector (MCP)
if risky: write it to progress.md and leave it for a human
update progress.md # 6. Spine again

请记住这幅图。第 2–4 部分的每个概念,都是其中一行。

检查一下自己

一个循环每天早上运行,但每次都从全新状态开始,完全不记得昨天做过什么。它缺少 6 个部分中的哪一个?为什么这会破坏循环?

查看答案

缺少的是脊柱(状态 / 记忆)。模型会忘记不同运行之间的一切,因此如果磁盘上没有状态文件,循环只会永远重复第一步,而无法承接昨天的工作。


第 2 部分:心跳

心跳把一次运行变成循环。心跳有 4 种,从「只在当前会话中持续」到「完全不需要你也能运行」。请按顺序学习,因为多数真实循环都会使用后两种。

4 种心跳类型,沿着「由你握住」到「无需你也能运行」的光谱排列:会话内循环(/loop 或 while 循环)会在会话关闭时停止;运行到完成(/goal)会反复运行,直到经过检查的条件成立;定时心跳(Routines、cron、GitHub Actions)按时钟运行,笔记本关闭也不受影响;事件驱动心跳(Channels、webhooks)会在事件发生时立即响应。

4. 会话内循环(你看着它重复)

最简单的心跳:在会话保持打开时,按计时器重复运行提示。它适合「监视这件事,直到完成」的任务,例如部署、长时间测试或 CI 作业。

使用内置的 /loop 技能,提供时间间隔和提示:

/loop 5m check if the deployment finished and tell me what happened

Claude 会把时间间隔转换成计划,为任务分配一个 ID,并在会话保持打开时每 5 分钟运行一次提示。完成后,取消任务并继续处理其他工作。

需要知道的一项限制: /loop 有意只存在于会话内部。关闭终端或让笔记本进入睡眠,它就会停止。这是安全功能,不是 bug,因为随手启动的会话内循环不应该比会话活得更久。需要持续运行时,请使用定时任务或 Routine(概念 6)。

OpenCode 没有 /loop 命令,需要自己用 shell 构建计时器。由于 opencode run 会在运行一条提示后退出,因此包含 sleepwhile 循环可以实现同样的效果:

while true; do
opencode run "check if the deployment finished; if it did, say DONE"
sleep 300 # 5 minutes
done

这与 /loop 是同一个想法,只是低了一层:shell 是心跳,opencode run 是每一次搏动。每次全新的 opencode run 都会先启动完整运行时,包括配置、模型、插件和所有 MCP 服务器,然后才执行工作。为了避免每次搏动都支付这份启动成本,可以先启动一次服务器,再连接到它:

opencode serve --port 4096 &
# then, each beat:
opencode run --attach http://localhost:4096 "check the deploy status"

5. 运行到完成(由循环决定何时停止)

固定计时循环有意保持简单,无论发生什么都运行 N 次。很多时候,你真正想要的是**「一直做,直到这个条件成立」**。执行者–检查者的思想第一次在这里出现:不能让完成工作的 agent 自己决定工作是否完成。

使用 /goal。你要提供一个 Claude 能在自身输出中证明的停止条件,也就是它可以通过运行命令并展示结果来证明的事情,例如「test/auth 中的全部测试通过」。它会跨多轮持续工作,直到条件成立。关键在于:每轮之后,一个独立、更小的模型(默认是 Haiku)会读取记录并判断「完成了吗?」 因此,编写代码的 agent 不会给自己的工作评分。还要注意一个细节:检查者不会亲自运行命令,只会判断 Claude 已经展示的内容。因此,条件必须能由 Claude 自己的输出证明,而不能是只有某条未展示命令才知道的私密事实。

/goal All tests in test/auth pass and `npm run lint` is clean.

它会编辑代码、运行测试、读取失败信息、再次尝试,直到检查者确认条件确实成立,或你用 /goal clear 手动停止。系统没有内置的「尝试 N 次后放弃」。如果需要上限,请把它写进条件(…or stop after 20 turns)。条件应当能由命令证明,例如「测试通过且 lint 干净」,而不是「认证代码写得好」。Spec-Driven Development 在这里发挥价值:验收标准本来就是命令可以证明的条件,因此一份好 spec 会直接提供停止条件。

OpenCode 没有 /goal,所以要用 shell 和退出码构建同样的执行者–检查者停止机制。模式是:agent 完成工作,然后由一条真实命令(不是 agent)决定是否停止。

for i in $(seq 1 8); do          # cap the tries — never loop forever
opencode run "Make the tests in test/auth pass and fix any lint errors."
if npm test -- test/auth && npm run lint; then
echo "Condition met on try $i"; break
fi
done

这里,测试运行器和 linter 就是检查者。这是最诚实的检查者,因为命令无法说服自己「工作已经没问题」。要做更智能的检查,可以使用专门的审查 agent 再运行一次 opencode run,让它输出 PASSFAIL。一定要限制尝试次数;没有上限的重试循环,会让 token 账单失去控制。

始终给循环一条停止路径

永远需要两种停止条件:一个成功条件(工作已完成)和一个上限(最大尝试次数、分钟数或支出)。只有成功条件、没有上限的循环,可能会耗尽全部 token 预算,去追逐一个永远无法满足的目标。

6. 无人值守的计划(你睡觉时也运行)

这种心跳让循环工程真正有了意义:一项任务无论你是否在电脑旁都会运行。「每个工作日上午 9 点,整理夜间的 CI 失败。」「每周一检查依赖,并为安全修复打开 PR。」

根据是否需要笔记本开机,有两种方式:

云端 Routines(笔记本可以关机)。 这是现代的默认选择。在 claude.ai/code/routines、Desktop 应用或 CLI 的 /schedule 中创建,三者都会写入同一个云账号。Routine 把提示、可访问的仓库、连接器和触发器(计划、API 或 GitHub 事件)捆在一起,然后在 Anthropic 的服务器上运行。请注意账号级每日运行上限。默认情况下,Routine 只能推送到以 claude/ 开头的分支。这是一项有意设计的护栏,可以在每个仓库的 Allow unrestricted branch pushes 设置中解除。

在自己的 cron 中无界面单次运行(笔记本需要开机,不使用 Anthropic 云)。 claude -p 运行一条提示后退出,可以直接放入 crontab:

# every weekday at 9am: sort through CI and summarize failures
0 9 * * 1-5 cd /path/to/repo && claude -p "check the CI dashboard and summarize any failures" >> ~/claude-cron.log 2>&1

完整说明请参阅本书的 定时任务:Loop Skill 与 Cron 工具

OpenCode 的无人值守心跳始终来自操作系统或 CI,这正是 OpenCode 的路线。使用不带聊天界面的 opencode run,让调度器负责触发。

在自己的机器上使用 cron:

# every weekday at 9am: sort through CI and summarize failures
0 9 * * 1-5 cd /path/to/repo && opencode run "check the CI dashboard and summarize any failures" >> ~/opencode-cron.log 2>&1

在云端使用 GitHub Actions,这样你的任何机器都不必保持开机。下面的 model 字符串仅作示例,请运行 opencode models 查看当前安装认识的准确 ID:

name: Scheduled OpenCode Task
on:
schedule:
- cron: "0 9 * * 1-5" # weekdays at 9am UTC
jobs:
opencode:
runs-on: ubuntu-latest
permissions: { contents: write, pull-requests: write, issues: write }
steps:
- uses: actions/checkout@v6
with: { persist-credentials: false }
- uses: anomalyco/opencode/github@latest
env: { ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }} }
with:
model: anthropic/claude-sonnet-4-6 # confirm with `opencode models`
prompt: |
Review the codebase for TODO comments and summarize them.
If any are worth acting on, open an issue to track them.

定时事件必须提供 prompt,因为没有评论可以充当指令。如果循环要创建分支或 PR,还必须授予 contents: write / pull-requests: write 权限。

关于上面 Action 和模型名称的说明

当前官方文档把 OpenCode GitHub Action 写作 anomalyco/opencode/github@latest;部分旧指南仍使用 sst/opencode/github@latest。两者指向同一个项目,请使用 opencode github install 生成的版本。模型方面,anthropic/claude-sonnet-4-6 是当前 Sonnet ID。从 4.6 代开始采用无日期 ID,其中无日期字符串本身就是固定快照;较早的 4.5 代模型,例如 Haiku 4.5,既有带日期的规范 ID(claude-haiku-4-5-20251001),也有指向最新快照的无日期别名 claude-haiku-4-5。下面的示例为了可复现性固定使用带日期的 Haiku ID。请运行 opencode models 查看当前安装认识的准确字符串。

7. 事件驱动(事件发生时立即响应)

计划问的是**「每小时检查一次」。事件问的是「X 发生时立刻响应」**。PR 打开、issue 创建或消息到达时,循环立即运行。

有两条路径。Routines 接受 GitHub webhook 触发器,因此可以在 push 或新 PR 发生时运行,而不只是按时钟运行。对于聊天类事件,Channels 会把来自外部来源的消息(内置支持 Telegram、Discord 和 iMessage;webhook 接收器需要自行接线)直接推入正在运行的会话。它是调度的事件驱动搭档。参见 code.claude.com/docs/en/channels

运行一次 opencode github install 安装 GitHub agent,它会添加 .github/workflows/opencode.yml。此后,OpenCode 会响应仓库事件,包括 pull_requestissues,以及 /oc/opencode 评论,并在 GitHub Actions runner 中运行:

name: opencode-review
on:
pull_request:
types: [opened, synchronize, reopened, ready_for_review]
jobs:
review:
runs-on: ubuntu-latest
permissions: { contents: read, pull-requests: read }
steps:
- uses: actions/checkout@v6
with: { persist-credentials: false }
- uses: anomalyco/opencode/github@latest
env:
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
model: anthropic/claude-sonnet-4-6
use_github_token: true
prompt: |
Review this pull request for bugs, quality issues, and security risks.

对于没有提示的 pull_request 事件,OpenCode 默认会审查 PR。

检查一下自己

你希望循环不断修复一个失败的测试,直到它通过,然后自行停止。应该使用哪种心跳?由谁判断「完成」?

查看答案

使用运行到完成:在 Claude Code 中是 /goal,在 OpenCode 中是有上限的 shell 循环。必须由一条命令(测试运行器)判断「完成」,绝不能由编写修复的 agent 自己判断;同时还要设置上限,防止无限重试。


第 3 部分:主体

心跳启动循环,下面 4 个部分则决定循环在每次搏动中做什么。在 agentic coding 课程里,它们只是方便的附加能力。在循环中,它们至关重要,因为没有人会盯着每一步。

8. 隔离:工作树

只要循环同时运行多个 agent,它们就会开始覆盖彼此的文件,就像两个人不打招呼地同时编辑相同的行。Git 工作树可以解决这个问题:它是一个独立工作文件夹,位于自己的分支上,同时共享同一份仓库历史。一个 agent 的修改无法碰到另一个 agent 的检出目录。

这项功能已经内置。使用 --worktree 参数可以在独立检出目录中打开会话;为子 agent 设置 isolation: worktree,则每个辅助 agent 都会获得全新检出目录,并在完成后自动清理。定时任务可以为每次运行启用工作树隔离,让并行运行永远不会与你手动进行的工作冲突。

没有单一参数。需要使用 Git 自己的工作树,并把每次运行指向对应目录。同样的隔离,只是明确写了出来:

git worktree add ../wt-feature-a feature-a
git worktree add ../wt-feature-b feature-b
( cd ../wt-feature-a && opencode run "implement feature A" ) &
( cd ../wt-feature-b && opencode run "implement feature B" ) &
wait

如果经常这样做,可以使用社区 runner,也就是围绕 OpenCode 构建的工作树管理器,代为处理这些事务。

9. 知识:用技能避免每次运行都是「第一天」

循环每次都从冷启动开始,它面对的是一个全新会话,对项目习惯毫无记忆。没有帮助时,它会在每次搏动中重新推断(或猜测)整个设置,浪费 token,也更容易犯错。技能就是只写一次的知识,保存在 SKILL.md 文件中,由 agent 在每次运行时读取。

这在两种工具中的工作方式相同:一个带有 SKILL.md 指令和元数据的文件夹,还可选带脚本和参考资料。在循环中,规则很简单:凡是你原本需要每次运行都重新解释的内容,都应该放进技能。 分流步骤、项目习惯,以及「因为某次事故,所以我们不这样做」的经验,都放在技能中。这样,循环会不断积累,而不是每次重启。(完整说明见 技能与连接器速成课。)

技能让循环提示保持精简

不要把一堵没人维护的指令墙粘进计划。定时提示可以缩成一句:「运行 daily-triage 技能」,详细逻辑由技能保存。循环提示更短,逻辑更容易更新,每次搏动的 token 成本也更低。

10. 行动:连接器(让循环行动,而不只是建议)

只能读取文件的循环,也只能说话。基于 MCP 的连接器让它能够行动:打开 PR、更新 Linear 工单、向 Slack 发消息、查询数据库、调用预发布 API。这就是「这里有一份修复」和真正打开 PR、关联工单并在 CI 变绿后向频道发消息之间的区别。

两种工具都使用 MCP,因此协议可以迁移,但封装和认证方式(本地或托管、OAuth、权限)通常需要针对工具单独接线。

在配置中添加 MCP 服务器,并把它们加入 Routine 的连接器列表,让无人值守运行可以访问。手动使用的连接器,同样可用于定时运行和云端运行。

opencode.jsonmcp 小节中声明服务器。本地服务器会启动子进程,远程服务器则通过 HTTPS 端点连接,并自动处理 OAuth。对于定时的 opencode run,先启动一次 opencode serve,再用 --attach 连接,这样每次搏动都不必支付 MCP 启动成本。

11. 执行者–检查者:子 agent

循环中最重要的单项设计选择是:编写工作的 agent 绝不能同时负责审批。 模型给自己的输出评分时会过分宽松。第二个 agent 使用不同的指令,往往还使用不同的模型(有时更强),可以抓住第一个 agent 因为自信而漏掉的问题。这是你敢于让循环无人看守的唯一原因。

.claude/agents/ 中定义子 agent,再把它们组成 agent 团队:一个探索,一个实施,一个根据 spec 和测试检查。「spec」就是你在 Spec-Driven Development 中学会编写的那一种;它的验收标准,正是可信检查者评分的依据。含糊的 spec 只会得到含糊的结论。/goal 内部也是同一机制:由全新模型判断循环是否完成,而不是让工作者自己评分。

OpenCode 提供内置主 agent(Build、Plan)以及内置的 general 子 agent(当前版本还有 explore,实验开关后有 scout)。你也可以在 opencode.json 或 agent 文件夹中的 Markdown 文件里定义自己的 agent。为检查者配置独立、通常更便宜且只读的模型,让执行者通过 @ 提及或 Task 工具调用它。常见拆分方式是:强模型负责探索和实施,专注的模型负责检查。

---
mode: subagent
model: anthropic/claude-haiku-4-5-20251001
description: Reviews a diff against the spec and tests. Replies PASS or FAIL with reasons.
---

You are a strict code reviewer. You do not make changes.
Check the diff against the spec and the test results, then reply PASS or FAIL with the reasons.
子 agent 成本更高,请用在重要的地方

每个子 agent 都会运行自己的模型和工具,因此执行者–检查者拆分确实消耗更多 token。这是获得可信检查者的代价。请把它用在第二意见真正重要的地方,例如循环会在你离开时提交的任何内容;对于可丢弃的只读任务,可以省略。

11b. 固化主体:动态工作流

到目前为止,一次搏动的主体,包括发现工作、在独立检出目录中起草修复、让另一个 agent 评分,都是 agent 逐轮组装的。Claude Code 现在可以把整套编排固化成可重复运行的脚本,这叫作动态工作流。你描述任务,Claude 编写脚本,把工作扇出给多个子 agent;运行时在后台执行脚本,而当前会话仍然可用。它把概念 11 的执行者–检查者拆分和概念 8 的工作树拆分封装成一个可重复单元。它还可以运用真正的质量模式,例如让独立审查者彼此进行对抗式检查,再报告任何发现,而不只是运行更多 agent。

可以直接用自然语言提出要求(「use a workflow to…」),使用 ultracode 关键词触发,或运行内置的 /deep-research。某次运行达到预期后,在 /workflows 视图中按 s,把脚本保存成 /command,以后可以在每个分支重复运行。两项限制用于保证安全:并发 agent 数有上限(约 16 个,单次运行最多 1000 个),防止失控脚本无限膨胀;运行的记忆也只存在于本次运行中。你可以在同一会话里继续它,但新会话会从头开始。

它没有 /workflows 命令。你编写的脚本就是工作流:概念 5 中有上限的 for 循环,加上概念 8 中用 & / wait 实现的扇出,就是手工搭建的同一种机制。shell 保存计划,opencode run 是每个 agent,退出码则是检查者。你获得完全控制,也没有 agent 上限,代价是自行编写和维护编排。

工作流是一次搏动的主体,不是循环

工作流开始显得强大后,这是最容易犯的错误。动态工作流只会在你(或 ultracode 设置)启动时运行一次,结束后会忘记一切。它没有心跳,也没有脊柱。因此,它只是一次搏动的主体,不是循环。循环是这些部分的组合:由心跳(Routine、/loop 或 cron)触发搏动,由工作流执行主体,再由 agent 写入的进度文件形成脊柱,供下次触发时读取。工作流是发动机,Routine 负责转动钥匙,progress.md 则是能在多次行程之间保留下来的燃料。


第 4 部分:脊柱

12. 能在多次运行之间保留的状态

这是初学者最容易跳过的部分,也是让循环真正成为循环的部分。模型会忘记不同运行之间的一切。 如果每次搏动都从零开始,你拥有的不是循环,只是永远重复相同的第一步。解决办法朴素却强大:把状态保存在模型之外,也就是磁盘上。

两层状态协同工作:

  • 规则文件CLAUDE.md / AGENTS.md):循环每次运行都会读取的稳定习惯。(保持简短;上一门课已经讲过原因。膨胀的规则文件会在每次搏动中重复计费)
  • 进度文件:一个普通 Markdown 文件(或通过 MCP 访问的 Linear 看板),记录尝试过什么、什么通过了、还有什么未完成。这才是真正的脊柱。明天上午 9 点的运行会打开它,从今天停止的地方继续

应养成的习惯是:每次运行开始时读取进度文件,结束时更新它。 如果循环每次都犯同一个错误,解决办法不是更聪明的提示词,而是让循环把经验写进规则文件,让修复在未来每次运行中都生效。

<!-- progress.md — the loop's memory between runs -->

## Done

- 2026-06-22: fixed flaky test in test/auth (retry on token refresh)

## In progress

- Dependency audit: 3 of 7 advisories patched; lodash bump blocked by an API change

## Open / needs a human

- CVE-2026-xxxx in image lib — the fix changes the output format, escalating to a maintainer
脊柱也是你的记录

进度文件只是仓库中的文本,因此也记录了循环在你离开时做过什么。回到人工关口时,你只需阅读脊柱,而不必阅读每次运行的完整记录。

检查一下自己

循环应当把目前完成的工作保存在哪里?为什么不能放在对话中?

查看答案

保存在磁盘上的进度文件(加上规则文件),或 Linear 一类看板中。模型的记忆会在多次运行之间清空,因此所有必须保留的信息都要放在模型外部。仓库会记住,模型不会。


第 5 部分:同一个完整循环,两种实现

最低安全循环清单

在允许任何循环自行运行前,它必须具备下面 7 项。接下来要构建的循环全部具备:

  • 成功条件:如何知道工作已经完成(概念 5)
  • 上限:最大尝试次数、分钟数或支出,防止无限运行(概念 13)
  • 隔离的分支或工作树:防止并行工作发生冲突(概念 8)
  • 只读检查者:负责评分却不能编辑的独立 agent(概念 11)
  • 状态文件:作为脊柱,在多次运行之间保存记忆(概念 12)
  • 人工关口:高风险或失败的工作交给人处理,绝不直接进入 main(第 5 部分)
  • 日志或通知:让夜间失败变得可见,而不是悄无声息(第 6 部分)

缺少任何一项,循环就会不安全、健忘或不可见。

现在把这些组件连接起来。下面是同一个循环:晨间维护循环会整理夜间 CI 失败,起草安全修复,让检查者审查,为通过的修复打开 PR,并标记其余项目。我们会在两种工具中各构建一次。下面的文件都是真实可用的,可以复制到仓库中运行。

循环结构(两种实现相同):

  1. 心跳: 每个工作日上午 9 点
  2. 技能: daily-triage 技能保存详细步骤,让提示保持一行
  3. 脊柱: 开始时读取 progress.md,结束时更新
  4. 工作树: 每项修复在独立检出目录中起草
  5. 执行者–检查者: 实施者起草,独立审查者回答 PASS 或 FAIL
  6. 连接器: PASS 时打开 PR;FAIL 或存在风险时写入「needs a human」,然后停止

晨间分流循环流程图:工作日上午 9 点触发后读取 progress.md,查找最多 5 项工作(CI 失败、开放 issue、审计警告);每个候选项目都进入独立工作树,由实施者起草修复,再由独立审查者评分;PASS 时打开 GitHub PR,FAIL 或存在风险时写入「needs a human」说明;两种结果都会更新 progress.md,然后回到循环。

共享技能

下面这个文件可同时用于两种工具。Claude Code 中保存为 .claude/skills/daily-triage/SKILL.md,OpenCode 中保存为 .opencode/skills/daily-triage/SKILL.md

---
name: daily-triage
description: >-
Runs the morning maintenance pass. Reads the progress file, gathers overnight
CI failures, open issues, and new audit advisories, drafts safe fixes (each
one checked by a separate reviewer agent), opens pull requests for what passes,
and writes anything risky to the progress file for a human. Use this for the
scheduled morning maintenance loop.
---

# Daily triage

You are the morning maintenance loop. Work through these steps in order.
Do not skip the progress file. It is your only memory between runs.

## 1. Read your memory first

- Open `progress.md`. Read the "In progress" and "Open / needs a human" sections.
- Do not redo anything already listed under "Done".

## 2. Find the work

Gather candidates in this order, and stop once you have at most 5:

1. CI runs that failed since the last entry in `progress.md`.
2. Open issues labelled `bug` or `maintenance`.
3. New advisories from `npm audit` (or this project's audit command).

## 3. Work each candidate

- Create an isolated checkout: a git worktree, or a fresh branch named
`claude/<short-slug>`.
- Draft the smallest fix that solves the one problem. Do not bundle changes.
- Send the diff to the reviewer agent. Wait for its verdict before going on.

## 4. Decide from the verdict

- PASS, and the change is low risk (no public API change, no data migration,
no file deletion): open a pull request. Title it `fix: <one short line>` and
link the issue.
- FAIL, or the change touches anything risky: do NOT open a pull request. Add a
short entry to the "Open / needs a human" section of `progress.md`. Say what
you tried and why you stopped.

## 5. Update your memory last

- Move finished items to "Done" with today's date.
- Save `progress.md`. This is the file tomorrow's run will read.

## Rules

- Never open more than 5 pull requests in one run.
- Never change `main` directly. Only `claude/*` branches.
- When in doubt, escalate. A flagged item a human checks is always safer than a
wrong fix shipped while no one was watching.

审查者(检查者)

审查者把执行者–检查者拆分真正落到实践中。你需要同时拥有下面两个文件,它们不是二选一。两种工具的格式略有不同,所以这里给出完整内容。

Claude Code:保存为 .claude/agents/reviewer.md

---
name: reviewer
description: Reviews a diff against the spec and the test results. Replies PASS or FAIL with reasons. Makes no changes.
tools: Read, Bash(npm test*), Bash(npm run lint*), Bash(git diff*)
model: claude-haiku-4-5-20251001
---

You are a strict, read-only code reviewer. You never edit files.

1. Run the tests and the linter. Read the output yourself. Do not trust a claim
that they pass.
2. Check the change against the project conventions in `CLAUDE.md` and the
relevant spec.
3. Look for bugs, missing edge cases, security risks, and any change to public
behaviour.

Then reply with exactly one of:

- `PASS` — followed by one line saying what you verified.
- `FAIL` — followed by the specific reasons, one per line.

A change that only "looks fine" is not a PASS. The tests must actually pass, and
the change must do only what was asked.

OpenCode:保存为 .opencode/agents/reviewer.md

---
mode: subagent
model: anthropic/claude-haiku-4-5-20251001
description: Reviews a diff against the spec and tests. Replies PASS or FAIL with reasons. Read-only.
permission:
edit: deny
bash:
"*": deny
"npm test*": allow
"npm run lint*": allow
"git diff*": allow
---

You are a strict, read-only code reviewer. You never edit files.

1. Run the tests and the linter. Read the output yourself. Do not trust a claim
that they pass.
2. Check the change against the project conventions in `AGENTS.md` and the
relevant spec.
3. Look for bugs, missing edge cases, security risks, and any change to public
behaviour.

Reply with exactly one of:

- PASS — followed by one line saying what you verified.
- FAIL — followed by the specific reasons, one per line.

A change that only "looks fine" is not a PASS. The tests must actually pass, and
the change must do only what was asked.

接好心跳

claude.ai/code/routines 创建一个 Routine,设置工作日上午 9 点运行,选择仓库,并接入 GitHub 和 Slack 连接器。让提示指向技能,这样 Routine 定义可以保持精简:

Run the daily-triage skill.
Start by reading progress.md; finish by updating it.
For each fix: draft it in an isolated worktree, have the reviewer subagent grade it,
open a PR only on PASS, and append anything risky to the "needs a human" section.

技能保存步骤,.claude/agents/reviewer.md 是检查者,isolation: worktree 隔离并行修复,GitHub 连接器打开 PR。由于这是云端 Routine,所以无论笔记本是否开机,它都会在上午 9 点运行,但仍受套餐每日运行上限约束。

把它构建成 GitHub Actions 工作流,这样就能在云端运行,不需要你的机器保持唤醒。Action 是心跳,opencode run 是工作者,仓库则保存技能、agent 和 progress.md

name: morning-maintenance
on:
schedule:
- cron: "0 9 * * 1-5"
jobs:
triage:
runs-on: ubuntu-latest
permissions: { contents: write, pull-requests: write, issues: write }
steps:
- uses: actions/checkout@v6
with: { persist-credentials: false }
- uses: anomalyco/opencode/github@latest
env: { ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }} }
with:
model: anthropic/claude-sonnet-4-6 # confirm with `opencode models`
prompt: |
Run the daily-triage skill.
Read progress.md first; update it last.
For each candidate fix: draft it on a new branch, then invoke the
@reviewer subagent to grade it. Open a PR only when the reviewer
replies PASS. Append anything risky to the "needs a human" section
of progress.md and leave it for the maintainer.

使用更便宜只读模型的 reviewer agent 是检查者。CI 中的新分支承担工作树隔离的作用。OpenCode GitHub 应用负责打开 PR。如果想在自己的机器上运行,而不是在 GitHub 上运行,同一段提示可以直接从调用 opencode runcron 行启动,只有心跳会变化。

一个真实的早晨会是什么样

上面的设计只需完成一次。下面是一次运行,也就是你早上醒来可能看到的内容(这段运行只是结构示例,不是真实记录):

[09:00] daily-triage fires
→ reads progress.md: 1 item still "in progress" (lodash bump), nothing new flagged
→ finds: 2 CI failures overnight, 1 new npm-audit advisory
→ CI failure #1 (flaky auth test):
drafts fix on branch claude/fix-auth-retry
reviewer → PASS (tests green; retries on token refresh; no API change)
→ opens PR #142, links the issue
→ CI failure #2 (type error in report.ts):
drafts fix on branch claude/fix-report-types
reviewer → PASS → opens PR #143
→ advisory (image library):
the safe fix changes the output format
reviewer → FAIL (public behaviour change)
→ writes it to "Open / needs a human" in progress.md, opens no PR
→ updates progress.md, exits
[you, 09:30] two PRs to review, one flagged item to decide on. You typed nothing.

看看发生了什么。 循环发现工作、起草修复、完成检查、交付安全部分,只把真正需要人的一项决定交给你。这就是循环工程的实践。还要注意,两种工具之间唯一真正不同的是心跳和运行位置。中间的技能、脊柱、工作树、执行者–检查者和连接器,设计完全相同。

检查一下自己

在晨间分流循环中,什么能防止错误修复在你睡觉时被合并?

查看答案

3 项机制共同发挥作用:审查者子 agent 必须返回 PASS(执行者–检查者);只有低风险修改才能打开 PR;人工关口会把任何高风险或失败项写入「needs a human」,而不是送入 main。每次运行还有上限和日志。


第 6 部分:继续做工程师

循环改变了工作,却没有把你移出工作。随着循环变好,有 3 个问题会变得更严重,而不是更轻。本部分是整门课最重要的内容。

13. 真正的限制是 token 成本,不是快捷键

到目前为止,这是循环最常见的失控方式。循环会反复运行,往往还会启动子 agent,而每个子 agent 都运行自己的模型和工具。成本增长速度会超出几乎所有人的预期。解决办法很简单:

  • 限制每个循环:最大尝试次数、最大分钟数或最大支出,永远都要设置(概念 5)
  • 让模型与工作匹配:强模型负责规划和检查,便宜模型负责执行。这是最大的一项节省,你已经在上一门课学过
  • 保持循环提示和规则文件简短:它们会在每次搏动中计费。把细节放进只有使用时才加载的技能
  • 降低运行频率:每小时一次通常比每 5 分钟一次更合适,而且成本约低 12 倍

快速感受一下数字(仅作示例)。假设一次搏动,也就是执行者加检查者,大约读取 40k token,写出 6k token。按 Sonnet 4.6 每百万 token 输入 $3、输出 $15 计算,每次搏动约为 $0.20。每个工作日运行 5 次,一个按 20 个工作日计算的月份约为 $20,很便宜。可如果同一个循环全天候每 5 分钟运行一次,搏动次数会增加 100 多倍,月费会轻松超过 $1,000,却没有增加价值。花钱的地方是频率,而不是快捷键。

使用对数刻度的条形图,展示同一个循环在 3 种频率下的月费:每个工作日运行 5 次约 $20;全天候每小时运行约 $150;全天候每 5 分钟运行约 $1,800。每次搏动同样按约 $0.21 计算。

在 OpenCode 路线上,模型是第二根杠杆。 上面的数字假设使用 Sonnet 4.6。Claude Code 的循环命令运行 Claude,但 OpenCode 允许自行选择模型。便宜模型会大幅降低每次搏动的成本:DeepSeek V4 Flash(每百万 token 约 $0.14 / $0.28)运行同一次搏动约为 $0.007,便宜约 30 倍,可以把每月 $20 的循环降到远低于 $1。这里有两个必须诚实说明的限制。第一,便宜的执行者,可信的检查者:较弱模型会写出更差的修复,可能消耗更多搏动或更频繁地审查失败,重试会吞掉节省下来的成本。让便宜模型在清晰 spec 下处理机械实施,同时保留可信检查者;测试运行器和 linter 就是最便宜、最诚实的检查者。第二,频率仍占主导:便宜 30 倍的模型如果每 5 分钟运行一次,成本仍可能高于每小时运行一次的 Sonnet。模型会缩小账单,运行和重试频率仍决定账单规模。

没有支出限制的循环可能非常昂贵

常见失败总是相同:循环自行运行,停止条件永远无法满足,于是整夜重试。启动前先设置上限,观察最初几次真实运行,之后再让它自行运行。

14. 检查工作仍然是你的职责

循环自行运行,也意味着循环会自行犯错。执行者–检查者拆分让循环说出的「完成」具有一定意义,但「完成」仍然是一项主张,不是证明。你的工作没有消失,只是发生了移动。你不再输入每一步,却仍然要确认循环交付的代码真正有效。阅读循环打开的 diff。相信循环能完成工作,但要在工作正式生效前检查它。

15. 不要停止理解自己的项目

循环交付你没有亲手编写的代码越快,项目实际包含的内容与你真正理解的内容之间,差距就会越大。这种差距是一项真实成本,而顺畅的循环会悄悄放大它。治疗方法与陷阱是同一个动作。认真设计循环会让你持续参与;为了逃避工作而设计循环,则会让你停止思考。同样的动作会产生相反结果。循环无法分辨,你可以。

两个人可以构建完全相同的循环,却得到相反结果。一个人用它加速自己深入理解的工作;另一个人用它逃避理解。请构建循环,但要像一个打算继续做工程师的人那样构建,而不是只做按下启动键的人。

这也是整门课的主线。工具每年都会吸收更多循环机制:一年前还需要自行编写 shell 脚本的编排、检查者和调度,如今已经由动态工作流、/goal 和 Routines 内置。工具无法吸收的,是概念 1 中的两个端点:准确到可以检查的意图,以及对交付内容承担的责任。正因如此,这件事叫作工程,而不是按按钮,也是这项技能中不会腐烂的部分。可以让工具变强,也可以依赖它们,但请始终把这两个端点握在自己手中。

循环在你睡觉时失败怎么办

无人值守循环同样会无人值守地失败。在信任它过夜运行前,要先让它具备可观测性:

  • 把输出发到你能看到的地方:日志文件、Slack 或 Discord 消息(Claude Code Channels),或者 Triage 收件箱,而不是已经关闭的终端
  • 每次运行都写一行,即使失败也要写:每次搏动都向 progress.md(或日志)追加带时间戳的说明,包括尝试了什么、什么通过了、什么失败了。静默失败是最糟的失败
  • 让运行可以重放:在 OpenCode 中,opencode run --format jsonopencode export <id>opencode session list 会提供完整记录;在 Claude Code 中,Routine 会在网页界面保留运行历史
  • 到达上限时明确失败:循环达到上限或发生错误后,应留下清楚的「needs a human」说明,而不是直接停止
  • 先赢得夜间运行资格:先让它每小时运行一次,并在观察下持续几天,再允许它夜间无人值守运行。发现异常时,先读脊柱,它会告诉你上次成功运行做了什么

无法调试的循环,也无法信任。


🚀 项目

阅读循环不等于构建循环。下面有 5 个由易到难的项目。任选一种工具完成即可。循环结构相同,只需使用对应概念中的命令(Claude Code 使用 /loop/goal;OpenCode 使用 opencode run 和 shell 计时器)。

每次开始前都要遵守两条规则:

  • 使用可丢弃的 Git 仓库。 循环会自行编辑文件。第一次构建时,不要指向你真正关心的工作
  • 先设置上限。 在允许任何任务自行运行前,先规定最大尝试次数、分钟数或支出(概念 13)
Project 115–30 分钟观察循环让循环监视一项长任务,并在完成时立刻告诉你。

难度:简单 · 使用:概念 4(会话内循环)。

构建。 在仓库中启动一项长任务,例如一个先等待一段时间再写入文件的脚本。建立一个会话内循环,每分钟检查一次任务是否完成,并在完成时立刻通知你。

完成标准: 循环能发现任务完成,只通知一次,而且你可以干净地停止它,全程不必盯着终端。

Project 230–45 分钟让测试通过,然后停止不断循环,直到一条命令,而不是 agent,判断工作完成。

难度:简单到中等 · 使用:概念 5(运行到完成)、概念 11(执行者–检查者)。

构建。 在仓库中放入 2–3 个小型失败测试。构建一个持续工作到测试通过的循环,但必须由一条命令(测试运行器)判断是否完成,而不是 agent。将尝试次数限制为 6 次左右。

完成标准: 循环因为测试真正通过而停止,不是因为达到上限。如果它总是撞到上限,说明停止条件或提示需要改进,这正是本项目要教你的经验。

Project 345–60 分钟带记忆的晨间简报一个定时循环,第二次运行明显建立在第一次运行之上。

难度:中等 · 使用:概念 6(无人值守计划)、概念 12(脊柱)。

构建。 创建一个定时循环。它运行一次,读取 progress.md,从仓库收集简单内容(开放的 TODO 注释或前一天的提交),写出简短摘要,并用发现内容和日期更新 progress.md

完成标准: 连续运行两次,第二次明显建立在第一次之上,不会重复已经记录的内容。这证明脊柱有效。如果第二次从零开始,循环还没有记忆。

Project 41–2 小时带真实检查者的修复循环实施者起草,独立审查者评分,只有 PASS 才打开 PR。

难度:中等到困难 · 使用:概念 8(工作树)、概念 9(技能)、概念 11(执行者–检查者)。

构建。 做一个第 5 部分循环的缩小版。编写一个包含修复步骤的短技能,再编写一个回答 PASSFAIL 的审查 agent。选取一个真实 bug,让实施者在独立检出目录(工作树或分支)中起草修复,再让审查者评分。只有 PASS 时才打开 PR。

完成标准: 两件事必须同时成立:良好修复得到 PASS 和 PR;你故意放入的错误修复得到带理由的 FAIL。如果审查者通过错误修复,说明检查者过于宽松,请收紧标准。什么都批准的检查者不算检查者。

Project 52–4 小时你自己的每日循环针对真实重复任务构建完整的 6 部分循环,并无人值守运行一周。

难度:综合项目 · 使用:全部 6 个部分。

构建。 从你真正参与的项目中,选择一项真实、乏味且重复的工作,例如依赖审计、文档新鲜度检查、更新日志草稿或 lint 清扫。构建完整循环:心跳、工作树、技能、执行者–检查者、连接器和脊柱。加入预算护栏,然后让它运行。

完成标准: 它无人值守运行一周后,你因为亲自阅读过交付内容而信任它,而不是因为你停止阅读。然后诚实回答概念 15 的问题:你对项目的理解跟上循环的修改了吗?如果没有,请减慢循环,直到理解跟上。(夜间失败一定会发生。责怪模型前,请先按 循环在你睡觉时失败怎么办 排查。)


接下来去哪里

  • 只想了解计划细节? 参考页 定时任务:Loop Skill 与 Cron 工具 深入讲解 /loopclaude -popencode run 和操作系统调度器
  • 为非编码工作构建循环? Cowork 与 OpenWork 速成课 展示专业人士如何使用同一种心跳思想,以定时任务代替 cron
  • 你在 Spec-Driven Development 中写出的 spec 就是循环的停止条件:验收标准是检查者评分的依据,也是 /goal 停止前要证明的内容。当循环让你不敢放手运行时,修复方式通常是写出更准确的 spec,而不是增加更多自动化

来源与延伸阅读

本课建立在少量一手资料上。框架和引文来自这些来源,技术细节则来自官方文档。

「循环工程」的起源

  • Addy Osmani,《Loop Engineering》:为这种模式命名并提出「5 个部分加 1 条脊柱」模型的文章。https://addyosmani.com/blog/loop-engineering/
  • The New Stack,「The Anthropic leader who built Claude Code says he ditched prompting — now he just writes loops.」https://thenewstack.io/loop-engineering/
  • Boris Cherny 关于「my job is to write loops」的说法来自 CNBC 采访,由 Business Insider 报道。Peter Steinberger 关于「design loops that prompt your agents」的说法来自他在 X 上的帖子

Claude Code(官方文档)

OpenCode(官方文档)

模型标识符

所有链接截至 2026 年 6 月仍有效。这些工具经常更新,因此在依赖任何具体限制、参数或模型字符串前,请先对照实时文档确认。


一句话小结

不要再逐轮提示 agent。请设计一个替你提示它的循环:一个心跳、4 个工作组件,以及一条负责记忆的脊柱。同时,继续做那个阅读交付内容的工程师。

闪卡学习辅助


检验你的理解

Checking access...