我用 opencode-loop 跑了一次完整的 Loop Engineering 实践,让 AI 自己写代码、自己 Review、自己跑测试。大约十几分钟后,测试从 8 个变成 23 个,全部通过。这不是魔法,关键在 verifier 和 checkpoint。


一、手动用 AI 写代码,人到哪都是瓶颈

过去两年,用 AI 写代码的基本流程是:

你写 prompt → AI 回复 → 你读代码 → 再写 prompt → AI 再回复 → ...

人是方向盘,每一轮都要在场。问题是,这个模式有几个死结:

  1. 写完就忘。Agent 可能一次改十几个文件,你不可能每一行都仔细看,bug 就藏在没看的那几行里。
  2. 测试后置。经常是代码写完了才想起来跑测试,失败了一堆再回头找,效率低。
  3. Review 走形式。自己 Review AI 写的代码,看多了会疲劳,边界条件、类型安全、可访问性这些很容易漏。

本质矛盾是:人成了瓶颈,但完全放手又不敢。

2026 年 6 月,Google 工程师 Addy Osmani 写了一篇 Loop Engineering,把这个问题的解法说得很直接:

Loop engineering is replacing yourself as the person who prompts the agent. You design the system that does it instead.

Peter Steinberger 也说过类似的话:

You shouldn't be prompting coding agents anymore. You should be designing loops that prompt your agents.

翻译成大白话:别再一遍一遍给 AI 写 prompt 了,去设计一个能自动循环的系统。


二、Loop Engineering 的最小控制环

Loop Engineering 不是某个具体工具,而是一种设计方法。Addy Osmani 在原文里讲的是 Automations、Worktrees、Skills、Plugins/Connectors、Sub-agents 这些能力层组件。落到一个最小可运行的控制环,我更喜欢 Codersarts 的拆法:

  1. Goal:清晰、可衡量的完成标准。
  2. Prompter:生成下一轮指令。
  3. Agent:执行指令、产出代码。
  4. Reader:读取代码 diff、测试输出、日志和进度文件。
  5. Verifier:独立验证结果是否满足 goal,不能信 Agent 自评。
  6. Controller:决定停止、重试还是升级给人。

还有一个贯穿整个循环的要素,Addy 叫它 State/Memory:循环必须有一个对话上下文之外的记忆文件,记住"完成了什么、下一步做什么",因为模型每次都会遗忘。CLAUDE.mdAGENTS.mdprogress.md 都可以承担这类记忆职责,只是粒度不同。

Codersarts 在 Loop Engineering Explained 里把这个控制环画成了一个最小骨架:

for iteration in range(1, MAX_ITERATIONS + 1):
    passed, output = run_tests()  # Verifier
    if passed:                    # Controller
        return True
    prompt_agent(output)          # Prompter → Agent
return False                      # 达到上限,升级给人

注意两个关键点:

  • Verifier 必须独立。Agent 自己说"我修好了"不算数,要跑真实的测试。
  • 必须设上限。没有 MAX_ITERATIONS 或预算上限,循环会无限烧钱。

三、我的实现:opencode-loop + Editor/Reviewer 双 Agent

我选择用 opencode-loop 作为 loop 调度器,OpenCode 作为 Agent 运行环境,搭了一个 Next.js Todo Web Demo。

完整项目已经开源在 Gitee: https://gitee.com/chenjim/opencode-loop-engine

3.1 Agent 设计

.opencode/agents/ 下定义了两个 Agent:

  • editor:DeepSeek V4 Pro,负责实现代码。
  • reviewer:Kimi K2.7-code,只读审查,不能改文件、不能跑命令。

opencode.json 里的核心配置:

{
  "agent": {
    "editor": {
      "mode": "primary",
      "model": "opencode-go/deepseek-v4-pro",
      "prompt": "{file:.opencode/agents/editor.md}"
    },
    "reviewer": {
      "mode": "subagent",
      "model": "opencode-go/kimi-k2.7-code",
      "permission": { "edit": "deny", "bash": "deny" },
      "prompt": "{file:.opencode/agents/reviewer.md}"
    }
  }
}

Reviewer 的 prompt 强制要求它输出结构化结果:

