系列第三篇。上一篇拆了 Harness(Agent 的操作系统),这篇拆 Loop(Agent 的认知循环)。核心问题是:Agent 拿到工具之后,怎么走路才不摔跤?

An image to describe post


前两篇反复提过一个说法:Loop Engineering 是把人类「边做边想」的模式工程设计进 Agent 里。听起来挺对,但这句话缺了一半——人类的「边做边想」到底是什么?拆开来看,其实就三件事:做完一步之后看一眼对不对(验证),发现不对了知道问题出在哪(失败分类),根据问题重新给自己下指令(自我提示)。这三件事转起来,就是一个 Loop。

这篇就把这三件事拆清楚。


验证机制:Loop 的眼睛

Loop 里最基础也最容易出问题的一环,就是验证。

为什么容易出问题?因为模型天然有一种倾向:它不知道自己做错了。模型生成了一段代码,你问它「这段代码对吗?」它大概率说「对」。这不是模型在撒谎,而是它没有独立于生成之外的判断能力——生成和评估走的是同一条推理路径。

验证机制要解决的就是这个问题:让 Agent 用一个独立的「眼睛」来看自己产出的东西。 这只眼睛不能是模型自己,得是外部的、确定性的、不依赖模型判断的东西。

我看到的具体实践里,验证大致分两类:

确定性验证(Deterministic Verification)。 这东西不会撒谎。测试跑过了就是过了,没过就是没过。lint 报了就是有风格问题。类型检查通过了就是类型安全。这些验证工具的好处是结果绝对可信,坏处是它们只能验证「对不对」,不能验证「好不好」。代码可以通过所有测试但架构一塌糊涂,lint 全绿但可读性为零。

Stripe 的 Minions 系统把确定性验证做到了极致——它用的是 Martin Fowler 框架里的「硬编码确定性 gate」。Agent 产出的代码必须先过编译、再跑测试、再过 lint,每一步都是一个硬 gate,不过就回退,没有商量余地。Minions 的设计思路很清晰:能用机器判断的事,绝对不让模型自己判断。

推理性验证(Inferential Verification)。 有些东西确定性验证覆盖不了——架构是否合理、代码是否可维护、逻辑是否正确。这些需要「理解」才能判断。于是有了 AI-on-AI review:用一个独立的模型来审查另一个模型的输出。Claude Code 支持通过自定义 subagent 做 AI-on-AI review——用一个独立 Agent 读另一个 Agent 的产出然后挑毛病(/goal 命令本身也会用独立模型评估结果)。

但这个模式有一个天然的矛盾:用模型验证模型,谁验证验证者?Addy Osmani 在他的 Loop Engineering 文章里也表达了类似的谨慎——模型自评天然有盲区,需要独立验证机制来兜底。所以推理性验证不能是最后一关,它上面还得有确定性验证兜底,再上面还得有人类 review。

一个好的验证体系,大概是三层叠加:确定性验证(机器)做第一关,推理性验证(AI review)做第二关,人类 review 做最后一关。每一关解决上一关覆盖不了的问题。


失败分类:不是所有失败都该用同一种办法处理

Loop 之所以是 Loop,就是因为会失败、会回头。但我发现很多人——包括一开始的我——对「失败恢复」的理解就是「失败了再试一次」。

再试一次是效率最低的恢复方式。

真的有用的失败恢复,前提是先搞清楚失败的类型。不同类型的失败,恢复路径完全不同。我试着把 Agent 工作中常见的失败分成了三类:

An image to describe post

确定性失败:原因清晰、路径明确。 编译错误就是最典型的——错误信息精确地告诉你在哪个文件的哪一行、什么符号出了问题。这种失败不需要 Agent「重新理解问题」,它只需要读错误信息、定位到具体位置、修正,然后重新验证。恢复路径是直线。

逻辑性失败:测试没通过,但为什么没通过需要重新推理。 改了 A 模块的代码,B 模块的集成测试挂了。错误信息只告诉你 B 挂了,但没告诉你是因为 A 的改动破坏了 B 的假设,还是 B 本身就有 bug。Agent 需要带着这个新信号重新进入理解循环——读 B 的代码、理解 A 和 B 的依赖关系、判断问题根源、修正、再验证。恢复路径有分支,可能走错。

环境性失败:跟 Agent 的代码无关,跟外部世界有关。 网络超时、第三方 API 挂了、CI 环境有问题、依赖包下载失败。这种失败最坑——Agent 如果把它当成代码问题来修,就会在完全错误的方向上浪费资源。好的 Loop 设计会先判断「这个失败是我的问题还是外部的问题」,外部问题就等着而不是改代码。

Claude Code 的 /goal 命令是处理失败恢复的一个好例子。/goal 让 Agent 持续跑直到一个可验证的条件满足——比如「所有测试通过」。Agent 每跑一轮,不管中间失败多少次,只要目标还没达到,Loop 就不会停。但 /goal 本身不区分失败类型——它只是持续重试。更精细的失败恢复逻辑需要 Agent 自己在 Loop 里判断:这次的失败是哪种类型?该用什么策略?

Boris Cherny 在 Lenny‘s Podcast 上提到过一个观点,大意是:Claude Code 团队花了很多精力设计 Loop,让 Agent 能判断该坚持还是换方向。这个判断能力不是靠多轮重试自然产生的,而是需要被设计进 Loop 里的——Agent 要能识别「我已经在这个方向上兜了三圈了,每次都是同一个错误,问题应该不在代码而在我的假设」。


自我提示:最让我着迷的 Loop 能力

自我提示是 Loop Engineering 里最独特的概念,也是我理解得最晚的一个。

