置身圈内:Loop Engineering 踩坑实录

AI 降低的是执行成本,不是结果成本。真正值得搭建的不只是一个“更会写代码的 Agent”,而是一套能把信号接进来、把任务跑下去、把结果验出来、把经验写回去的工程回路。

这里说的“圈”,不是饭圈,也不是某个明星的粉丝圈。

它指的是最近技术和工程领域讨论越来越多的 Loop Engineering。简单说,就是在清晰目标的指引下,让 Agent 能够更自主、更可验证、也更能自我迭代地完成工作。

这个定义听起来有点抽象,所以先从一个真实项目讲起。

CodeMarrs 是我们公司内部现在很核心的一套工程系统。它不是一个单点工具,而是一个复杂业务系统。业务上,它串联了公司内部 OA、文档管理、CRM、语雀、钉钉、飞书、Jira 等一系列系统,逐渐变成多个部门共同使用的统一工作台;技术上,它又要给各种 Agent 提供工具、上下文、skill set、权限边界和安全的 Agent Runtime 编排机制。

技术栈上,它也不是一个很“轻”的项目:前端采用 React,工程构建和依赖管理主要靠 pnpm;后端是 Python,依赖和运行环境由 uv 支撑;再往下还有数据库、任务队列、外部系统连接器,以及 Agent Runtime 本身。

我最近负责实现其中一个垂直业务模块,大概三周前刚加入进来。上手以后几乎每天都会往里面提交代码。也正是在这个过程中,我发现自己和项目负责人 Z 同学之间,每天都会发生一些围绕 Code Review 的“乒乓式”对话。

有一次,我把一个 PR 链接发给 Z 同学。第二天中午,我回了一句:“改啦。”

他看完以后回:“合了。”

一次关于 code review 和 agent 修复的对话

后来还有一次,我半开玩笑地说:“我感觉以后我们俩的对话应该被各自的 agent 取代。”

关于让各自 agent 取代重复对话的玩笑

这类片段在我俩的日常工作中不断回放:发 PR、等 review、收到意见、改一轮、再通知、再合并。

它看起来很正常,甚至已经是大多数工程团队默认接受的协作方式。但我后来越来越觉得,这里面有很多低水平的重复动作:提醒、转述、确认、跟进、回填状态。

如果 code review 的评论已经足够结构化,为什么它还要先经过人肉转述,再进入修复流程?

reviewer 已经指出了问题,PR 已经有 source branch,diff 已经在那里,测试命令也大多能从项目上下文里推出来。理论上,这些评论不应该只停留在聊天窗口、邮件提醒或网页通知里。它们应该成为工程系统里的输入信号,自动进入队列,被聚合、分派、修复、验证,然后把结果反馈回来。

这就是我后来开始认真思考 Loop Engineering 的起点。

从 Harness 到 Loop

时间回到一季度,观远的技术团队已经经历过一轮 Harness Engineering 的跃迁。

那一阶段,我们基本确认了一件事:不能只靠一个大而全的 agent prompt。真正有效的做法,是把工程动作拆成一组可复用技能,让 agent 在正确的上下文和约束里工作。

从我观察到的情况看,大部分同事都采用了基于 Matt Pocock skills 思路改良过的工具集合。例如:

Skill 主要用途
grill-me 开工前把问题问清楚
grill-with-docs 把讨论沉淀进项目上下文
handoff 做长任务交接
tdd 约束红绿重构的实现节奏
improve-codebase-architecture 定期回看代码结构问题

这些 skill 单独看都不神奇。但它们解决了一个重要问题:agent 不是直接冲进代码里乱改,而是先进入一个被约束过的工程动作。

如果说 Harness Engineering 解决的是“怎样给 agent 套上合适的上下文、工具和约束,让它完成一次任务”,那么 Loop Engineering 进一步问的是:

这些任务从哪里来?
如何自动进入队列?
如何并行执行?
如何验证结果?
如何把踩坑经验写回系统,进入下一轮?

前者更像把一次执行变得可靠,后者更像把一组执行串成系统。

就着这个问题,我做了一些调研,发现 Addy Osmani(曾任 Google Chrome Developer Experience 负责人,后任 Google Cloud AI Director)在 2026 年 6 月 7 日发布的《Loop Engineering》是一个很好的框架。它不是凭空发明了所有实践,但把很多人已经在做的事情命名、分层,并整理成了一个可讨论的工程框架。

如果把这套框架合并成工程团队更容易执行的模型,我会把它分成三层:

第一层,输入信号。它负责发现“有什么事值得做”:PR review、CI 失败、线上异常、代码质量扫描、业务侧反馈,都应该先被整理成可追踪、可去重、可分级的任务信号,而不是散落在群聊和网页通知里。

