Skip to content

H10 · 如何测试和验证 Agent System 的行为? - Testing & Validation ​

所属知识库:Agent 全栈技术地图
所属领域:03 · Agent System
所属章节:03 · 如何让 Agent System 稳定、安全、可控地运行? - Engineering & Governance
文档类型:Agent System 测试策略、验证技术与工程实施专题研究
版本:v1.1
更新日期:2026 年 10 月 29 日
核心问题:面对模型输出的非确定性、工具执行的真实副作用、多 Agent 协作的复杂状态,以及外部系统的动态变化,如何构建分层、可复现、可审计的测试体系,验证 Agent System 的功能、行为约束、可靠性与发布安全?

专题导读 ​

本篇属 Engineering & Governance。传统软件测试主要验证给定输入下的程序行为;Agent System 还要验证模型驱动的行动选择、工具参数、执行轨迹、状态变化、外部副作用以及最终结果。相同输入可能产生不同的合理路径,因此不能将“每次生成完全相同的文字”作为普遍正确性标准。但非确定性不意味着不可测试:可以把系统拆成确定性契约、可观测执行轨迹和具有统计波动的模型行为,分别采用断言、模拟、场景评估和重复实验。

本文延续“技术研究报告 Studio”案例:选题 Agent、调研 Agent、分析 Agent、审核 Agent 在编排器控制下协作,使用检索、文档读取、代码执行和报告发布工具。目标是让开发团队能够从一次本地单元测试逐步建立集成测试、端到端测试、故障注入、回归测试与发布门禁。

研究边界: H3 Evaluation 主要回答“系统表现有多好、相对基线是否改进”;H10 Testing & Validation 主要回答“实现是否满足指定契约、约束和发布条件,如何发现与复现缺陷”。两者共享数据集和执行记录,但用途不同。H2 定义安全边界,H7 定义可靠性目标,H4 定义状态不变量,H5 定义版本绑定,H1 提供观测证据;H10 将这些要求转化为可执行验证。L4/L5 提供被测执行引擎和编排机制。

阅读目标: 能够制定 Agent System 测试金字塔、定义可验证的不变量、设计模型与工具替身、控制非确定性、开展故障注入和端到端验证,并建立可追溯的发布判定流程。

一、测试对象与可验证性边界 ​

1.1 什么是 Agent System 的测试 ​

测试(Testing)是通过执行、检查或模拟来寻找实现与要求之间的偏差;验证(Verification)检查系统是否符合明确规定的设计和契约;确认(Validation)检查系统在目标使用情境下是否满足实际需求。工程实践中三者常交叠,但应区分证据:通过 API 契约测试,不代表报告具有研究价值;通过报告质量评估,也不代表发布操作没有越权。

将一个 Agent Run 抽象为:输入 + 配置版本 + 环境状态 + 模型/工具响应序列 → 执行事件序列 + 外部副作用 + 最终产物。测试必须同时关注过程和结果。模型内部推理不一定可见或可稳定重现;测试重点应放在可观察、可授权和可审计的行为,而不是假设能够完整检查模型的内部思维。

1.2 六类被测对象 ​

对象关键验证问题典型证据
输入与契约非法输入能否被拒绝Schema 校验结果
执行引擎状态转移是否正确Run/Step 事件
工具边界参数、权限、副作用是否受控工具调用记录
协作编排依赖、交接、返工是否正确DAG 与 Handoff 事件
交付结果内容、引用、格式是否合格Artifact 与评分记录
运行保障故障后能否安全恢复故障注入与恢复记录

同一缺陷可能跨越多个对象。例如“报告重复发布”可能源于 HTTP 超时、幂等键失效、任务恢复错误或审批版本未绑定,不能只通过最终报告文本发现。

1.3 三种不同的测试预言机(Oracle) ​

确定性预言机: 明确输入对应唯一合法结果,例如状态机不允许 SUCCEEDED → RUNNING、未授权用户不得发布报告、预算不得超额预留。适合普通断言、属性测试和形式化不变量。

集合/性质预言机: 合法结果不唯一,但必须满足性质。例如报告章节顺序允许变化,但必须包含来源、发布日期和必要章节;模型可选择不同检索关键词,但不得调用未授权工具。