## Review Result: PASS / NEEDS_FIX

### Issues
- ...

### Suggestions
- ...

3.2 Loop 命令

启动循环的 /loop-goal 命令:

/loop-goal \
  --check "npm test" \
  --check "npm run lint" \
  --check "npx tsc --noEmit" \
  --complete-when-checks-pass \
  --max-failures 3 \
  --max-runtime 2h \
  --checkpoint-only \
  --safe \
  --progress-file progress.md \
  --prompt-file loop-prompt.md \
  "完成 Next.js Todo Web Demo 的所有 TODO。每次修改后调用 @reviewer 审查,按反馈修复,直到所有检查通过。"

几个关键参数的作用:

  • --check:Verifier,每轮后自动跑测试、lint、类型检查。
  • --complete-when-checks-pass:Controller,所有检查通过就停止。
  • --max-failures 3--max-runtime 2h:安全上限,防止无限循环。
  • --checkpoint-only:只保存 diff 快照,不自动 git commit
  • --safe:阻挡危险命令。
  • --progress-file progress.md:外部状态文件,Agent 每次读取并更新 TODO。

整个流程可以用下面这张图概括:

Loop Engineering 实战流程

3.3 为什么要有 CLAUDE.md

Loop 每次运行都是一次新的对话,模型不会记住上一轮的项目约定。如果不在仓库里写清楚,Agent 每轮都会重新猜测:

  • 这个 demo 用不用数据库?
  • 样式是 Tailwind 还是 inline style?
  • 哪些命令是 verifier?
  • 哪些命令绝对不能跑?

我在项目根目录放了 CLAUDE.md,把项目定位、技术栈、关键文件、验证命令、Agent 约定、已知问题都写进去。它和 AGENTS.md 一样,本质上都是仓库级记忆文件,让 loop 不用每次都从零推导项目上下文。

Addy Osmani 把这类文件叫 State/Memory,Codersarts 会把它们作为 Reader 读取的输入。名字不同,作用一样:把意图写在对话上下文之外,落到仓库文件里,而不是让 Agent 每次自己猜。


四、实战过程:从 8 个测试到 23 个测试

项目初始骨架已经搭好:

  • package.json 和测试配置已经提交
  • src/tests/ 有基础实现,共 8 个测试
  • progress.md 里列了 6 个 TODO,全部未勾选

运行 /loop-goal 后,Agent 的行为如下:

  1. 探索代码库,读取 progress.md 和关键文件。
  2. 运行初始检查npm testnpm run lintnpx tsc --noEmit,8 个测试全过。
  3. 调用 Reviewer 对项目结构、类型、API 路由、前端页面、测试分别审查。
  4. 按 Review 反馈修复
  5. 扩展测试覆盖,并重新跑检查。
  6. 再次 Review,处理剩余问题。
  7. 更新 progress.md,标记所有 TODO 完成。

整个循环跑了 大约十几分钟,最终结果:

Test Files  2 passed (2)
Tests       23 passed (23)

测试从 8 个增加到 23 个,全部通过。


五、Reviewer 到底发挥了什么作用

这次实践里,Reviewer 不是摆设。它确实找出了代码里的真实问题:

问题 位置 严重程度
toggleTodo 只能标记完成,不能取消 src/app/page.tsx
API 路由 catch-all 返回 400,不区分服务器错误 src/app/api/todos/route.ts
PATCH body 没有运行时校验 src/app/api/todos/[id]/route.ts
页面缺少 loading/error 状态 src/app/page.tsx
input 缺少 label,按钮缺少 aria-label src/app/page.tsx
测试覆盖不足,缺少交互测试 tests/page.test.tsx

修复后,代码质量比初始版本高了一档。

但 Reviewer 也不是万能。它没发现把 eslint-config-next 升到 16.2.9 后,在当前 FlatCompat 配置下会触发兼容问题。这个坑是在实际跑 lint 时踩到的。这说明:Reviewer + 自动化测试 = 两层验证,比单层更可靠,但都不是 100%。


六、踩坑记录

6.1 eslint-config-next 版本不兼容

Reviewer 建议把 eslint-config-next 从 15.1.7 升级到 16.2.9,与 next 版本对齐。但升级后,FlatCompat 处理新配置时直接崩溃:

Converting circular structure to JSON

Agent 回退到 15.1.7 后 lint 才恢复正常。这个兼容性问题被写进了 progress.md 的 Known Issues 里。

6.2 opencode-loop 是小众社区插件

ByBrawe/opencode-loop 目前还是小众社区插件,没有官方背书,文档主要靠 README。但它完整实现了 Loop Engineering 需要的核心能力:调度、验证、checkpoint、安全限制。

6.3 模型选择有讲究

  • Editor 用 deepseek-v4-pro:推理和实现能力强,适合写代码。
  • Reviewer 用 kimi-k2.7-code:代码审查细致,适合找问题。

如果反过来,或者两个用同一个模型,效果可能会差一些。至少在这次实践里,"实现模型"和"审查模型"拆开后,Reviewer 更容易站在旁观者视角挑问题。

6.4 verifier 全绿后,人工核验又找出 bug

循环跑完、npm testnpm run lintnpx tsc --noEmit 全部通过,progress.md 也全勾选。我本以为可以收工,结果手动拉起来看了一遍页面和 diff,又发现几个问题:

  1. input label 用了 display: 'none':屏幕阅读器也会忽略这个 label,等于 input 还是没有可访问名称。
  2. 加载态把整页替换成 Loading...:骨架结构都没有,首屏体验差。
  3. tsconfig.jsonjsx 还是 preserve:Next.js 16 新编译器下应该配成 react-jsx
  4. mutation 没有防重入:快速点两次 Delete 会触发并发请求,第二个会 404。

这些问题都没被自动化 verifier 拦住。测试覆盖的是功能正确性,lint 覆盖的是代码风格,tsc 覆盖的是类型,但可访问性、交互细节、框架版本适配仍然需要人仔细看。


七、Loop Engineering 的边界

这次实践让我确认了几件事:

第一,Loop 不是全自动魔法。

人仍然要定义目标、设计 Agent prompt、配置 verifier、审阅最终的 diff。Loop 只是把"重复prompt"这部分自动化了。

第二,Verifier 是底线,但不是上限。

如果循环只问 Agent"你完成了吗",它会自信地说完成了,然后留下一堆 bug。独立的测试、lint、类型检查是 loop 能信任的底线,能拦住功能错误和类型错误。

但就像 6.4 里写的那样,verifier 全绿之后,人工复核仍然可能发现可访问性、交互细节、框架版本适配这类问题。Loop 能替你跑重复验证,不能替你负责最终质量。

第三,理解债务会加速积累。

Loop 跑得越快,代码库增长越快,你越可能不理解自己仓库里的代码。Addy Osmani 管这叫 comprehension debt。解决方案没有捷径:定期读 Loop 产出的代码。

第四,成本必须设上限。

--max-runtime--max-failures、token 预算,这些不是可选项。一个无人看管的 loop,可以在几小时内烧掉很多钱。

适合用 Loop 的场景:重复性改造、测试驱动重构、长时编码任务、需要多轮修复的 bug。

不适合的场景:架构设计、需要深度业务判断的代码、需要创造性 UI/UX 的工作。


Loop Engineering 把 AI 编程从"人拿着方向盘"推进到了"人设计导航系统,车自己跑"。但车最后还是你的,路也要你选。

这次用一个 Todo Demo 验证了这条路是通的。下一步,我会把它用到一个更真实的项目里,看看在复杂代码库上,Reviewer 还能不能保持同样的命中率。

如果你也想试,建议从一个小功能开始,先把 verifier 写好,再让 loop 跑起来。


本文链接:Loop Engineering 实战:用 opencode-loop 搭一个能自我修正的 AI 开发循环 - https://h89.cn/archives/634.html

版权声明:原创文章 遵循 CC 4.0 BY-SA 版权协议,转载请附上原文链接和本声明。

标签: AI, Agent, opencode, prompt, Engineering, Loop, Verifier, progress

🎓 呈言英语 智能英语学习平台
📚单词学习 🎧听说练习 📖阅读理解 ✏️拼写练习 🌟 AI智能推荐 · 科学记忆曲线
🚀 立即开始免费学习

添加新评论