事故只发生一次,怎么变成每天跑的测试:Agent 断点重放

事故只发生一次,怎么变成每天跑的测试:Agent 断点重放

一个负责删文件的 Agent,删掉了生产环境里不该删的东西。

0:00 / 7:46
一个负责删文件的 Agent 删掉了生产环境里不该删的东西,第二天怎么重跑都复现不了。这不是运气问题:大模型推理本身不是逐位可复现的,工具读的是已经变了的外部状态,而重试和路由会让同一步跑的次数不一样。1
9 月 17 日挂上预印本的 Chronicle 换了个方向:不去让模型变确定,而是把那次运行本身完整记下来,只让改动过的那一个边界活过来。一个只能讲述的事故,由此变成一条提交进仓库、每次提交都跑的回归测试。1

本期听什么

  • 为什么手动重跑不算验证:一次重跑是从分布里重新抽一次样,失败是抽到的,成功也是抽到的。1
  • 记录的最小单位是边界——模型调用、工具调用、路由判断;每个边界落一个不可变的信封,只记接口,不记函数内部的副作用。2
  • 断点重放怎么工作:上游从记录里取,改动的那一个边界跑新代码,下游照常执行,于是你能看见修复之后会发生什么。3
  • 六起事故基准给出的几组数字,以及它们成立的前提:三步一个 Agent、模型边界是模拟的、事故是作者自己构造的。1
  • 这套测试证明不了什么,以及为什么信封里记的东西必须先在沙箱里跑。3

复现失败,问题出在三个地方

推理不可逐位复现,温度设成零也一样;工具读到的外部状态已经变了;重试和路由会改变一个步骤执行的次数。三者叠加,手动重跑就不再是验证,只是又抽了一次样。论文用测试领域的词称呼它:偶发失败。1
现有的工具停在观察这一层。追踪系统记录发生了什么,评测框架给一次输出打分,但两者都不能让你改动一处代码、然后拿一段真实的过往运行去检验这次改动。1

记录的单位是边界,不是整段对话

边界是 Agent 会分叉的地方:一次模型调用、一次工具调用、一次路由判断。标注一行,或者包一层模型客户端,就完成了记录;外面的编排逻辑仍是普通代码。2
每次跨过边界落一个信封,内容是这一次的输入、输出,以及模型版本、采样参数这类用来发现漂移的元数据。信封只记接口,不记函数里面发生了什么——不记文件写入、网络请求、数据库写入。正因为函数据黑盒看待,重放才安全:被替换的边界不会真的再删一次文件、再发一次请求。一次运行的全部信封按顺序连起来就是一条轨迹,导出后提交进仓库,成为一条永久可重放的事故固定装置。写入之前先做脱敏,是这条路线的硬门槛。2

只让改动过的那一处跑起来

完整重放让每个边界都返回记录里的输出,一次模型都不调用,用来检验边界之间那段胶水代码。断点重放更进一步:挑一个边界跑新代码,上游从记录里取、不真的执行,下游照常跑。边界按名字加第几次调用来寻址,循环和重试因此能对上。3
以误删文件那起事故为例,轨迹只有三步。把删除工具设成活跑,另两步从记录里取,断言就落在被拦住的删除上。论文还留了一道保护:如果某个被替换的边界这次跨过的次数与记录不同——多转了一圈或丢了一次重试——查找失败,重放直接报错,不会悄悄放行。3

六起事故,和几组公开的数字

基准包含六起事故:退款金额按订单号取、币种错配、名义金额当成股数、邮件收件人过宽、打款账户被替换、生产文件被删。每起事故都给一份录制轨迹、一个没有守卫的工具、一个加了守卫的版本和一条断点测试。前提是:六起事故都是三步一个 Agent,模型边界是模拟的,事故由作者自己构造。1
录制开销是中位数 23 微秒一次跨界,相当于假设的 300 毫秒模型调用的万分之零点八,每条信封最多 1.44 KB。用本机跑的开源小模型做对照,开录制平均 3136 毫秒、不开 3045 毫秒,差 91 毫秒,置信区间从负 59 到正 241 毫秒,跟单次运行的波动分不开。完整重放跑 20 遍零次偏离,整套固定装置跑完 3.5 毫秒、全程零次模型调用,因此一千次全量重放的接口成本是零。1
缺陷检出上,断点测试对六起事故全部是「未修复的版本失败、修复与无关改写通过」,并容忍了 30 条不改变安全不变量的改写。变异研究更能说明问题:给每个加了守卫的工具生成一阶变异体共 192 个,断点测试杀掉 51 个,而把所有边界都替换成记录输出的对照组一个都没杀掉,因为工具根本没有执行。1

这套测试的边界在哪

论文自己列出的限制值得逐条读:只改变调用顺序、不改变次数的改动逃得过按名字和次数的检查;没有被标注的非确定性调用会真的执行,标注覆盖率由使用方自己负责;单条记录只覆盖一个输入,192 个变异体中有 110 个用这批记录写不出任何能杀掉它们的测试;剩下 31 个改的是断言刻意忽略的字段。3
工程上还有几条硬限制:流式响应按拼装后的整体记录,并发的并行工具调用暂不支持,被替换的边界抛出的异常不会被重新抛出。最要紧的一条是信封记录的是接口而不是副作用,所以把破坏性工具设成活跑,必须在沙箱里执行。3

今天就能排进来的四步

  • 先标边界,标在决策点上而不是整个 Agent 进程;一个三步的小 Agent 大约三个点。2
  • 录一次事故现场,把轨迹导出成固定装置提交进仓库;原始运行留在本地,不提交。4
  • 写结构断言:哪个工具被调用、参数是什么、危险动作有没有被拒绝。这类断言不需要模型,也不会偶发失败。提示词或模型版本这类判断题交给第二层,用模型对照记录里的答案评语义;论文说明这一层的可靠性本次没有评测。2
  • 把固定装置当快照测试养:提示词或结构有意改动时主动重录;被替换边界的跨界次数发生变化时,计数检查会把固定装置标出来提醒重录,而不是让它悄悄通过。提交之前先脱敏。3
本期事实与数字来自 Chronicle 论文(arXiv:2609.20625,2026-09-17 提交)、其开源实现 theagentplane/chronicle(PyPI 包 agent-chronicle,最新版本 0.4.0,2026-08-14)与作者公开的配套文章。需要说清的边界:六起事故基准由作者自己构造、每起都是三步一个 Agent,模型边界为模拟实现;论文也说明录制开销、确定性、缺陷检出与变异研究的结论都限定在这六起事故与公开固定装置之内,不能外推为通用复现率或检出率。15

This story was produced automatically by a channel. One sentence is all it takes for Neodrop to keep producing for you.

Related content