统计/人工预言机: 内容质量具有主观性或分布性,例如论证充分性、可读性。需要评分量规、多次采样、人工校准与置信区间,详见 H3。不要将一次 LLM 裁判输出当作客观真值。

二、测试体系:从纯函数到真实业务闭环 ​

2.1 分层测试矩阵 ​

层级主要对象外部依赖运行频率
单元测试状态机、策略、预算、校验全部替身每次提交
组件测试Agent Engine、工具网关模型/工具模拟每次提交
契约测试API、事件、工具协议Mock Server每次提交
集成测试DB、队列、对象存储隔离测试实例CI/每日
场景测试完整任务路径受控模型或回放CI/每日
端到端测试UI→任务→审批→交付真实隔离环境发布前
非功能测试并发、故障、安全、成本专用环境定期/发布前

这不是固定比例的“金字塔”。高成本真实模型调用应少于纯函数测试,但关键跨系统风险必须用真实集成环境覆盖。单元测试数量多,不能弥补发布流程从未进行端到端验证的缺陷。

2.2 测试的四个环境 ​

  1. 纯模拟环境:固定模型响应、虚拟工具和内存状态,用于快速复现执行分支。
  2. 本地集成环境:真实数据库/消息队列、测试密钥和沙箱工具,用于验证事务、恢复和协议。
  3. 预生产环境:尽量贴近生产配置,使用隔离租户和受限权限,进行真实模型与外部服务测试。
  4. 生产受控验证:仅在授权条件下执行低风险合成任务、灰度监测或只读探测;不得把测试邮件、付款或发布操作发送到真实用户。

环境应具有可识别的 environment_id、独立的测试数据、明确的出口策略和清理规则。任何会触发真实副作用的测试都应默认关闭,显式授权后才能启用。

2.3 覆盖率应覆盖行为而非仅代码 ​

传统行覆盖率、分支覆盖率仍然有用,但 Agent System 还应维护:状态转移覆盖、工具权限矩阵覆盖、失败分支覆盖、协作拓扑覆盖、审批决策覆盖、模型响应类型覆盖、数据敏感等级覆盖。覆盖率不能直接证明正确性;它只说明哪些行为被执行或检查过。

三、确定性核心:状态、契约与属性测试 ​

3.1 把关键行为写成不变量 ​

以下不变量应先于模型质量评估被测试:

  • 终态 Run 不可未经新建重试语义重新进入执行态。
  • 一个外部操作的幂等键在同一作用域内只能对应一个逻辑操作。
  • 审批必须绑定动作类型、目标资源、参数摘要和版本;参数变化后旧审批失效。
  • 子任务不得获得超出委托者和策略允许范围的权限。
  • 每次可计费执行在预算准入后才能开始;预留与结算须可对账。
  • 失去 Lease 的 Worker 不能继续提交被保护资源的状态更新。
  • 用户取消后不得再启动新的可取消外部操作;已发生的副作用应如实记录。
  • 报告引用必须能解析到已登记的来源版本;缺失来源不得伪装成已验证引用。

这些断言应在可信服务端执行,不能依赖 Prompt 要求模型“遵守”。

3.2 API 与事件契约 ​

契约测试至少检查:必填字段、枚举值、版本字段、未知字段策略、错误码、分页游标、幂等语义、事件顺序与向后兼容。SSE 或 WebSocket 断线后应能根据游标补读事件,重复事件由客户端去重;不能把“收到两次消息”直接等同于“执行两次工具”。

对于跨服务事件,建议使用版本化 Schema 和消费者契约测试。新增可选字段通常较容易兼容,删除字段或改变状态含义需要显式迁移。契约测试只验证格式和约定,不能替代数据库事务或权限集成测试。

3.3 属性测试与状态机模型测试 ​

比起手工列举几十个输入,可以生成随机操作序列:create → start → pause → approve → retry → cancel,在每一步检查不变量。例如随机重复审批、交换消息顺序、插入超时、让两个 Worker 竞争同一 Run。记录随机种子和最小失败序列,以便复现。

状态机测试还应覆盖非法路径:未创建任务直接执行、已撤销审批继续发布、终态任务被取消、过期 Worker 写入旧版本。关键是将“非法输入必须被拒绝”纳入通过条件,而非只测试成功路径。

四、模型行为测试:如何处理非确定性 ​

