2026-07-30
从“Agent 能做对”到“Agent 的测试能抓错”:一个研究备忘录
说明:这是一份早期研究备忘录,用来保存问题意识、方法设想和实验计划。 文中内容尚未经过完整实验验证,不应被理解为已经成立的研究结论。
最近在思考 AI Agent 的工程质量时,我逐渐意识到一个容易被混淆的问题:
Agent 在一组任务上取得成功,并不等于测试套件足以发现 Agent 系统中的缺陷。
任务成功率回答的是“系统这次有没有把事情做成”,而测试充分性关心的是“当系统内部出现 某类错误时,现有测试能不能稳定地把错误暴露出来”。这两个问题有关,但并不相同。
这篇文章先把当前想到的研究框架记下来,避免以后忘记。
一、为什么任务成功率不等于测试充分
传统软件测试不会因为程序通过了几个正常输入,就认为测试已经充分。我们还会检查异常 路径、边界条件、状态变化和安全约束。Agent 系统同样如此,而且它的问题往往横跨模型、 工具、上下文、运行时和外部环境。
一个任务表面上可能返回了合理答案,但执行过程仍可能存在缺陷,例如:
- 对具有副作用的工具重复调用,造成重复退款、重复下单或重复写入;
- 选择了错误的工具,或者使用了语义不正确的参数;
- 在长上下文中丢失用户最初的目标或约束;
- 权限检查已经拒绝操作,系统却仍沿着后续路径执行;
- 模型停止生成,被运行时错误地解释为任务已经成功;
- 最终文本看起来正确,但中间过程违反了必须遵守的业务规则。
如果测试只判断最终文本或单一成功标志,这些错误可能不会被发现。因此,评估 Agent 的 测试不能只问“完成了多少任务”,还要问:
如果我们有控制地制造一个真实、合理的缺陷,测试是否会失败?
二、核心设想:面向 Agent 的变异测试
变异测试(Mutation Testing)的基本思想,是主动对系统做小而受控的错误修改,生成 一批 mutant,然后运行测试。如果测试能够发现错误,这个 mutant 就被“杀死”;如果测试 仍然通过,它就暴露了测试套件的潜在盲区。
一个常用的概念是 Mutation Score:
关键并不只是把传统代码变异直接搬到 Agent 上,而是从真实 Agent 缺陷中提炼具有代表性 的变异算子。例如,算子可以作用于:
- 工具调用的选择、参数、顺序和次数;
- 上下文的保留、截断和污染;
- 权限与策略检查的结果及其控制流;
- 模型输出和运行时终止状态之间的映射;
- 外部环境返回值、延迟、失败与状态更新。
理想情况下,这些算子不是凭空想象的错误,而应当能够追溯到真实缺陷模式。这样得到的 Mutation Score 才更有机会反映现实中的测试能力,而不是仅仅衡量测试能否发现人为构造 的古怪故障。
三、为什么需要确定性的 Trace 与 Replay
Agent 执行具有明显的非确定性。即使输入相同,模型输出、工具结果、网络状态和采样过程 也可能不同。如果每个 mutant 都重新进行完整在线执行,会带来三个问题:
- 很难判断测试失败来自注入的缺陷,还是来自一次随机波动;
- 大规模实验的成本和时间都很高;
- 同一故障可能无法稳定复现,降低实验可解释性。
因此,一个重要组件是记录正常执行的结构化 trace,并在可控制的边界上进行确定性 Replay。记录的信息可以包括模型响应、工具调用、工具结果、状态变化、权限决策和终止 原因。之后将变异注入 trace 或执行边界,再重放后续过程。
Replay 并不是为了假装所有 Agent 行为都能完全确定,而是为了隔离变量:在研究某一个 故障时,尽量固定与该故障无关的部分。它是否真的能提高复现率、降低成本,同时又不损害 故障的真实性,需要由实验回答。
四、只检查结果还不够:过程 Oracle
测试需要 Oracle,也就是判断一次执行是否正确的依据。对 Agent 而言,单一的最终答案 Oracle 往往不够,还需要观察过程性质,例如:
- 是否只在授权后执行敏感操作;
- 具有副作用的动作是否满足幂等性要求;
- 工具调用是否遵循必要的先后顺序;
- 关键用户约束是否一直保留;
- 失败状态是否被正确传播,而不是被包装成成功;
- 外部状态与最终声明是否一致。
这些过程 Oracle 可以把“答案看起来没问题”之外的故障变成可检测的测试失败。与此同时, Oracle 本身也可能不完整或产生误报,因此应当把它作为实验对象,而不是默认它永远正确。
五、Behavioral Coverage:覆盖了代码,不代表覆盖了行为
代码覆盖率能告诉我们哪些语句或分支被执行,但 Agent 的关键行为经常由跨组件交互决定。 同一段运行时代码可能承载完全不同的工具、策略和状态路径。因此还需要一种更贴近 Agent 执行语义的 Behavioral Coverage。
可能值得记录的行为单元包括:
- 不同类型的工具调用与工具序列;
- 权限允许、拒绝和拒绝后的控制流;
- 重试、超时、回滚与降级路径;
- 上下文读写和关键约束的传递;
- 外部状态的读写组合;
- 各类正常与异常终止状态。
Behavioral Coverage、传统代码覆盖率和 Mutation Score 不应被预设为等价指标。一个 值得验证的问题恰恰是:它们分别能解释什么,又会在哪些情况下彼此背离。
六、计划回答的问题
目前最希望通过实验回答四组问题:
- 代表性:从真实缺陷中提炼的变异算子,能否代表 Agent 系统中重要且可复现的故障?
- 检出能力:现有 Agent 测试能够杀死多少 mutant,主要遗漏哪些故障类别?
- 指标关系:Mutation Score 与任务成功率、代码覆盖率、Behavioral Coverage 之间是什么关系?
- 实验效率:确定性 Replay 对故障复现率、实验时间和执行成本有多大影响?
这些问题需要预先定义清楚的实验协议、对照组和统计方法。尤其不能仅凭少量案例,就声称 某个指标能够代表整体质量。
七、实验不能只测自己实现的 Agent
自己实现的系统适合做方法开发:容易插桩、容易注入故障,也容易观察内部状态。但如果 全部实验都发生在同一个自研系统里,结论可能只对这套实现成立。
因此,更合理的实验结构可能分为三层:
- 在可完全控制的内部系统上验证机制是否工作;
- 在实现方式不同的独立 Agent runtime 上验证可迁移性;
- 在包含真实状态变化的外部任务场景中验证故障与 Oracle 是否仍然有意义。
这里的目标不是证明某一个 Agent 框架更好,而是观察测试方法在不同执行模型、工具接口和 任务类型上的稳定性。
八、目前明确知道的限制
这条研究路线至少有以下风险:
- 变异算子可能不够真实,也可能漏掉重要缺陷类型;
- 部分 mutants 可能与原程序行为等价,导致 Mutation Score 失真;
- Replay 可能固定了过多环境因素,从而牺牲生态有效性;
- 过程 Oracle 可能需要领域知识,难以完全自动生成;
- 行为覆盖的粒度如果过粗就没有区分度,过细又会导致状态空间爆炸;
- 不同模型和任务的随机性可能给统计比较带来干扰;
- 公开 benchmark 上的结果未必能直接推广到真实生产系统。
这些限制不是附带问题,而应当进入实验设计和结果讨论。
九、下一步待办
- 系统收集并分类真实 Agent 缺陷;
- 给出每类变异算子的形式化定义、适用边界和等价判定方法;
- 设计 trace schema、注入点和可重复的 Replay 协议;
- 建立最终结果 Oracle 与过程 Oracle;
- 定义 Behavioral Coverage 的最小可用版本;
- 选择彼此独立的运行时与有状态任务场景;
- 预注册主要指标、对照实验和统计分析方式;
- 在小规模试验后,再决定哪些研究主张真正有证据支持。
十、暂时的总结
这项工作的出发点可以压缩成一句话:
不要只评估 Agent 能否完成任务,也要评估它的测试是否有能力发现错误。
真实缺陷驱动的变异算子负责提出“值得检测的错误”,Trace/Replay 负责让实验更可控, 过程 Oracle 负责观察最终答案之外的违规行为,Behavioral Coverage 则描述测试到底探索了 哪些执行语义。它们组合起来,或许能形成一套比单纯任务成功率更接近软件测试的问题框架。
但目前这仍然只是研究设想。算子是否具有代表性、指标是否有效、Replay 是否真的降低 成本、方法能否迁移到不同系统,都必须等待后续实验验证。