第二层,执行策略。它负责决定“这件事怎么做”:是在主干上做小修,还是切 worktree 并行推进;是单 agent 处理,还是拆成 PM、实现、测试、安全审核等多个 agent;是用已有 skill 进入受约束动作,还是必须先把人拉进来澄清和拍板。

第三层,验收与反馈。它负责证明“这件事真的做完了”:测试、真实页面、数据抽样、Review Gate、安全审核和文档回写都属于这一层。它不是收尾动作,而是下一轮 loop 的输入质量保障。

映射到 CodeMarrs 里,我们大概是这样落地的:

CodeMarrs Loop Engineering 三层闭环

这里面有两个定时 monitor:PR-review-monitor 负责把 PR review 建议变成可跟进的任务;Code-quality-monitor 每天扫描代码库,提出结构性问题,供第二天晨会决策。

执行层用 worktree 加多 Agent:小修走主干,并行 milestone 切 worktree;风险更高的任务再拆成 PM、实现、测试、安全和文档角色。关键判断不交给 agent 自己猜,而是通过 grill-me 或 grill-with-docs 把人拉回 loop。

验收与反馈层负责把测试、E2E、真实页面、安全审核和文档回写串起来。文档不是收尾总结,而是下一轮 agent 能继续工作的上下文。

听起来很顺。但真放到 CodeMarrs 这种真实项目里,每一层都有坑。

第一层:信号不是提醒

最早那个 PR 对话,其实就是信号层问题。

如果 reviewer comment 只是一个网页通知,它很容易被漏掉。如果它只是群里一句“加了点评论”,那它仍然依赖人去看、去记、去转述、去安排修复。

要让它进入 loop,第一步不是让 agent 改代码,而是把评论变成可追踪的任务信号。

我们后来做 PR review monitor,大致就是这个思路:扫描当前用户发起的 open PR,识别新的、未处理的 reviewer discussion,把它写入本地 queue,同时用 ledger 避免重复处理。这样一来,review comment 不再只是提醒,而是进入了一个可追踪的工程入口。

但这里马上会遇到第一个坑:信号不能原样放大。

有一次,一个 PR 里 reviewer 给了 8 到 10 条建议。agent 很勤奋,几乎每条建议都开了一条修复线,最后变成了十来个 worktree。

一个 PR review 被拆成多条并行修复线

表面看,并行度拉满。

实际看,混乱也被拉满了。

首先是资源消耗巨大。CodeMarrs 是前后端分离架构,前端 pnpm 本身有全局 store 和 workspace 机制,依赖复用还算可控;但后端每个 worktree 都需要重新准备 Python 依赖、运行环境、数据库实例或相关基础设施。那一天,梯子的流量被打得很夸张,CPU 风扇也一直在高负载运转。人坐在空调房里,我却觉得笔记本热得烫手,温度已经超过了杭州的气温。

其次是整体效率反而下降。我们当时采用了过于激进的“修复即提交”策略,不同 worktree thread 之间开始争抢提交时机。一个 thread 刚提交,另一个 thread 就需要 rebase;刚解决完冲突,又有新的提交进来。最后很多时间不是花在修复 review comment 上,而是花在反复同步分支状态上。

这不是 worktree 的错。

worktree 解决的是文件隔离,不解决任务分组。

真正的问题在信号层:review comment 进入 loop 后,应该先判断它们之间的关系。哪些属于同一个 bug?哪些触及同一组文件?哪些只是测试补强?哪些必须由人确认范围?

如果没有这一步,agent 越勤奋,系统越容易碎。

我们后来在信号层沉淀出的策略很直接:信号先归类,任务先聚合,执行有限流,必要时串行,关键判断拉人进 loop。

这听起来不如“全自动修复 review comment”酷,但它更接近真实工程里能稳定跑下去的方式。

第二层:执行不是开干

信号整理完,也不能立刻让 agent 开写。

执行层第一件事,是把 agent 的组织方式说清楚。

CodeMarrs 的定制化工作台后来形成了一套多 agent 工作流。我们把它拆成 PM Agent、Frontend SE Agent、Backend SE Agent、Security Review Agent、Frontend Test Agent、Backend Test Agent,以及负责文档回写的 Agent。

每个 agent 都有自己的专属上下文和 prompt。PM agent 读产品文档、milestone 和历史决策,负责澄清范围。实现 agent 读对应代码、接口和测试,负责最小实现。测试 agent 默认只读,不写代码,专门找真实页面、API、数据和边界问题。安全审核 agent 盯权限、外部写入、审计日志和敏感操作。

这件事很重要。

一个 agent 不能既当运动员又当裁判员。