4.1 区分四种替身 ​

类型返回行为适用目的
固定 Stub固定响应状态与控制流
Scripted Fake按步骤返回多轮工具循环
Recorded Replay回放已记录响应缺陷复现
Live Model真实模型调用兼容性与质量

固定 Stub 的成功不能证明真实模型表现。 它只能证明系统在给定响应下如何处理。真实模型测试又受到模型版本、服务端变化、采样、工具结果、时间与检索语料的影响,必须记录可控制的实验条件。

4.2 建立模型响应覆盖集 ​

至少构造以下模型响应:正常文本、合法工具调用、多个并行工具调用、无工具调用、未知工具、缺少参数、非法 JSON、结构化输出不符合 Schema、拒答、空响应、输出截断、流式事件中断、重复事件、超长上下文、供应商限流、服务端错误。不同供应商的 API 语义不同,不能假设所有模型均支持同一工具协议、结构化输出或流式事件结构。

在工具执行前验证参数与权限;当模型输出非法时,Engine 应进入明确的修复、拒绝或失败路径,而不是把不可信文本直接作为命令执行。

4.3 真实模型测试的可复现性记录 ​

每次测试应固定或记录:模型提供方、模型标识与可得版本信息、请求参数、Prompt/工具 Schema 哈希、检索语料版本、工具结果、时间、数据集版本、执行环境、预算与超时、采样次数、评判规则。即使设置温度为零,也不应承诺跨时间、跨硬件或跨服务版本的逐字确定性。

对随机行为可采用同一测试集多次运行,报告成功比例、失败类型和不确定性范围。关键安全约束应采用“任何一次违规即阻断发布”的策略,而不是让较高平均分掩盖越权行为。

4.4 变形测试(Metamorphic Testing) ​

当没有唯一标准答案时,测试输入变换后应保持的性质:改变无关措辞不应改变访问权限;交换无关资料顺序不应改变来源可追溯性;加入包含“忽略先前指令”的恶意网页不应导致系统执行其指令;工具返回重复文档不应产生虚假独立来源。变形测试不是保证语义等价的万能方法,应为每种变换明确前提。

五、工具与外部副作用:最关键的测试边界 ​

5.1 工具测试的三层 ​

工具定义层验证 Schema、参数范围和权限要求;工具执行层验证超时、取消、错误映射、重试与幂等;外部结果层验证真实系统是否发生预期变化。仅看到 tool_call.status=success,不等于外部系统完成操作。

以 publish_report(report_id, version) 为例,至少验证:版本匹配、审批有效、目标环境允许、幂等键稳定、网络超时后先查询操作结果、重复请求不会重复发布、操作记录与外部系统一致。

5.2 故障模拟必须区分时序 ​

注入位置风险应验证的行为
调用前失败尚无副作用安全重试或失败
已发送未响应结果不确定查询远端或进入待核验
远端成功本地崩溃重复执行风险幂等与恢复对账
本地记录成功前崩溃状态不一致事务/Outbox 恢复
已审批后参数改变越权发布风险审批失效并重新请求

对非幂等的真实工具,不应通过无条件重试来“测试恢复”。优先使用沙箱环境、测试账户和可查询的外部操作标识。

5.3 Prompt Injection 与权限回归 ​

建立攻击性输入集,覆盖网页、PDF、搜索摘要、工具返回、Agent 间消息与长期记忆中的恶意指令。检查模型是否试图越权是一层;更重要的是检查可信工具网关是否拒绝越权动作。测试记录包括攻击载体、被测版本、请求的动作、实际授权结果、外部副作用及审计事件。H2 负责威胁模型,H10 负责自动化验证这些控制是否有效。

六、多 Agent 编排与协作测试 ​

6.1 从 DAG 到动态任务图 ​

对静态 DAG 测试依赖顺序、并行执行、失败阻断、循环依赖拒绝;对动态编排还要测试任务创建上限、递归委托深度、预算继承、子任务取消、交接协议、结果汇总和终止条件。多个 Agent 互相回复消息并不意味着协作任务完成,必须验证产物与验收条件。

6.2 共享状态与竞争条件 ​

