通过账户删除功能的真实案例,展示如何建立跨规划、编码、测试、审查、发布、故障的六层反馈循环,让Agent的错误转化为系统性检查。
这就是循环工程在实践中的应用:六个反馈循环,将 AI 编程代理的修正转化为整个交付管道中的持久检查。
我们最近在实现一个允许用户删除账户的功能。一个编程代理实现了端点、添加了测试,并产生了 Pull Request。测试通过了,但审查发现活跃订阅仍未被处理。进一步测试发现,删除所有者还会破坏对共享对象的访问。
每个发现都为我们提供了有关实现遗漏内容的信息。我们希望创建一个适当的流程来利用这些信息:一个纠正当前变更的流程,然后将期望保留下来,以影响后续工作。
这项工作使我们回到了贯穿规划、编码、测试、审查、发布和事故处置的六个反馈循环。为代理的行为设计周期——它行动、观察结果、修正方法——现在有了一个名字:循环工程(loop engineering)。下面的循环将这个概念从编程代理扩展到整个交付管道,这是我我认为大多数工程负责人在设计 AI 优先的工程管道时应该关注的核心。
我们的需求——“允许用户删除账户”——描述了一个意图,但留下了几个产品决策未解决。
删除应该立即执行吗?活跃订阅会发生什么?共享项目的唯一所有者能删除自己的账户吗?
我们达成共识:订阅必须先取消,共享项目的所有权必须先转移,然后才能删除账户。这些决策给了我们具体的测试期望:
拥有活跃订阅的账户不能被删除。
项目的唯一所有者必须在删除前转移所有权。
符合条件的用户可以完成删除。
用户不能删除他人的账户。
AI 帮助我们检查现有实现,揭示未回答的问题和边缘情况。解决预期行为仍然需要产品上下文和工程判断。
我们通过将这些答案写入规范,然后将其转化为验收测试,从而关闭规划循环。如果把它们留在聊天中,下一个实现很容易忽略它们。
在实现过程中,代理需要一个可靠的方式来运行应用程序并检查失败。我们提供构建输出、相关测试和运行时上下文,使其能够检查其变更在哪里破坏了系统。
在一次修正中,删除端点调用服务时使用了错误的参数类型。我们给代理提供了实际的错误信息。它检查了服务契约,纠正了调用,并重新运行了失败的检查。
重新运行很重要,因为仅凭编辑本身无法确定问题已被解决。
Anthropic 关于长期运行编程代理的研究描述了代理在未进行充分测试的情况下宣布功能完成的失败。在其实验中,提供可执行环境并提示端到端验证有助于暴露代码检查遗漏的问题。
我们还定义了何时停止迭代。如果重复尝试产生相同的失败,代理需要返回证据及其尝试的修复方案供审查。任何额外的编辑都需要工程师审核的正当理由。
我们的初始测试覆盖了我们想到要编码的场景。进一步测试暴露了另一个缺口:由于格式错误的查询 ID 导致的订阅查找失败被当作“无活跃订阅”处理。应用程序因此在无法确定资格时允许了删除。
我们达成共识:在这种情况下应阻止删除,然后添加了回归测试来复现该失败。我们检查了它是否在有问题的实现上失败,并在修正后通过。
我们还审查了断言。如果端点已返回错误后再检查,断言删除账户失败是不完整的。我们需要检查结果状态。这个断言缺口值得单独讨论:AI 在软件测试中的作用:为什么生成的测试会遗漏 Bug。
AI 帮助构建了复现场景并实现了修复。我们需要判断测试是否准确地捕获了失败,其预期结果是否与业务规则匹配。
审查揭示了一个我们现有检查遗漏的权限问题。某项所有权检查信任了请求中提供的用户 ID。
修复端点解决了当前问题。我们还考虑了同样错误可能再次出现的地方,以及如何使修正可用于后续工作。
我们添加了跨账户访问测试,使用了已建立的授权辅助函数,并在仓库指南中记录了何时使用它。
这些服务于不同的目的。指南帮助代理选择方法,而测试检查特定结果。
我们没有将每个审查意见都转化为永久规则。我们专注于表达重复性约束的修正,并在代理的下一次实现之前使其可用。埋在已合并 Pull Request 中的关键评论对后续工作来说是一个薄弱的依赖,直到它被正式化。
在发布前,我们定义了决定是否继续上线所需的证据。
Google 关于金丝雀发布的指南解释了如何将变更暴露给有限流量,并将其行为与对照组进行比较来为决策提供依据。
对于账户删除,仅看请求成功是不够的。我们还需要了解后台清理的可见性,以及资格检查中的意外失败。
我们定义了暂停条件,为不同的工程师分配了跨条件的责任,并在进一步部署之前要求恢复。回滚应用程序代码无法恢复已删除的数据。
AI 持续帮助我们检查日志和指标,但上线仍然需要工程师审核的明确决策规则。扩展金丝雀发布成为观察行为的直接函数,而函数规则由我们定义。
后来的一次事故暴露了我们遗漏的一个序列:一个账户变得符合删除条件,同时一个订阅被并发创建,删除使用了更早的资格结果继续执行。
我们重建了这个序列并检查了促成条件。AI 帮助组织了证据并提出了解释,我们对照观察到的行为进行了验证。
后续工作包括并发测试以及资格和删除协调方式的更改。改进检测有帮助,但它解决的是问题的另一个部分,因为仅靠告警无法阻止该序列。
Google 的事后分析指南强调理解促成原因并实施预防措施。我们为后续工作分配了负责人,并定义了验证其是否解决了失败的证据。
从这些生产发现中收集的证据应该被正确地路由回规划、实现和测试阶段。它改变了下一版本每个阶段的期望。AI 帮助我们头脑风暴每个证据大致可以归属于哪个阶段,但所有权的最终决定权在于运行整个循环的工程负责人。
在这六个阶段中,我们需要将四件事明确化:反馈信号、接收者、它可以触发的动作,以及我们将如何验证修正。
代理可以在一次运行中根据反馈采取行动。后续运行需要使相关测试、指令和证据再次可用。我们必须在工作流中设计这种连续性。
整个过程中最容易实现的是:从审查者反复做出的修正,或者已经逃逸超过一次的失败开始。追踪它今天在哪里变得可见,然后构建一个将其提前的检查。用下一个相关变更来验证循环是否真正有效。
原文发表于 nulltensor.com。