2026年7月31日 2 分钟阅读

Agent 遇到 429、坏 JSON 和重复调用时怎么测:用 ResiliReplay 把故障轨迹变成回归测试

tinyash 0 条评论

给 Agent 补单元测试并不等于验证它能在真实故障里恢复。一次工具调用可能超时,模型端可能返回截断 JSON,网络重试又可能把写操作做两遍;MCP 服务还会带来 schema 演进、权限失败和有副作用的工具调用。若只断言“这次回答正确”,这些路径通常都没有被覆盖。

ResiliReplay 是一个本地优先的 TypeScript 工具包,试图把这类不稳定性放进可重放、可审查的测试循环。它不绑定某个模型 SDK:核心边界是一种版本化的 TraceEvent,把 Agent 或 MCP 交互记录为 JSONL 轨迹;随后对同一轨迹注入带 seed 的故障、回放并根据声明的证据评分恢复结果。失败轨迹还能被收缩为场景和可执行的 Node 回归测试。

这不是“给 Agent 打安全认证”的工具。项目明确强调:报告只说明某个版本、某个声明测试集的结果;record 会执行你提供的命令,也不是操作系统沙箱。它更适合把发布前的可靠性假设写成可重复验证的工程资产。

为什么重试次数不是可靠性的充分证据

常见的恢复逻辑是“失败后最多重试三次”。但这个规则没有回答三个关键问题:失败发生在哪一层、恢复后是否仍满足业务约束、重试是否制造了新的副作用。

以订单创建类工具为例。若请求在服务端已经落库、客户端却因连接重置没收到响应,盲目重试可能产生重复订单。对于只读查询,重试也许合理;对于发邮件、转账或创建工单,测试应当要求幂等键、补偿动作或人工确认。于是测试的目标不该只是“最终成功”,而应包含:是否识别故障、是否在许可次数内恢复、是否保留安全边界、是否留下足以复查的证据。

ResiliReplay 将这些信息放在轨迹、故障场景和报告中。README 列出的故障覆盖 provider/transport 的延迟、超时、429/5xx、连接重置、截断、坏 JSON、重复与陈旧响应;工具和工作流层还包含权限错误、文件缺失、结果损坏、重复副作用、交接丢失、错误接收者、陈旧状态、冲突指令与循环。重点不是一次性穷举所有组合,而是先挑出对业务最危险的恢复承诺,把它固定下来。

先跑确定性演示,再接入自己的 Agent

该项目要求 Node.js 20 或 22 以及 pnpm。最短路径是拉取源码、构建后运行演示:

git clone https://github.com/aliengineering-byte/resilireplay.git
cd resilireplay
pnpm install --frozen-lockfile
pnpm build
pnpm demo

演示会启动本地确定性子进程,注入三种故障,生成恢复成功与未恢复失败的报告,并把失败轨迹编译为测试。因为确定性路径不需要 API Key、Docker、外部账号、遥测或 LLM 裁判,它很适合先在 CI 里验证测试管线本身,而不是把问题混入模型波动或云端账单。

随后可用 record 捕获某个本地命令的交互,再用 replay 生成报告:

pnpm exec resilireplay record \
  --output runs/agent/trace.jsonl \
  -- node examples/deterministic-agent/dist/index.js

pnpm exec resilireplay replay \
  --trace runs/agent/trace.jsonl \
  --report-dir runs/agent/report

接入真实框架时,适配器需要发出同一种 TraceEvent。官方说明中的 OpenAI-compatible 示例是“翻译用 fixture”,并不声称会调用线上 Provider;因此,落地时应把你自己的请求、工具调用和恢复事件映射进去,而不是把示例误当作生产集成。

用固定 seed 复现一次坏 JSON

可复现性是故障测试能进入日常开发的前提。下面示例对既有轨迹注入 malformed-json,并固定 seed 为 42:

pnpm exec resilireplay inject \
  --trace runs/agent/trace.jsonl \
  --scenario malformed-json \
  --seed 42 \
  --output runs/agent/failed.jsonl

pnpm exec resilireplay replay \
  --trace runs/agent/failed.jsonl \
  --report-dir runs/agent/failed-report

第二条 replay 在最小基线没有恢复事件时会以退出码 1 结束,但仍会写出失败报告——这是预期信号,不应被包装脚本悄悄吞掉。若 CI 需要同时验证预期成功和预期失败场景,可运行项目提供的场景测试:

pnpm exec resilireplay test scenarios

测试设计上,建议把“模型输出坏 JSON”拆成两个断言:解析失败必须被识别;Agent 只能走已声明的恢复路线,例如请求格式化重试、切换到安全降级分支或终止并请求人工输入。不要把“多试几次后出现了一段文本”当作恢复成功。

把一次失败收敛成可维护的回归资产

线上事故最有价值的产物不是一段日志,而是能阻止同类事故复发的测试。ResiliReplay 可以把失败轨迹转换为最小化 fixture、场景、manifest 和 node:test

pnpm exec resilireplay generate-test \
  --trace runs/demo/failed.jsonl \
  --output runs/generated-regression

生成过程默认会立即执行测试;manifest 会以 SHA-256 哈希关联源轨迹、最小化 fixture、场景与测试文件。这里的哈希证明的是这些产物之间的链接和完整性,而非报告真实性,项目也明确说明 manifest 未签名。若团队需要跨系统审计,还应把原始证据、构建版本和执行环境保存到自己的制品库。

报告可输出终端文本、JSON、HTML、JUnit、SARIF 2.1.0、manifest 与 SVG badge。实务上可让 JUnit 进入测试平台、SARIF 进入代码扫描界面、HTML 留给复盘;不要只保留绿色 badge,因为它缺少场景范围和失败上下文。

MCP 审计要从“默认不碰业务工具”开始

MCP 测试的风险高于纯模拟:一次工具调用可能修改远端状态。项目的本地示例允许审计一个自带的 resilient stdio server:

pnpm exec resilireplay mcp audit \
  --command "node examples/resilient-mcp-server/dist/index.js" \
  --output runs/mcp-audit

默认情况下,mcp audit 会捕获 tools/list schema,只调用名为 reliability_probe 的工具。只有在人工审阅工具行为后,才应加入 --call-tools;非 loopback 的 Streamable HTTP 目标还必须显式传入 --allow-remote。这两个限制值得保留在团队封装脚本中,而非为了“全自动”直接绕开。

更稳妥的推进顺序是:先用无副作用的探针测试 schema、超时和错误传播;再为关键写操作准备隔离账号、临时目录或可回滚资源;最后才把幂等、权限拒绝和重复副作用写入场景。项目也提醒,文件系统故障应使用受控的临时目录,输出路径要做包含关系检查。

在 CI 中把“预期失败”当作一等结果

很多团队会把可靠性检查包装成单一的“命令必须退出 0”。这会让故障注入测试变得别扭:真正暴露缺失恢复动作的 replay 应该失败,流水线却可能把失败报告当作构建异常直接丢弃。更好的做法是把场景分成两类:一类证明指定恢复策略能够通过;另一类故意缺少恢复事件,用来证明检测器和报告确实会拒绝它。前者适合做合并门禁,后者适合验证测试框架没有被错误地放宽。

可以把每次运行的 JSON 或 JUnit 报告作为 CI 制品保存,并将 runs/.../trace.jsonl、故障 YAML、生成的回归测试和提交 SHA 放在同一份构建记录里。这样,后来修改重试策略、替换模型 Provider 或升级 MCP server 时,团队能直接比较同一个 seed、同一轨迹的恢复差异,而不是从零开始解释一次偶发失败。对于包含写操作的 Agent,还应在回归场景中显式记录“未执行第二次副作用”或“已走补偿路径”这类业务不变量;仅有较高的 recovery score 不能替代领域断言。

边界与适用场景

ResiliReplay 当前明确列出几项边界:Streamable HTTP 的集成覆盖少于 stdio;流式 Provider 输出在 v0.1.0 会聚合成响应事件;因果收缩在适配器提供 parentIdcauseId 时效果最好。换言之,若你的 Agent 只能记录零散文本日志,先提升事件关联质量,比先堆更多故障组合更有效。

它尤其适合三种场景:为工具调用链建立发布前回归测试;把一次线上恢复失败固化为确定性案例;在引入 MCP 服务或更换模型/Provider 前比较恢复策略。对于需要真实端到端效果的场景,它不能替代隔离环境、权限设计和人工评审;但能把“我们认为它会恢复”变成可以反复运行、可以在 PR 中讨论的证据。

相关链接

发表评论

你的邮箱地址不会被公开,带 * 的为必填项。