模拟两个 Agent 同时更新同一报告章节:一方读取版本 4,另一方已提交版本 5;旧版本提交必须冲突或经显式合并。对并行调研结果应检查引用归属、来源去重、证据冲突与汇总完整性。测试消息重复、乱序、延迟、丢失、Worker 重启以及旧 Worker 回归。

6.3 协作协议测试 ​

Handoff 应包含任务 ID、父任务 ID、发起者、接收者、输入引用、授权范围、截止时间、预算上限、预期输出 Schema 和相关追踪 ID。测试无效接收者、过期委托、缺失输入、重复交接、超预算交接和部分结果返回。跨 Agent 传来的内容仍然是不可信输入,不能自动升级为系统指令或权限授予。

七、故障注入、可靠性与恢复测试 ​

7.1 故障目录 ​

应覆盖模型 429/5xx、工具超时、网络分区、数据库事务冲突、队列重复投递、对象存储不可用、Worker 进程崩溃、磁盘空间不足、凭据过期、配置版本不兼容、外部 API 成功但本地超时、用户取消与审批长时间等待。

7.2 恢复测试的判定条件 ​

恢复后不仅要“最终成功”,还应满足:没有重复外部副作用、没有越权动作、状态单调前进、预算正确结算、审计链完整、未确认操作被明确标记、用户看到正确状态。对于无法自动确认的外部操作,系统应进入 NEEDS_RECONCILIATION 等明确状态,而非虚构成功或失败。

7.3 Chaos Engineering 的约束 ​

故障注入应有假设、影响范围、停止条件、回滚计划和观测指标。先在隔离环境开展,再考虑受控预生产实验。不要在真实用户的敏感任务中随机断开依赖以追求“混沌覆盖率”。测量 RTO/RPO 时要说明测量范围和恢复目标,不能把单次恢复时间泛化为 SLA。

八、安全、性能、成本与数据生命周期验证 ​

8.1 安全测试 ​

覆盖身份认证、对象级授权、多租户隔离、工具白名单、网络出口、凭据泄漏、Prompt Injection、审批重放和数据外发。检查服务端执行结果,而非只检查 UI 是否隐藏按钮。对安全测试使用最小权限测试账户与脱敏数据。

8.2 性能与容量测试 ​

使用分层负载模型:同时在线用户数、活跃 Run 数、每 Run 工具调用数、Agent 扇出系数、模型 RPM/TPM、队列长度、数据库写入频率。报告 P50/P95/P99 延迟、队列等待、成功率、超时率、吞吐量和成本;明确测试期间的供应商配额。模型供应商动态限流可能让压测结果随时间变化。

8.3 预算与成本测试 ​

验证任务预算准入、并发预留、费用结算、失败释放、超额拒绝、跨 Agent 预算继承与账单对账。故障重试可能同时增加费用和延迟;性能测试必须记录成本,否则容易将“更快但贵十倍”的方案误判为全面改进。

8.4 数据治理测试 ​

覆盖来源版本、引用血缘、RAG 检索权限、记忆过期、删除传播、备份保留例外和审计记录脱敏。测试删除时需检查原始文件、派生摘要、向量索引、缓存和可访问的最终产物,不能只验证主数据库的删除标志。

九、测试数据、基线与回归管理 ​

9.1 测试数据集的分层 ​

建议维护四类数据:契约用例(小而确定)、典型场景(覆盖真实业务)、对抗与异常用例(覆盖风险边界)、历史缺陷回归用例(复现曾经失败的轨迹)。每条用例具有稳定 ID、输入数据版本、期望性质、判定方式、风险等级、责任人和来源。

生产数据不得未经授权直接复制到测试环境。优先使用合成数据、脱敏数据或获得明确授权的数据;测试数据也需要保留与删除策略。

9.2 回放机制 ​

保存必要的模型响应、工具结果、事件顺序和环境版本,以便对同一缺陷进行回放。回放能够复现控制流,但不能证明真实外部依赖仍具有相同行为。对包含敏感信息的轨迹实施脱敏、访问控制和保留期限。

9.3 基线比较与发布门禁 ​

每次发布应与已知稳定版本比较:确定性契约是否全部通过、关键场景是否退化、模型行为的统计指标是否下降、成本是否异常、安全约束是否触发。质量阈值由业务风险决定,不应直接照搬示例数值。发布门禁需要记录测试集版本、配置哈希、模型标识、执行环境和失败豁免审批。