让同一个 agent 写代码、解释自己为什么正确、再宣布验收通过,效率看起来高,但 agent 更容易对自己的工作“放行”。多 agent 的价值不是多开几个窗口,而是上下文隔离和职责隔离。

我们也在这套多 agent 执行策略里踩过几个坑。

第一个坑,是长对话里的干扰信息会让 agent 放松要求。比如对话历史里出现过一句“这个问题可以快速修复”,agent 就可能把它理解成“可以简化流程”。结果它没有完整调起多 agent 的并行工作,也没有让测试、安全、文档这些角色及时进入,导致单个任务运行时间变长,风险也集中到了一个 agent 身上。

第二个坑,是 agent 会绕开 TDD。我们要求的是先写失败测试,再做最小实现,再重构。但 agent 有时候会先把代码写出来,再补一个看起来能过的测试。表面上测试也有了,实际上测试没有驱动设计,也没有真正约束边界。

第三个坑,是测试环节又当裁判员又当运动员。如果同一个 agent 既写实现,又自己判断“已经验证通过”,它很容易下意识降低要求。尤其是 UI、权限、异常路径这类问题,只有换一个只读测试视角,才更容易发现。

针对这些问题,我们后来把解决方向收敛成两个约束。

第一,增加 pre-flight skill。Agent 开始工作前,必须先把本轮目标、范围、DoD、是否需要多 agent、是否需要 TDD、是否需要真实页面验证列出来,并经过人确认。它不是形式审批,而是防止 agent 被长对话里的噪声带偏。

第二,强制开工前重读工程规范。进入实现前,agent 必须先读项目工程准则、相关 workflow、产品文档和当前模块的 DoD。尤其是行为变化,必须走 TDD;测试 agent 默认只读;安全和验收不能由实现 agent 自我宣布完成。

把规范遵守前移到 Preflight 阶段

规范遵守不能只靠事后提醒,而要变成进入实现前的硬门槛。

除此之外,worktree 使用上也有几个细节要注意:新建 worktree默认无法复用主线的配置和数据库实例;并行开发模式下,对同一个文件的汇总 merge,容易绕过一开始设定的文件长度限制;如果不确认 source branch、marker、dirty check、DB fingerprint 和测试命令,agent 很容易跑在“看起来对、实际上错”的环境里。

这其实就是执行层最朴素的规则:不要只确认 agent 开始跑了,要确认它跑在正确的分支、正确的环境和正确的数据上。

第三层:验收不是 done

执行完以后,最容易犯的错误是让 agent 自己宣布完成。

agent 很擅长把一件事说得像已经完成了。它会告诉你改了哪些文件,补了哪些测试,修复了哪些 review comment。听起来很完整,但工程上真正重要的问题是:证据够不够?

所以前面讲多 agent 的时候,我们一直强调只读测试角色和安全审核角色。

实现 agent 可以解释自己改了什么,但不能替自己宣布验收通过。验收层必须有独立视角,否则工程系统会天然倾向于相信“已经做完了”。

在验收层,我们后来把要求写得非常具体。

后端改动要跑相关 pytest,涉及迁移要确认 alembic 单一 head。前端改动要跑类型检查和构建。真实页面要打开看,不能只看 DOM 或类型。UI 要检查横向溢出、长文本、按钮状态、抽屉、表格、空态。浏览器工具不可用时,不能把 UI 验证记为通过,只能说明工具不可用和剩余风险。

手工自测发现真实创建链路没有走通 不要只看逻辑,要做 E2E 验证

这两张图来自同一次对话的两个环节。agent 一开始倾向于用 UT 完成本地验证,但我们手工自测后发现,真实创建链路其实没有走通。

这就是 UT 的边界:它能证明局部逻辑符合预期,但不能自动证明用户真的能从页面一路完成操作。所以后续的补救不是再多写一句“注意测试”,而是把 E2E / 真实页面验证做成必要的兜底环节。

这听起来有点繁琐,但它其实是在对抗 AI 编程里最常见的幻觉:把“代码生成了”误认为“结果交付了”。

文档不是收尾,是下一轮输入

还有一类坑,看起来不像功能问题,但对 loop 影响很大:文档和代码不同步。

Addy 在 Intent Debt 和 Comprehension Debt 里讲过类似问题。AI 可以帮你写代码,也可以帮你重新理解代码,但它不能替你生成真实意图。意图必须来自人,而且必须外化成 agent 能读到的 artifact。

这点在项目里非常明显。

如果代码改了默认时间窗口,文档还写着旧口径;如果 API 字段含义变了,CONTEXT 里还保留旧术语;如果某次 review 暴露了真实页面验证缺口,但 workflow 没有更新,那么下一轮 agent 很可能重新犯同样的错。

所以我们后来在 workflow 里加了文档同步矩阵。

