智能体行为失当:如何设计内循环以保住人工审查注意力
Agents Behaving Badly: engineering the inner loop to preserve review attention
文章提出用"一致性契约"定义完成标准:由独立评估器判定候选代码是否满足要求,让人类审查从证据而非声明出发。NBER 对 50 多万名 GitHub 开发者的研究显示,采用交互式编码智能体后第 21–30 周每周改动行数增加 958%、PR 数增加 86%;Faros 数据则显示 AI 高采用率伴随合并 PR 增加 98%、审查时间延长 91%。
摘要
AI 辅助代码生成可以缩短产出代码所需的时间,同时增加人类理解与验证代码所需的时间、注意力和判断力,从而在软件开发流程的后期形成瓶颈。本文介绍如何设计流程,以保住人类的时间、注意力和判断力。
以下大纲概括了本文的主要论点:
- 终端评估:定义“完成”。一致性契约规定代码必须做什么、必须保留什么以及绝不允许什么,并由独立评估者判定候选代码是否满足该契约,因此人工审查从证据出发,而非从声明出发。仅凭最终结论只能说明系统达成了什么,而不能说明它是如何达成的。
- 设计内循环:尽早纠正错误。做好准备、观察实际发生的情况、将信息缺失与智能体失误区分开来,并在证据支持时介入,以减少达到符合契约的候选代码所需的时间、token 和重试次数。
- 学习循环:优化所有阶段。来自成功与失败运行的经验证据表明,哪些做法、检测器和纠正措施值得保留,以及随着模型和工具的变化,何时应将其淘汰。
有两份附加文档随本文一同发布:
- 设计内循环:准备、失败模式与应对 —— 常见 AI 失败模式目录,以及检测和纠正每种模式的建议。
- 跟踪候选代码从一致性契约到人工审查的全过程 —— 本文所述流程的一个示例(并非实际运行记录)。
引言
AI 辅助软件开发中的两个根本挑战是:精确且完整地表达意图,以及验证生成的代码是否满足该规范。本文主要关注这一等式中的第二部分:验证 AI 编写的代码。
AI 辅助代码生成可以大幅提升编码活动量。一篇覆盖 50 多万名 GitHub 开发者的 NBER 工作论文估计,在采用后的第 21–30 周,交互式编码智能体使每周更改行数增加了 958%,创建的 PR 增加了 86%,而每周仓库发布量增加了 20%。但据估计,编写和测试代码仅占从最初想法到产品发布所需时间的约 25–35%(Bain)。更快地生成更多代码会如何影响软件开发生命周期(SDLC)的其余部分?
更快的 AI 辅助代码生成可能造成的验证瓶颈
更快、更便宜的代码生成可能在下游流程中造成新瓶颈,或加剧现有瓶颈。验证变得更繁重的原因有五个:
-
代码到达的速度超过人类审查的速度。 智能体可以在比读完这段话更短的时间内生成一千行代码,而人类的阅读速度并未改变。Osmani,Agentic Code Review。Faros 的遥测数据将高 AI 采用率与合并 PR 增加 98%、审查时间延长 91% 相关联。Faros 2025。这样的数量可能超出审查能力:在 Faros 更大的 2026 年数据集中,未经任何审查(人工或智能体)即合并的 PR 增加了 31.3%,作者认为这更可能是审查者无法跟上进度所致,而非有意绕过监督。Faros 2026。
-
不正确的代码看起来仍然非常合理。 找出错误可能需要更多时间,跨文件追踪变更并将行为与需求进行比较。JetBrains–Lund 研究。在 Sonar 的 2026 年调查中,61% 的开发者认同 AI 可以生成看起来正确但不可靠的代码。Sonar。METR 2025 年初的研究也指出,花在审查、测试和修复不可靠 AI 输出(包括开发者最终丢弃的输出)上的时间,是导致任务完成变慢的一个因素。METR 分析。
-
理解债务。 如果团队中没有人编写过实现,审查开始时就不具备人类作者通常会带来的理解。Osmani 将代码与人类理解之间日益扩大的差距称为理解债务,并指出阅读彼此的 diff 过去会作为副作用传播对系统的了解。Osmani,Agentic Code Review。在 Anthropic 一项针对 52 名学习新库的工程师的试验中,使用 AI 辅助的人完成时间大致相同,但在后续理解测验中得分低了 17 个百分点(50% 对 67%)。Anthropic。
-
变更更大,问题更多。 Faros 将 AI 采用与平均 PR 大小增加 154%、每位开发者 bug 数增加 9% 相关联;其更大的 2026 年数据集报告该数字为 54%。Faros 2025,Faros 2026。在一项针对 470 个开源 PR 的研究中,CodeRabbit 发现 AI 共同创作的变更每个 PR 携带的问题约为 1.7 倍。CodeRabbit。因此平均而言,每次审查可能覆盖更多变更,也有更多需要修复的内容。
-
检查也不可靠。 测试和静态分析有帮助,但没有人能为他们没想到要指定的行为编写测试。当 AI 改变行为并更新数百个测试以匹配时,问题就从“这段代码正确吗?”转变为那些测试变更是否必要。Osmani,Comprehension Debt。因此,一个通过的测试套件可能意味着测试被重写以与代码一致,这就是为什么评估者的检查和预期结果需要置于构建者无权更改的范围之外。
你将学到什么
本文提供三件事:
- 清晰定义完成。 一份一致性契约,说明代码必须做什么、保留什么、绝不允许什么,以及一个独立评估者来决定候选方案是否满足它,从而让人类审查从证据而非声明开始。在此过程中,将提示工程、规范驱动开发、循环工程和智能体基准视为一个共享过程,并了解基准分数能告诉你什么、不能告诉你什么。
- 尽早纠正错误。 如何减少达到符合要求的候选方案所需的时间、token 和重试次数:做好准备工作,观察发生了什么,将缺失信息与智能体错误区分开,并在证据支持时进行干预。
- 优化所有阶段。 一个学习循环,评估整个过程中的成功与失败,以决定哪些实践、检测器和纠正措施值得保留,以及何时随着模型和工具的变化将其淘汰。
过去十二个月里,我们一直在开发这些方法,并且运行了自己的流水线,用它来生成代码。为了让示例代码保持简洁、易于理解,我们选择了说明性示例,其中一些是假设性的,而非我们自己运行的结果。本文不报告实测的节省量;该方法旨在让你在自己的工作流中进行测试。
1. 终端评估
什么是终端评估?
终端评估只评判自主尝试的结果,不评判其他任何东西。给定一个任务和成功标准,AI 系统自主工作,直到它认为自己已经生成了满足预定义成功标准的结果。然后由评估者对照标准检查该结果。在编码工作流中,结果是一个候选方案,标准是商定的规格说明。判定结果可以是通过或失败、部分得分或多项得分。最终判定告诉我们结果是否满足标准,但对系统如何达到该结果一无所知。
该判定让我们可以提出两个不同的问题:
- 能力:这个已配置的系统能否执行该任务?成功的结果表明,在受测条件下它可以做到。
- 可靠性:它成功的稳定性如何?在可比条件下重复该任务,可以让我们估计这种稳定性。一个成功一次的系统,与一个在 100 次尝试中成功 99 次的系统,所展示的东西是不同的。
这两个问题都关乎一个已配置的系统,而非仅关乎模型。配置包括供应商的模型和运行框架(合起来即供应商的智能体),以及我们在其周围添加的任何东西:自定义运行框架、工具、上下文、运行限制、图或流水线。改变其中任何一项,结果都可能改变,因此必须针对新配置重新测量能力和可靠性。
为了进行公平比较,请使用相同的任务和成功标准,保持预算和重试策略可比,并纳入不成功的尝试。
同一主题的变体
基于智能体的基准测试(评估)、提示工程、规格驱动开发(SDD)和循环工程,是同一底层过程的四种变体:给 AI 一个任务,让它自主尝试该任务,然后评估结果。每种变体强调该过程的不同部分,但都不禁止采用其他变体所强调的实践。
例如,独立评估者、强制停止条件和自动交接通常与循环工程相关联,但没有什么能阻止 SDD 方法采用自动交接。它们是否存在取决于系统的实际设计。开发者认为自己正在实施的方法论,既不保证它们被包含,也不禁止它们被使用。
图 1:一个过程,四种方法。展开每种方法以查看实践和引用。共享路径包括返工、重试耗尽和升级;没有哪一条是某种方法独有的。
合作编写一致性契约
在我们的编码工作流中,人类在运行前批准各项义务,并在之后决定是否合并合格的候选方案。这些决策将人类判断置于 AI 自主工作的两端。人类和 AI 可以合作履行这两项职责。Osmani,Own the Outer Loop。
在流程开始时,人类和 AI 可以协同将意图转化为义务:代码必须做什么、必须保留什么、绝不允许什么。与其让人类独自编写这些义务,然后隔着墙把它们扔给 AI,不如让人类和 AI 合作编写和完善它们,并在出现歧义时加以解决。我们将这些经批准的义务称为一致性契约。人类最终负责确保一致性契约全面表达意图。意图在一致性契约中被指定得越准确、越完整,错误就越难从评估者眼皮底下溜过。
将义务转化为检查
每项义务还需要一种评估一致性的方式。在构建开始之前,人类和 AI 共同制定检查、预期结果和证据要求,确定哪些可以自动检查,哪些仍需要人类判断。测试、抽象语法树(AST)检查和运行时观察可以为特定属性提供证据,并且可能足以表明所考虑的候选实现已满足一致性契约中的某些义务。检查设计必须同时处理违规行为和预期行为:一个既能通过预期实现、也能通过有缺陷实现的检查,几乎证明不了什么。契约及其权威检查在有界运行期间保持固定。任何 AI 代理都不得在运行过程中悄悄更改义务或检查。相反,它可以提出更改建议,如果被接受,则需要重新运行整个流程。
评估候选实现
当构建返回一个候选实现时,控制器代码会调用一个独立的评估者,使用这些检查依据契约对其进行评估。评估者位于构建循环之外。它的检查、预期结果和停止规则不在构建者有权更改的范围内。它记录评估了哪个候选实现、运行了哪些检查、发现了什么以及哪些仍未验证。构建者的完成消息并不决定是否合格,缺失的证据不能算作通过。独立性保护评估不受构建期间所做更改的影响;它并不能消除需求或检查覆盖范围中的缺口。
停止条件决定接下来发生什么。满足合格要求的候选实现进入人工审查。被拒绝的候选实现连同未通过的义务和支持性发现一起返回构建阶段,前提是仍有重试机会。重试次数耗尽则停止运行,且没有合格的候选实现。需要人类判断的歧义或其他问题会暂停流程并提出该问题。这些决策由控制器强制执行,而不是留给构建者自行决定是否继续或宣布完成。
人工审查
一旦评估器判定某个候选方案合格,人类就必须决定是否接受它。这正是运行前准备好的各项检查发挥作用的地方。凡是能够确定性验证的内容都应加以验证:测试、AST 检查与运行时观察能够解决它们所能承担的职责,而它们记录的结果就是既定事实,审查者无需重新推导。剩下的则是任何机械检查都无法裁定的主张,例如需求是否捕捉到了意图、行为是否符合产品需要,以及该变更如何融入周边系统。AI 会为每项职责汇集一个视图,将职责本身、检验它的各项检查及其结果、为满足它而生成的代码、未解决的问题以及与之相关的其他证据整合在一起,使审查者从需要判断的主张出发,而不必从头重建证据。
通过这种方式,确定性验证将人类的注意力与判断力预算引导到真正需要它们的主张上。可靠的判定让审查者能够依赖既定结果,专注于尚未解决的判断,把精力花在证据耗尽之处。这种依赖取决于检查覆盖率以及与候选方案绑定的证据,并且不确定性要像通过结果一样可见;一个薄弱的检查,或者一个能让有缺陷实现通过的检查,几乎确立不了什么。审查者仍然需要理解该变更如何融入周边系统及其后果是什么。即便 AI 无法裁定这一判断,它也能帮助汇集和审视证据。由人类决定是否合并。
一个例子:存储读取失败
考虑一个无法读取先前已保存数据的应用程序。其契约要求它报告失败并保留原始数据。一个报告了错误但用空列表覆盖数据的候选方案只满足了该职责的一半。评估器必须同时检查失败响应和已存储数据的保留情况。
随附的 演练 通过这个例子展开,其中的示例文档展示了符合性契约、可执行检查、对有缺陷候选方案的拒绝、修复以及移交人工审查。其 审查包 将需求与变更后的代码及检查结果关联起来,同时指出审查者仍需解决的问题。应用程序是否使用了被评估的代码路径?所选案例是否充分?恢复行为是否符合产品需要?该候选方案的历史仅作说明之用,并非一次记录在案的运行。
仅凭最终结果无法解释什么
当我们只衡量最终结果时,就把开发候选方案的自主过程当作一个黑箱。判定结果并不显示中间的计划、变更、检查或修正。一次成功的尝试可能毫无差错地推进;另一次可能引入若干错误并从中全部恢复。两者得到相同的成功判定。一次失败的尝试告诉我们系统未达到标准,但仅凭判定本身无法解释它在哪里或为何失败。最终判定具有 较低的诊断分辨率:它们报告结果,却让过程的大部分得不到解释。
要理解这些差异,就需要审视中间过程以及一个结果如何影响下一个结果。我们需要看到错误在哪里出现,它们是传播了还是被纠正了,以及这些纠正付出了多少时间和 token 代价。仅凭最终判定无法回答这些问题。更广泛的可靠性评估还会考察轨迹、鲁棒性以及失败的后果。普林斯顿可靠性研究。
思想实验:假设评估是完美的
为便于论证,假设一致性契约捕获了所有意图,且评估器和资格规则都是完美的。只有符合该完整捕获意图的代码才能被认定合格并提交人工审查。这是一个思想实验,并非对当前系统的断言。它保证的是合格候选者的正确性,而非构建过程一定能在预算内产出一个合格候选者。
即使有这道完美的关卡,构建过程在产出正确候选者的途中仍可能犯错、恢复并浪费工作。更早的检测和纠正能在时间、token 和人工注意力上节省多少?更早的检测和纠正是否意味着能在给定的重试预算内产出合格候选者?这些就是接下来我们深入构建循环内部时要考察的问题。假阳性(即尽管违反某项义务却仍通过审查的候选者)可能减少的情况,属于后续讨论,届时我们会放宽完美评估的假设。
2. 设计内循环
回到第 1 节中的存储读取示例。该示例的一致性契约包含义务 TD-08:当存储的数据无效、不可读或不受支持时,应用程序必须返回可区分的读取失败结果,且不得覆盖或清除原始存储字节。我们将沿着该义务中“保留”这一半,追踪其经过准备、规划交接以及可能发现其遗漏的检查的过程。
在构建循环内,智能体、流水线或图会进行规划、编写、检查和修订,以构建符合给定规范的代码。构建和外部评估构成内循环;人类设计与审查则界定外循环。扩展流程地图将这些职责一并展示。
在我们的完美评估器假设下,内循环中的外部评估正是确立所生成代码候选者正确性的环节。让我们深入构建循环的内部运作,看看如何改进为评估器产出候选者的路径。
我们关注构建循环中两类错误来源,它们需要不同的应对方式。它们并非唯一可能的来源;能力限制、工具故障以及契约或检查中的缺陷也很重要:
- 环境性(缺少前提条件):智能体缺少它需要的东西,例如某项义务从未到达它那里、缺少应用程序或 API 知识、上下文被截断或淹没,或者某个工具行为异常。
- 智能体失败模式:智能体拥有所需信息却仍然出错,例如忽略明确要求、误读清晰的工具输出,或在有记录失败的情况下仍报告检查通过。
一项关于编码智能体失败的研究说明了第二个来源为何重要。失败作为过程考察了基于终端的编码智能体如何失败。研究人员在 Terminal-Bench 任务上,将七个前沿模型分别运行于三种编码智能体脚手架中,保留了 1,184 条失败轨迹和 610 条成功轨迹。对于每次失败运行,他们识别出一个决定性的错误,即决定最终失败的那个错误,这是事后识别的,不一定是第一个出现的错误,并对其根本原因进行了分类。大多数决定性错误(57.9%)是认知性的,而非能力相关的:智能体错误处理了它已经拥有的信息。他们的类别包括规范忽视、输出误读和被忽略的信号。他们还发现,成功的运行中包含错误随后恢复的情况。总之,这些发现支持考察判定背后的过程,而不仅仅是判定本身。
这项研究对我们的目的有用,但它回答的是与我们不同的问题。它的类别与我们所说的智能体失败模式(定义见第 2 节“区分缺失前提与智能体错误”)有重叠,但重叠并非等同。它们并非由我们更窄的测试来定义,即智能体在相关步骤是否拥有充分、准确且可用的信息,因此我们无法说它统计的错误中有多少符合我们的定义。该研究还每次失败运行只统计一个决定性错误,而在我们自己的运行中,我们经常在单次运行中看到多种失败模式,因此其占比无法告诉我们每种模式总体上出现的频率。而且,尽管它分析了恢复,它并未单独区分我们这类错误,因此它无法告诉我们其中有多少可以恢复,无论是智能体自行恢复还是通过干预恢复。
了解我们想知道的内容需要进一步的工作:标注一次运行中的每一个错误,而不仅仅是决定性的那个;根据我们的定义对每个错误进行分类,这意味着要确定智能体在该步骤拥有什么信息;测量每一类错误被恢复的频率,包括自行恢复和通过干预(如针对性检查或纠正)恢复;并在模型、框架和任务之间重复这些测量,进行足够多的重复运行以考虑尝试之间的差异。在此之前,请将 57.9% 视为证据,表明错误处理可用信息很常见且值得考察,而不是我们可以应用于自己循环的比率。我们将这项工作留给后续研究。
配套的演练,跟随一个候选方案从一致性契约到人工审查,跟随一个需求从一致性契约到人工审查:义务 TD-08,在本节开头有所描述。这里我们深入构建循环内部,看看在产生满足该需求的候选方案的过程中,错误是如何产生的。在这个例子中,一个从未被告知失败的读取必须保留已存储数据的规划阶段存在环境问题。一个被告知了这一点,却仍然计划用空存储替换不可读数据的规划阶段,则存在失败模式。
这两个来源出现在构建循环的不同位置,因此我们以不同方式处理它们:
| 错误来源 | 在存储读取示例中 | 出现位置 | 主要应对方式 |
|---|---|---|---|
| 环境性:智能体缺少所需之物 | 规划阶段从未获得义务 TD-08,或者不知道已存储数据可能不受支持或不可读。 | 在于一个阶段如何被设置:它接收到的义务、上下文、工具和交接。 | 通过为成功做好准备来预防它。通过检查实际到达该阶段的内容来发现它。 |
| Agent 故障模式:Agent 拥有所需的一切,却仍然出错 | 规划阶段负有义务并掌握相关事实,但它的计划却用一个空存储替换了不可读的数据,而不是将其保留。 | 在 Agent 在某个阶段自身的决策和行动中,通常发生在交接时或它报告结果时。 | 通过安排工作的方式来减少暴露,然后观察发生了什么,在正确的节点检查并纠正。 |
许多真实事件同时混合了两种来源,而现有记录往往无法说明究竟发生了哪一种。我们将这种不确定性视为需要保留的信息,而不是靠猜测来消除的麻烦。以下三项活动遵循该表:第一项主要预防环境错误。观察和纠正适用于任一来源:检查可以在原因已知之前就确认缺陷,并为修复提供依据。
下图概述了本节其余部分将要介绍的构建循环:准备上下文并行动、可选的检查与纠正、提交给评估器,以及跨运行延续的学习循环。步骤底部的标签标明了接下来描述的三项活动各自适用的位置。
三项活动改善了为评估器产出候选方案的路径:
- 为成功做好准备(PREPARE 步骤)。为每个阶段准备所需的上下文和工具,并安排工作以避免可预防的错误。
- 观察发生了什么(CHECK 步骤)。检查中间工作是否存在可观察到的错误,将缺失的前置条件与 Agent 的错误区分开来,并在做出任何更改之前记录所发生的情况。
- 当证据支持时进行干预(DECIDE 和 CORRECT + VERIFY 步骤)。判断证据是否支持进行纠正,然后在证据可靠的最早节点纠正工作并验证纠正。
ACT 步骤是 Agent 自身的工作,SUBMIT 将候选方案交给评估器。这三项活动改善了它们周围发生的事情。
一份配套指南,Engineering the Inner Loop: Preparation, Failure Modes and Responses,为这三项活动提供支持,我们会在过程中引用它。它从困难的成因出发,因为不完整的规范、缺失的信息或失效的工具需要与 Agent 的错误不同的补救措施。接着,它将常见问题——例如目标不明确、信息过时、上下文过多、权限模糊、任务过大和评估薄弱——与设计实践、证明其有效的证据以及衡量成本配对。然后,它列举了十五种反复出现的 Agent 行为,例如不忠实的交接、跳过的工作以及未经证实的检查通过声明,每种行为都附有建议的检查和响应。最后,它展示了学习循环如何选择保留哪些机制。每当你定义 Agent 的任务、流水线阶段或两个阶段之间的边界时,都可以将其用作设计检查清单。它的模式和检查是可供测试的工作指导,而非详尽的分类体系或经过验证的检测套件。
活动 1:为成功做好准备(PREPARE)
一个阶段是构建循环中的一个工作单元:单个 agent 会话中的一个步骤,流水线中的一个角色(如规划、实现或审查),或图中的一个节点。阶段之间通过交接传递工作。每个阶段设置得如何,以及阶段和交接如何安排,决定了有多少错误会到达后续检查。以下指导来自我们与 agent 协作的通用原则,涵盖支持性环境、上下文策略、验证和实现。配套文档中关于准备工作的一节对此进行了汇总。
给每个阶段它所需的东西
给每个阶段明确的职责、相关的义务、准确的应用和 API 知识、合适的工具,以及获取更多信息的途径。当工作在阶段之间移动时,保留需求和未解决的问题。在控制器代码中强制执行可机械检查的权限和强制转换。配套文档中的预防性设计指导将这些实践汇集在一起。
一次性提供所有内容与提供有用的上下文并不相同。Anthropic 的上下文工程指导描述了渐进式检索以及在压缩过程中丢失重要细节的风险。更窄的任务和专门的 agent 有助于管理信息,但每次交接都会引入另一个丢失信息的机会。对于存储读取示例,TD-08 的两个部分——报告失败和保留已存储的数据——以及关于存储接口的相关事实,都需要到达对其做出决策的阶段。
有意识地设计阶段和交接
在添加检测器之前,先问工作的安排是否正在制造困难。在规划—实现—审查流水线中,实现阶段需要控制性义务和相关的应用事实,而不仅仅是规划者的结论。交接应携带对这些来源的引用、已做出的决定和仍未解决的问题。它应指明它描述的是哪个候选方案或起始状态。这些要求同样适用于单个 agent 会话内的阶段和独立的 agent。
设计每个阶段的一个有用方法是回答五个问题:它负责什么,它必须知道什么,它可以改变什么,它必须返回什么,如果它无法完成会发生什么?然后检查阶段之间的边界。如果两个工作者可以编辑同一状态,它们的更改如何协调?如果一个工作者返回不完整的结果,后续工作能否将其与完成区分开来?在可以机械强制执行的地方,将规则放入控制器代码。在需要解释的地方,保留证据和升级途径。
对于我们的规划阶段,这意味着规划应用在无法读取已存储数据时如何响应,了解存储如何加载和保存,并有权提出实现工作,同时保持已批准的义务不变。它的交接必须保留义务的两个部分——报告失败和保持已存储字节不被改动——并指明未解决的问题。关于存储接口的缺失事实应导致检索或明确的阻塞,然后实现才能依赖该计划。
拆分工作可以减少每个智能体必须处理的信息,但也可能把需要放在一起考虑的事实割裂开来。将失败读取报告与已存储数据保留放在同一个任务中,可能比分别委派、之后再修复集成错误更可取。单独的审查者可能带来有用的审视,也可能只是重复同样的误解。把拓扑结构视为一种需要测试的设计选择。更长的提示词或更大的图结构本身都不是解决方案。
活动 2:观察会发生什么(CHECK)
在改变循环之前,我们需要知道实际出了什么问题。区分这两类错误来源,有助于把需求、信息传递、工具和协调方面的问题,与智能体如何使用所收到内容方面的错误区分开来。
区分缺失的前提条件与智能体错误
在本文中,智能体失败模式是指在已配置智能体所展示的能力范围内,尽管在相关步骤拥有充分、准确且可用的知识和上下文,仍反复出现的不正确决策或行动模式。失败模式引发的错误是被观察到、且被支持为符合该模式的一个实例。例子包括忽视明确需求、误读清晰的工具输出,或在有记录失败的情况下仍报告检查通过。
这一区分很重要。缺少必要 API 知识的智能体需要被提供这些知识。而收到明确需求却将其忽视的智能体,呈现的是另一类问题。已确认的缺陷可以值得修复,即使其原因仍未解决。这些模式不必在每次尝试中都出现,而且无论是自发恢复还是被指示纠正,都不保证会发生。
内循环工程伴侣将通用原则与智能体行为目录结合起来。缺失知识、上下文过多和不完整规范属于其预防性设计指导;行为条目则针对在前提条件充分的情况下仍出现的错误。每个条目都将一种可识别的模式与建议的检查、响应以及纠正验证联系起来。用这些来选择要调查的机制;它们不是详尽无遗的分类法,也不是经过验证的检测套件。
先观察,再干预
一个实用的起点是以观察模式运行拟议的检测器:记录其发现而不改变构建过程,然后检查接下来发生了什么。对于存储读取示例,记录规划交接是否在读取失败时保留了已存储数据,以及实现如何处理它。智能体恢复了吗?评估器拒绝了候选方案吗?该信号是否涉及真实缺陷?这可以在添加中断之前揭示放置不当或误报过多的问题。它不能告诉我们如果进行纠正会发生什么;那需要下文讨论的对比运行。
活动 3:在证据支持时进行干预(DECIDE & CORRECT + VERIFY)
在循环中追踪一个遗漏
回到存储读取示例。规划智能体收到义务 TD-08 以及关于存储接口的相关事实;假设它已展示出处理这类变更的能力。
在这个假设情境中,它的交接仍然计划通过保存一个空存储,然后报告读取失败,来从一个不受支持的已存储版本中恢复。该计划报告了失败,但丢弃了保留原始数据的要求。随后有一个实现阶段遵循该计划,已存储的数据被覆盖。源契约从未被更改。错误出现在一个中间产物丢失了一项义务,而后续工作又依赖它的时候。这说明了该伙伴的不忠实交接模式。
实现者可以重新阅读契约并进行恢复。在我们的完美评估器假设下,如果最终候选没有做到这一点,它就会被拒绝。这两种可能性都不能使这一遗漏对过程无害:在修正开始之前,依赖它的代码和测试可能已经围绕它构建起来了。一个只收到缩短版交接的下游代理也存在信息缺口;这并不会自动构成另一次独立的失效模式激活。
我们可以在哪里介入?在交接时,在依赖它的实现开始之前,将拟议的工作与相关源义务进行比较。一份明确的义务标识符列表允许对缺失引用进行机械检查。确认该计划实际上保留了它们的含义可能需要语义审查。仅有一份完整列表是不够的:在我们的例子中,一个通过标识符引用 TD-08 但提议覆盖数据的计划会通过第一项检查,却无法通过第二项。
如果确认存在遗漏,就返回一项具体发现:该计划用空存储替换不可读数据,这与 TD-08 保留原始字节的要求相矛盾;指出起控制作用的义务以及受影响的工作。将其恢复到计划中,并修复任何已经由该遗漏衍生出的实现或测试。不要为了迁就候选而削弱契约。
然后使用契约的四个代表性失败来对修正进行行为验证:一个不受支持的版本、一个不是对象的已存储值、一个其 todos 值不是数组的版本 1 信封,以及一个适配器读取错误。对于每一种情况,应用程序都应返回读取失败结果,保持已存储字节不变,并且不进行任何保存调用。缺失数据仍应产生空列表;这检查了修复不是简单地把每一次异常读取都变成错误。还要针对一个故意有缺陷、会在读取失败时覆盖数据的版本运行这些检查,并确认它会因为已存储字节发生变化而失败。这表明这些检查能够检测出这一特定缺陷。这些检查覆盖四个具体案例,而不是所有可能的畸形输入。
有用的证据是源义务、不完整交接、依赖变更、发现、修复以及已执行的检查结果。保留这条链条可以让审查者检查被修正的内容,而无需重建整个尝试过程。它也让我们能够测试这次干预是否有帮助。
检查需要目标和响应
存储读取示例赋予了一个失效模式标签以操作意义:一个可观察的遗漏、一个在传播之前的检查点、一个有边界的修复,以及一种验证它的方法。其他模式需要不同的机制。关于测试已通过的声明可以与执行记录进行比较。反复不成功的修复可以通过候选变更和重复发现来调查。这两种检查都不需要猜测模型的内部推理。
泛泛地要求“寻找失败模式”会让这些决策悬而未决。要选择相关证据在何处变得可用、什么算作一项发现,以及响应应当是纠正、进一步调查、继续工作还是升级。机械检查可以比对标识符或执行记录。模型辅助检查可以评估摘要是否保留了某项需求的含义,但其判断需要加以限定。Anthropic 的智能体评估指南讨论了这些评分器的权衡取舍,包括将模型判断与人工评估进行校准。
对于交接检测器,准备几个小案例:一个在读取失败时保留已存储数据的计划;一个省略了保留要求的计划;一个通过标识符提及 TD-08 但提议覆盖数据的计划;以及一个用不同措辞正确表达保留的计划。检查应当区分遗漏和矛盾,同时不拒绝合法的替代表述,也不将有数据尚未保存时合法创建空存储标记为问题。加入它未经调优的案例。这测试的是该机制能否检测出预期的缺陷,而不是它能否识别自己示例中的词汇。
单独测试纠正。检测器可以正确识别出缺失的义务,却仍然提示出无效的修复。智能体可能会在计划中加一句话,却让实现保持不变;或者停止覆盖数据,却开始将存储缺失视为错误,这与“数据缺失应产生空列表”的要求相矛盾。提供具体的发现和相关来源,限定允许的修复范围,并在之后验证受影响的行为和保留义务。反复失败的修复需要设置上限,并诚实地停止或升级;添加一个纠正智能体并不会让纠正按定义就变得可靠。
时机是另一个选择。对交接而言,有用的检查点是它已准备好指导依赖它的工作时。一份未完成的计划可能合理地省略作者仍在补充的细节。同样,在编辑未完成期间出现的暂时性测试失败,可能并不足以打断智能体。应在证据可靠地确立问题、且所避免的下游工作值得打断的最早时点介入。有些约束必须在行动之前强制执行;可选的质量检查通常可以等到产出一份连贯的成果物之后。
早期检测仍然是一个实质性问题。在Failure as a Process中,一个实验性监控器读取部分轨迹,试图识别出已通过回溯性标记的“锁定”点的运行——在此之后未观察到任何成功恢复。其最佳召回率为 28.8%。这与在已完成的交接中检测特定遗漏是不同的任务,但它说明了从部分历史中识别问题的难度。监控器结果。一份目录为我们提供了调查的目标,但仅仅列出它们并不等于一个检测器。
如上方的构建循环图所示,这些可选的检查和响应与常规的恢复和提交至外部评估并存。
这种介入能给我们带来什么?
比较三种可能的历史:智能体自己注意到遗漏;外部评估器拒绝候选方案并提示修复;或者中间检查在更多工作依赖它之前将其捕获。早期干预可能节省返工。它也可能打断廉价的自我恢复、在虚惊上消耗 token,或引入新缺陷。其价值取决于这些历史之间的差异,包括检查和验证修复的成本。
有证据表明有针对性的干预可能有帮助。Meta 的 Wink 定期检查编码智能体的历史记录并提供纠正性指导。其为期 15 天的生产 A/B 测试报告称,每个会话的 token 减少了 5.3%,工程师干预减少了 4.2%。这些是在该环境下的运营改进;它们并不能确立最终代码的正确性,也不能确立在另一个循环中具有同等的节省效果。该论文单独的恢复评估判定的是所检测行为的停止和进展的恢复,而非独立验证的任务完成。
假设再做一次思想实验,我们能够阻止或纠正我们所针对的每一种行为模式实例,包括它们的下游影响。候选方案将不会包含由这些实例引起的缺陷。消除该错误类别本身并不能确立完整的需求、足够的知识、正确的工具或完成任务的能力。我们仍然需要衡量节省的工作量:有些错误本来可以廉价地纠正,而另一些可能导致了大量返工。实证问题关乎结果和成本的变化,而不仅仅是检测器覆盖了分类法中的多少。
在完美的终端评估下,早期检查不会为合格代码增加正确性保证。当我们放宽这一假设时,额外的检查可能会暴露评估器遗漏的违规并防止虚假的绿色通过。这是一个潜在的额外好处。内循环工程的主要动机是减少达到符合要求的候选方案所需的时间和 token(以及潜在的返工或重试)。
哪些检查值得我们付出成本,针对我们的任务和智能体配置?这是学习循环的职责。
3. 学习循环
改进准备工作或增加检查可以改变生成符合要求的候选方案所需的工作。这种改变是否有帮助取决于原本会发生什么,包括普通恢复、评估器驱动的返工以及干预自身的成本。
- 从设计、构建、评估、人工审查以及发布后发现的缺陷中收集证据。
- 将观察到的问题转化为可测试的变更,然后比较检测、修复、整体结果和人工投入。
- 当智能体或其工作条件发生变化时重新评估支持,并建议保留、修改或淘汰哪些机制。
学习循环利用成功和失败运行中的证据来建议流程改进。Lilian Weng 的 harness-engineering survey 探讨了将 harness 本身作为优化目标的更广泛理念。在此提出的安排中,AI 进行分析和建议;人类批准对循环的更改。
学习循环接收什么并建议什么
来源及其提供的证据
学习循环需要来自流程每个环节的证据,而不仅仅是构建环节。发布两周后报告的缺陷可能暴露出被遗漏的义务、薄弱的检查或失败的修复,而每一点都指向不同的改进方向。其输入来自五个来源:
| 来源 | 它提供的证据 |
|---|---|
| 人工设计 | 版本化的契约、其理由、假设和未决问题,以及从义务到检查的映射。 |
| 构建循环 | 每个阶段接收和返回了什么、检查结果、干预和修复、失败的尝试和恢复。还包括智能体和测试框架配置、上下文和工具版本、运行限制、时间和 token 用量,包括不成功的运行。 |
| 外部评估 | 逐项义务的发现、被拒绝的候选方案、所采用的停止规则及其原因、使用的重试次数和评估成本。不可用的证据保持可见。 |
| 人工审查 | 所审查的候选方案和证据包、提出的问题、审查时间和精力,以及决定及其理由和要求的更改。 |
| 发布之后 | 合并后发现的缺陷、回归和事故,追溯到引入它们的更改。 |
证据如何变成建议
随后,学习循环分四步进行:
- 重建发生了什么。将每个问题追溯到最早有证据的错误、促成该错误的条件以及漏掉它的检查。区分这两类错误来源有助于诊断出了什么问题,区分缺失信息、不完整的规格、薄弱的评估器、工具或协调失败以及智能体失败模式。在记录无法说明的地方,原因保持未知。
- 将问题与候选更改匹配。《一般原则》建议如何准备工作。行为目录建议检查和响应。
- 提出一个有边界的更改。陈述假设以及什么证据会否定它。
- 测试它并给出建议。比较结果和成本,估计检测率和纠正率,并建议保留、收窄、修订或淘汰该更改。由人工批准;随着条件变化,重新鉴定会重新审视该决定。
建议落在何处
由于证据横跨整个流程,建议可以指向其中任何部分:
- 契约准备和审查。如果契约从未要求在读取失败时保留已存储的数据,那么改进交接检查器也无法恢复那项缺失的意图。
- 上下文准备和阶段设计。更好的 API 上下文、更简单的工作流或不同的工作划分,可能消除一个信息缺口,否则检测器会较晚才发现它。
- 检测器和纠正。添加、收窄、修订或淘汰一项检查或其响应。
- 评估。如果义务存在,但测试走了错误的路径,则改进该检查。
- 证据交接。如果审查者花了一小时定位一个已经记录的结果,则改进证据的组装方式。
将观察转化为可测试的更改
利用说明性的存储读取历史来制定一个有边界的提案:在实施之前,将规划交接与其来源义务进行比较,因为修复计划可能比修复由计划衍生的工作成本更低。明确检查点、它可以返回的发现以及允许的修正。说明哪些情况会构成对该提案的反证:频繁误报、相比普通恢复没有改进,或修复引入其他缺陷。这将像这样的遗漏转化为一个我们可以检验的假设。
比较整个过程
在重复的可比任务上测试所提出的交接检查,分别在有和没有干预的情况下进行,保持契约、评估器、代理配置和预算策略固定不变。基线保留普通代理恢复和评估器驱动的返工。通过资格认定或不成功的停止来比较两条路径,包括检查和修复开销。纳入未用于开发该检查的代表性案例;一次成功的修正不能确立可靠的收益。
将四个问题分开:是否发生了错误、检测器是否识别出它、修正是否有效,以及整体运行是否改善。独立于检测器审查抽样的历史记录,以寻找遗漏的错误和误报。保留关于原因的不确定性。附加在一个遗漏上的多个标签不会产生多个事件。
每次比较都从等效的干净状态开始,不将一次尝试的修复传递到下一次。在可行的情况下,随机化或交错条件,以减少服务条件变化解释结果的可能性。一小组手工制作的故障交接可以测试检测;它无法告诉我们这些交接在普通工作中出现的频率。使用代表性任务来估计实际价值,并报告有多少任务和重复支持该结果。
核算应包括:
- 检测:每个相关机会中确认的事件、遗漏的错误、误报以及检查发现问题的及时程度。
- 总成本:准备、协调、每次检查调用、修正和重新检查,包括时间和来自不成功运行的可用令牌使用量。包括设置和维护工作。
- 结果和后果:在预算内完成、回归、逃逸的缺陷以及如果错误未被检测到的潜在损害。一个罕见的数据丢失缺陷可能证明一个仅凭频率会被否定的检查是合理的。
- 人力投入:监督、澄清、审查证据和重建缺失的上下文。构建期间较少的参与可能意味着审查时较少的熟悉度;两者都要计入。
频繁触发的检查可能会中断廉价的自我恢复。更安静的检查可能会遗漏错误或阻止后果严重的逃逸。在证据允许的情况下估计逃逸的可能性和后果,并在不允许的情况下说明不确定性。仅凭信号计数无法决定哪种机制应属于循环之中。
举个简单的算术例子,一项检查在100次调用中每次耗时20秒,在任何修复之前,累计检查时间就达到33分20秒。如果它发现了十个真实问题,那么在这些案例中节省的时间必须覆盖这一总开销以及修正和重新检查的时间,该机制才能在整体上节省执行时间。这十次检测并不等于十次被挽救的运行。并行执行还意味着累计工作量和挂钟延迟是不同的度量。请将时间、token和人力投入区分开来,而不是将它们合并成一个单一的生产力分数。
如果某种机制能实质性减少后果性逃逸或人力工作,那么即使它增加了执行成本,决策仍可能倾向于它。反过来,一次更快的运行如果交给审查者一个更难理解的候选结果,可能只是转移了负担而非减轻了负担。要衡量证据包本身:审查者能否找到起控制作用的需求,检查相关变更,并同时看到支持性结果和未解决的局限?他们能否解释变更后的行为,并识别出其证据中的后果性缺口?在可比的审查案例中,将这些判断与所花时间一起评估,包括纠正误导性证据所需的努力。当更短的审查能保持或提高决策质量时,它才是有用的。
同样的比较也适用于预防性设计。更好的API上下文可能比增加另一个审查者更有效地消除信息缺口。更简单的工作流可能避免交接损失。在可行的情况下,一次只测试一项变更,或者明确正在测试的组合。保留完整历史,这样最终的绿色结果就不会掩盖反复出现的失败或代价高昂的完成路径。
将检测和纠正视为比率
智能体行为可能是随机的:相同的任务和工作条件可能导致不同的错误,或对纠正做出不同的反应。一次成功的修复表明该纠正可以奏效,但并不意味着每次错误出现时它都会奏效。某个特定触发条件仍可能产生高度可重复的错误。记录每种模式出现和被纠正的条件,这样这些比率才能描述该机制将被使用的情境。
在Wink的评估中,一个LLM评判员将智能体在约91%的单次干预对话和约79%的多次干预对话中评为已恢复。恢复意味着被检测到的行为停止,且智能体在后续步骤中取得了前进进展。这些是评判得出的恢复率,不是保证,也不是经过独立验证的任务完成率。
将链条中的每一环都视为一个需要估计的比率:该错误类型在机会中出现的频率、检测器捕获它的频率,以及一旦捕获后纠正成功的频率。从重复的可比案例中估计每一项,并报告有多少案例支持它;少量观察会在两个方向上留下很大的不确定性。三个观察案例中三次成功,与远低于100%的成功率是相容的。
这些比率应当为增加或移除某个检测或纠正机制的决策提供依据,同时还要考虑其成本以及逃逸的后果。一个只在部分情况下有效的纠正,在错误频繁发生或后果严重时,仍然可以有其价值。在依赖某项修复的工作开展之前,先检查每一次尝试的修复;失败或未经验证的修复需要有界的重试、诚实的停止或升级。修复检查本身也有其覆盖范围的局限,而纠正本身永远不能单独使候选方案合格。一个很少需要、或很少奏效的机制,可能不足以证明其开销是合理的。随着模型、测试框架和任务组合的变化,持续进行测量。
随着系统变化重新认定资格
新的模型或供应商测试框架可能会改变哪些支持是有用的。Anthropic 报告称,当 Opus 4.5 基本解决了当初促使他们在 Sonnet 4.5 上采用上下文重置的过早收尾行为后,他们移除了上下文重置;自动压缩仍然处理了上下文增长。这是一个针对特定配置修订支持的具体例子。测试框架设计报告。
在模型、测试框架、工具、上下文策略或任务组合发生重大变化后,重复进行对比。纳入先前的失败案例和有代表性的新案例,并在启用和禁用可选机制两种情况下进行测试。也要重新检查检测器:警报减少可能意味着错误减少、机会减少,或者意味着它不再识别的错误模式发生了变化。如果评估发生了变化,在解读更高的通过率之前,先单独评估这一变化。
当两个智能体版本都可用时,有四种条件可以将智能体自身的改进与机制所提供的改进区分开来:
| 配置 | 可选检查禁用 | 可选检查与纠正启用 |
|---|---|---|
| 较早的智能体 | 确定其常规恢复能力和由评估器驱动的返工情况。 | 在该智能体下估计机制的贡献。 |
| 更新后的智能体 | 在没有自定义支持的情况下测量更新后的智能体。 | 确定该支持是否仍然增加足够的价值。 |
在这些条件下使用相同的任务集和验收标准,并进行重复尝试和记录成本。启用检查时更低的错误率并不能证明智能体已经接管了其职责。禁用条件对于这一决策至关重要。如果无法复现较早的配置,请说明这一局限,并仅依据其自身证据来认定当前安排。
这为“模型吃掉测试框架”提供了一个实用的检验。供应商智能体能否在我们的条件下足够可靠地履行这一职责,且成本和后果可以接受?证据可以证明保留、收窄、改进或退役自定义支持是合理的。当实现方式发生转移时,职责依然存在。移除一项早期干预本身并不能证明移除独立资格认定或人类的验收决策是合理的。
对于是否保留某项检查,并不存在通用的阈值。团队可以仅针对安全敏感的变更保留它,在交接点而非每次操作后运行它,或者用更廉价的机械检查来替代语义审查,以覆盖更窄的属性。记录该决策的范围以及支持它的证据。在变更后继续观察相关结果,以便在出现回归时,学习循环能够建议恢复该支持。
有用的输出是与证据挂钩的建议:什么发生了变化,哪些结果改善或恶化了,代价是什么,以及哪些仍不确定。人类批准闭合了学习循环。从一个反复出现的问题或一项重要义务开始,测试一项有针对性的改进,并持续检查两个结果:更好的候选人,以及让人类审查更容易的证据。如果你尝试过这一点,哪些机制赢得了自己的位置——哪些最终付出的代价超过了它们节省的?
来源:Hacker News · bradleygibbs.dev