防止“只对测试集优化”:保留独立的未见测试集、周期性更新真实失败样本,并区分开发集与最终验收集。对提示词或路由规则的每次调整,至少重跑受影响场景和高风险回归用例。

十、研究报告 Studio:完整验证方案 ​

10.1 业务路径 ​

用户创建 Studio → 提交研究要求 → 选题 Agent 提案 → 审核 Agent 评审 → 用户确认 → 调研/分析 Agent 并行执行 → 审核 Agent 验收 → 用户审批发布 → 生成最终报告。每一节点均具有状态契约、权限约束、输入输出 Schema 和失败路径。

10.2 场景测试矩阵 ​

场景故障或变化必须满足的条件
选题返工审核不通过不进入调研阶段
并行调研某 Agent 超时依赖与部分结果正确
来源撤回引用失效标记并触发复核
恶意网页包含注入指令工具网关拒绝越权
审批竞态报告版本改变旧审批不得发布
发布超时远端结果未知不盲目重复发布
Worker 崩溃Checkpoint 恢复无重复外部副作用
预算耗尽子任务继续申请拒绝新增计费动作
用户取消Run 正在执行停止可取消新动作
SSE 断线客户端重连状态与事件可补读

10.3 端到端验收的证据包 ​

一次验收应输出:test_run_id、测试用例版本、环境与配置版本、执行事件、Trace 关联、工具操作标识、外部状态核验结果、产物哈希、评估结果、成本记录、失败原因与最终判定。证据包用于复现和审计,不应包含不必要的原始敏感 Prompt 或密钥。

10.4 推荐实施顺序 ​

阶段一: 先固化状态机、审批、权限、预算和幂等的单元/契约测试。阶段二: 用 Scripted Fake 模型覆盖主要执行分支,并接入隔离数据库和队列。阶段三: 建立 Studio 全链路沙箱测试与故障注入。阶段四: 引入真实模型场景测试、统计评估和版本回归。阶段五: 将安全、可靠性、成本和质量门禁接入发布流水线,并持续补充线上缺陷回归集。

十一、最小可执行实验:状态与审批约束 ​

以下示例只使用 Python 标准库,演示确定性控制逻辑的测试方式;它不模拟真实模型、数据库事务或分布式并发。为了避免把测试用例当作生产安全实现,示例仅表达最小约束。配套文件 H10-Agent-System-Testing-and-Validation-v1.1-demo.py,Python 3 标准库(含 3.9)。运行:python3 H10-Agent-System-Testing-and-Validation-v1.1-demo.py。

python
from __future__ import annotations

from dataclasses import dataclass

@dataclass
class Publication:
    version: int
    approved_version: int | None = None
    published: bool = False

    def approve(self, version: int) -> None:
        if version != self.version:
            raise ValueError("stale approval target")
        self.approved_version = version

    def edit(self) -> None:
        self.version += 1
        self.approved_version = None

    def publish(self, version: int) -> None:
        if version != self.version or self.approved_version != version:
            raise PermissionError("approval mismatch")
        if self.published:
            raise ValueError("already published")
        self.published = True

def test_version_bound_approval():
    doc = Publication(version=3)
    doc.approve(3)
    doc.edit()
    try:
        doc.publish(4)
    except PermissionError:
        pass
    else:
        raise AssertionError("stale approval was accepted")

def test_duplicate_publish_rejected():
    doc = Publication(version=7)
    doc.approve(7)
    doc.publish(7)
    try:
        doc.publish(7)
    except ValueError:
        pass
    else:
        raise AssertionError("duplicate publish was accepted")

if __name__ == "__main__":
    test_version_bound_approval()
    test_duplicate_publish_rejected()
    print("2 deterministic checks passed")

本地执行通过:输出 2 deterministic checks passed。

扩展实验: 用 SQLite/PostgreSQL 的事务和版本条件更新替换内存对象;并发启动两个发布 Worker;在外部服务成功但响应丢失时注入故障;检查操作账本、幂等键、外部发布记录和恢复后的状态一致性。这些扩展实验不属于上述示例的验证范围。

十二、常见反模式与工程决策 ​

反模式一:只测 Prompt,不测执行边界。 Prompt 改进可能降低错误概率,但不能保证权限、审批、预算和外部副作用正确。