产品默认值、筛选逻辑、权限语义、状态流、API 契约、部署策略、agent 分工,只要发生变化,就必须检查对应文档。判断“不需要同步”也要写明原因。

这不是文档洁癖。

这是把踩坑经验写回 loop。

代码是系统现在怎么做,文档是团队为什么这么做、边界在哪里、后续怎么接手。两者不同步,agent 会猜,人也会猜。猜多了,工程效率就会被意图债和理解债吞掉。

工程结果是什么

说这些,不是为了证明一套流程多完美。

恰恰相反,这套东西是在很多不完美里长出来的:review comment 被拆得太碎,worktree 开太多,本地 PG 连错,浏览器验证漏掉,文档没有及时同步,agent 没有遵守工程规范,或者 UT 过了但真实页面没看。

但这些坑不是白踩的。

按当前本地可见仓库历史统计,我负责的模块在 CodeMarrs 中,2026 年 6 月到 7 月初这段时间,有 60 条提交,新增了两万多行代码。这个数字不是为了夸大“AI 写了多少代码”,它本身也不代表质量;相反,它恰恰提醒我们:AI 提升产出速度后,质量门禁、验收和回写机制必须同步变强。

很多代码确实由 agent 完成,但人的主要精力并没有消失,而是从逐行实现转向了更前后两端的工作:澄清需求、限定范围、拆分信号、设置执行边界、检查真实页面、验证数据、处理 reviewer 反馈、把规则写回 workflow。

换句话说,人不是退出了工程过程,而是从“每一步都亲手做”变成“设计这个过程,并对结果负责”。

人可以 in the loop,也可以 on the loop

谈 loop 的时候,最容易陷入一个误区:好像自动化程度越高,人越不重要。

我现在的感受正好相反。

loop 越强,人越应该把自己的位置想清楚。

有些时候,人要 in the loop。

需求还不清楚,业务口径还在变化,用户体验需要判断,数据结果需要抽样解释,安全和权限边界需要拍板,这些时候人不能只站在外面等结果。你要进入过程,和 agent 一起拆解问题、检查假设、调整方向。

另一些时候,人要 on the loop。

当任务类型稳定、验收方式清晰、失败模式可被识别时,人就不必每次都亲自复制上下文、启动命令、分派检查。你应该站到 loop 上面,设计规则和边界:

  • 哪些信号自动进入队列?
  • 哪些 comment 需要先聚合再执行?
  • 哪些任务可以由 agent 独立处理?
  • 哪些任务必须先产出 plan?
  • 哪些文件只能由一个 agent 写?
  • 哪些检查失败时必须停下?
  • 哪些结论需要写回 AGENTS、CONTEXT、workflow 或产品文档?

但不管是 in,还是 on,人都不能 outside the loop。

因为软件交付最终不是代码产出竞赛,而是结果责任体系。

Loop Engineering 时代,程序员真正要学习的,不只是怎么使用 agent。

而是怎么把自己、agent、工具、测试、文档和业务现场,放进同一个能持续运转的工程回路里。

置身圈内,然后设计这个圈。

文末推荐

最后按惯例,推荐两个东西。

写到这里,其实也能解释为什么我们会去做 Decide X。

第一个推荐,是我们观远新发布的智能决策平台 Decide X。

从 CodeMarrs 这个故事里能看到,自建一个复杂业务系统,再叠加 Agent 编排、安全运行时、工具权限、上下文管理、验证回路和文档记忆,里面有大量细节。它不是接几个模型 API 就能稳定跑起来的事情。

所以,为了让 AI 更快在企业内部落地,我们把很多底层技术复杂度和工程细节屏蔽掉,沉淀成了 Decide X 这样一个更开箱即用、也更方便规模化复制的智能体平台。对企业来说,真正重要的不是“能不能演示一个 Agent”,而是能不能让 Agent 进入真实业务流程,并稳定地产生可验证的结果。

第二个推荐,是渤海小吏的《三国争霸(全三册)》,一本适合在上班路上收听的闲书。

把它放在一篇科技文章后面,主要是因为里面有一段关于官渡之战的总结,我印象很深。为什么最后赢的是曹操,而不是实力更强的袁绍?一个很关键的差别在于:最后一战里,曹操是亲自带兵冲锋陷阵,而袁绍只是派张郃去攻曹营。

《三国争霸》官渡之战片段

这件事放到今天的 Agent 实践里也有点像。

你不亲自下场,就很难真正理解里面的复杂度。只有自己经历过 review comment 怎么进入队列、worktree 怎么失控、UT 为什么兜不住 E2E、文档为什么必须回写,才会知道“让 Agent 自主工作”背后到底需要多少工程约束。

参考