An image to describe post

传统观念里,prompt 是人写的——人告诉模型要做什么,模型去做。在 Loop 里,这个关系反过来了:Agent 每走完一步,自己给自己写下一步的 prompt。

举个例子可能更清楚。假设 Agent 接到一个任务:「修复 CI 中 test_payment_flow 的失败」。第一轮,它读了 CI 日志,发现错误是「PaymentGateway.timeout」。它给自己写的下一步 prompt 大概是:

「CI 日志显示 PaymentGateway.timeout 错误。我需要:第一,找到 PaymentGateway 类的定义和调用位置;第二,检查是否有最近的改动涉及超时配置;第三,查看测试用例 test_payment_flow 具体在测什么场景。」

它执行了这几步之后发现超时配置没有问题,但测试用例里 mock 的支付网关返回值跟实际的不一致。于是它给自己写第三轮的 prompt:

「超时配置没有问题。我发现 test_payment_flow 的 mock 返回值跟 PaymentGateway 的实际签名不匹配——最近有人改了 PaymentGateway.process() 的返回值类型但没更新测试 mock。我需要:第一,确认 PaymentGateway.process() 的新返回值类型;第二,更新测试 mock 以匹配新类型;第三,检查是否还有其他测试用了相同的 mock。」

注意这里发生的事:每一轮的 prompt 都包含上一轮的分析结论和下一步的具体方向。 Agent 不是在「盲跑」——它在每一步积累理解,然后把理解注入下一步的指令里。

这种自我提示的质量,是区分「好 Loop」和「烂 Loop」的核心指标。好的自我提示有几个特征:

信息增量。 每一步的 prompt 都包含上一步的新发现,不只是重复「继续修 bug」。Agent 是在建构一个越来越精确的问题模型。

方向收敛。 随着 Loop 推进,每一步的目标越来越具体、越来越接近根因。如果三轮之后 self-prompt 还在说同样的东西,说明 Loop 在兜圈子。

适时转弯。 当新证据表明当前方向是错的,self-prompt 要能明确提出换方向——「之前的假设是 X,但新数据表明 Y,我需要重新从 Y 出发。」

Boris Cherny 有一句话被广泛引用:「我不再给 Claude 写 prompt 了。我写 loop,loop 替我写 prompt。我的工作是设计 loop。」这句话的核心含义是:从 prompt engineering 到 loop engineering 的转变,就是把「一次性写好指令」升级为「设计一个能持续生成和修正指令的系统」。

Claude Code 里的 CLAUDE.md 文件是这种思路的一个落地——Agent 在任务中发现自己犯了重复性错误,就把教训写进 CLAUDE.md,这样后续所有会话都能受益。这是一个跨 Loop 的自我提示:不仅是单次任务的循环,还是跨任务的知识积累循环。


Loop 的工程化:从手写到系统

2026 年 6 月,Loop Engineering 从一个非正式的模式变成了一个命名的学科,很大程度上是因为两个产品的功能发布让它变得可操作了。

Claude Code 的 /loop 和 /goal. /loop 让 Agent 按固定节奏反复执行——适合定时巡检、定期检查类的任务。/goal 让 Agent 持续跑直到一个可验证条件达成——「所有测试通过」「CI 变绿」「PR 通过所有 review gate」。Boris Cherny 说 /loop 是他目前最喜欢的功能——因为它把「人盯着 Agent 跑」变成了「设定目标,Agent 自己跑到达标」。

OpenAI Codex 的 Automations. Codex 在 2026 年 4 月发布的 Automations 功能,让 Agent 可以在没有人类触发的情况下自动运行——每天定时检查 issue 列表、自动分类和打标签、甚至自动修简单的 bug。OpenAI 内部用这个功能做日常的 issue 分类和 CI 失败总结。这是 Loop 从「人驱动的循环」到「事件驱动的循环」的关键一步。

把这两个产品放在一起看,Loop Engineering 正在从「每次跑一个任务」进化到「持续运行的自治系统」。这不再是单个任务的循环,而是多个 Loop 并行、互相触发、持久运行的架构。

Addy Osmani 给 Loop Engineering 定义了六个构成原语:automations(自动触发)、worktrees(隔离工作空间)、skills(可复用能力包)、connectors(外部系统连接)、sub-agents(子任务分解)、external state(跨运行持久状态)。这六个东西在两个产品里的映射惊人地一致——说明 Loop 的设计模式正在收敛。


一个好的 Loop 长什么样

验证、失败恢复、自我提示,三者不是并列的模块——它们是咬合在一起的。验证发现了问题,失败恢复判断问题类型,自我提示生成新方向,然后下一轮验证检查新方向对不对。三个齿轮转起来,就是 Loop。

一个好的 Loop,我觉得有几个共同特征:

验证不是「最后一步才做」——它是每一步之后都做,越早发现问题,恢复成本越低。

失败恢复不是「再试一次」——它是先分类再处理,确定性失败直接修,逻辑性失败重新推理,环境性失败等待。

自我提示不是「继续」——它是带着新发现往前进,每一步的 prompt 比上一步更精确、更接近根因。

跨 Loop 的知识不丢失——每次失败都是一次学习机会,教训要被写进持久记忆里供未来所有 Loop 使用。

下一站,把 Harness 和 Loop 叠起来看真实案例。Claude Code 和 Stripe Minions,两个目前最成熟的 Agent 系统,用三层模型(Model + Harness + Loop)完整拆解。


下一篇预告:工程实践与案例分析——用三层模型拆解 Claude Code 和 Stripe Minions,看 Harness 和 Loop 在生产环境里到底怎么配合。