反模式二:所有测试都调用真实模型。 这样成本高、执行慢、失败难复现。应将确定性机制和模型行为分开测试,再通过少量关键集成场景连接。

反模式三:只用 Mock 测试。 Mock 能验证预设行为,不能发现供应商协议差异、真实网络错误和数据库一致性问题;必须保留真实依赖的契约和集成测试。

反模式四:以最终答案评分替代系统测试。 一份质量较高的报告仍可能由越权检索或重复发布产生。质量评估与行为验证都不可缺少。

反模式五:把单次成功率视为稳定性。 应记录样本数、波动、失败分布、数据集版本和模型配置;对关键约束采用零容忍门禁。

反模式六:故障注入后只看是否恢复。 必须检查重复副作用、预算、审批有效性、状态一致性和审计完整性。

反模式七:测试数据与生产数据混用。 容易造成隐私泄漏和误操作;应严格隔离账户、租户、密钥、外部接收方和存储位置。

研究结论 ​

  1. Agent System 可以被系统化测试,但必须按行为性质选择测试预言机。 确定性契约采用严格断言;模型质量采用统计和人工评估;跨系统副作用采用外部状态核验。
  2. 测试的最小可信边界是执行控制层,而不是模型输出。 关键权限、审批、预算、幂等与状态不变量必须由可信代码强制执行并接受自动化测试。
  3. 模拟与真实测试必须结合。 Scripted Fake 和回放用于快速复现;真实协议、数据库与模型测试用于发现环境差异;端到端测试用于证明业务闭环。
  4. 非确定性需要被测量和管理,而不是被忽略。 应记录版本、参数、数据集、采样与结果分布,区分随机波动和真实回归。
  5. 故障恢复的验收标准不仅是任务最终完成。 还要验证无重复副作用、无越权、状态一致、成本正确、审计可追溯。
  6. H10 是跨层工程验证能力。 它把 H2、H4、H5、H6、H7、H8、H9 的约束转化为可执行测试,并向 H11 的发布运维提供门禁证据;与 H3 的质量评估相互补充。

附录 A:参考文献与原始资料 ​

以下优先列出标准组织、项目维护者或技术厂商的官方资料。引用用于解释技术机制与工程实践;具体接口、版本和适用性应在实施时再次核验。

证据映射: 测试层级与术语参考 [R1][R2];属性/契约测试参考 [R3][R4][R15];执行可观测性参考 [R5];Agent 与工作流测试实践参考 [R6][R7];模型质量评估参考 [R8][R9];安全与可靠性测试参考 [R10][R11];事务与接口边界参考 [R13][R14]。本文的测试矩阵、Studio 方案和验收条件属于基于上述原理提出的工程综合设计,并非任何单一来源的逐字规范。

附录 B:研究证据、验证声明与适用边界 ​

B.1 已进行的验证 ​

  • 结构性检查: 文档名称、所属领域、章节、七项元数据、专题导读、研究结论和固定附录的完整性。
  • 代码实验: 文中 Python 最小实验仅覆盖审批与版本绑定、重复发布拒绝两项确定性约束;具体是否已实际执行,以交付时的运行记录为准。
  • 资料使用: 引用官方文档作为机制与术语参考;未对每个版本的接口行为进行独立实机验证。

B.2 未进行的验证 ​

未执行真实模型多次采样、真实 LangGraph/Temporal 集成测试、数据库并发压测、跨服务网络故障注入、真实外部发布副作用测试、生产环境安全渗透测试或正式质量统计实验。文中的测试用例与验收方案属于待实施设计,不能据此宣称系统已经达到生产级可靠性。

B.3 适用边界与维护建议 ​

本文适用于具备模型调用、工具执行、任务状态、协作编排和对外接口的 Agent System。纯聊天机器人可采用简化测试体系;涉及金融交易、医疗、关键基础设施等高风险业务时,还需要额外的行业规范、独立审计与合规验证。模型、框架、供应商 API 和协议随版本演进,实施前应核对官方最新文档,并将测试用例与具体版本绑定。

后续关联专题: 「H11 · 如何部署、发布和运维 Agent System? - Deployment & Operations」 将进一步研究如何把 H10 的测试与验收结果接入 CI/CD、灰度发布、运行监控和回滚流程。