背景

进入公司后,一直所在的部门属于算法部,作为 QA,经历了模型传统机器学习阶段、深度学习阶段,再到 23 年左右的大模型阶段,需求周期越来越短,迭代节奏越来越快。最开始做 OCR 业务测试那会,需求提出来后,光是local 打标都要一个月,还要训练,还要评测,出模型,工程结合算法提交最终的 API,一个周期下来一两个月。大模型时候来了后,需求的周期慢慢缩到了1 个月,训练更多地是强化学习;后面为了加强知识领域的能力,减少模型幻觉,出现了 RAG,各种知识的检索,筛选,解决冲突。
从 24 年开始一直负责智能 客服系统的测试,后端全是一个个模型+工程能力实现的单 API,一个 API 负责一块能力,通过 API 将流程串起来。一旦第一个环节做意图识别出现问题,后面基本都废了,另外几十个接口管理起来很痛苦,就来到了Multi-Agent 架构升级阶段了。一下子收敛成可分工、可编排、可观测的智能协作链路,让意图识别、任务规划、工具调用、专家处理和结果生成各司其职,降低链路耦合,也提升复杂任务的可维护性与可扩展性,现在就来说说作为 QA,怎么保证这块质量。

大模型应用和传统软件最大的不同在于:它不是一个单纯的确定性程序,而是由协议、路由、Prompt、模型输出解析、规划器、工具调用、状态流转、风控兜底和最终回复共同组成的系统,Multi-Agent 可以理解为每个 agent 负责的领域不一样,就像不同的职责分工。比如我们会有 Main agent、Planner agent、expert agent,Rewrite / Final Agent、Risk Control Agent。
在这里插入图片描述
如果只看最终回答,很容易出现两个问题:

第一,结果看起来对,但过程可能错了。例如 Agent 调用了错误工具、没有做必要诊断、遗漏关键状态,只是靠模型“猜”出了一个看似合理的答案。

第二,结果看起来不稳定,但不知道该改哪里。到底是意图识别错了、Planner 拆解错了、工具返回错了、模型解析失败,还是最终 Rewrite 表达不清楚?

所以,Agent 测试不能只做“问答对不对”的黑盒测试,而应该做分层测试。

本文介绍一种三层测试方法,适用于诊断类、电商经营类、数据分析类、客服类等复杂 Agent 场景。

为什么 Agent 需要分层测试

传统应用的测试边界通常比较清晰:

  • 接口输入输出是否正确
  • 业务逻辑是否符合预期
  • 数据库状态是否正确变更
  • 前端展示是否正常

但 Agent 系统的问题更复杂,常见风险包括:

  • 用户输入表达多样,同一个意图可能有几十种问法
  • 模型输出不稳定,JSON 格式、字段值、语义内容都可能波动
  • Agent 需要在多个能力之间路由,例如直接回答、规划、工具调用、转人工、风控拦截
  • Planner 可能拆错步骤,或者调用了不合适的工具
  • 工具返回结构正确,但模型理解错了
  • 最终回答可能编造数据,或者把内部错误暴露给用户
  • 多轮对话里状态可能丢失、串话、重复执行

因此,一个有效的 Agent 测试体系,至少要回答三类问题:

  • 每个组件本身是否可靠?
  • 多个组件串起来时,过程是否正确?
  • 最终用户体验和业务效果是否达标?
    对应地,可以把测试分成三层。

三层测试模型

我觉得把把 Agent 测试分为三层比较好:
用户输入query -->
组件契约层:协议 / Prompt/ 解析器 / 工具契约
Agent 编排层:路由 /Planner / 工具调用 /状态流转 / 风控
业务场景层:最终回答 /用户体验 / 效果评测 /回归集
这三层不是按代码目录划分,而是按测试目标划分。

第一层:组件契约层

组件契约层关注的是:每个基础组件是否按约定工作。
这一层不关心完整对话效果,而是验证单点能力是否稳定、可解析、可复用。

测试目标

组件契约层主要测试:

  • 输入协议是否能被正确解析;
  • Prompt 是否能稳定生成, 这里需要查看 prompt 槽位填写的信息是否正确、无丢失等;
  • 写到 Redis 的 memory 数据格式、状态是否正确;
  • 模型输出是否符合 schema,这个一般在 TD 时会定输入输出;
  • 输出解析器是否能兼容异常格式;
  • 工具 / MCP / Expert 的入参和返回结构是否符合契约;
  • 风控模块是否返回标准字段;
  • 卡片、结构化消息、finish 状态等协议字段是否完整;
    这一层的核心是:把不稳定的大模型输出,约束成系统可消费的稳定结构。

应该覆盖哪些模块

在一个典型 Agent 中,下面这些都属于组件契约层:

模块 测试重点
协议解析 必填字段、默认值、异常输入、历史消息解析
Prompt 构造 变量是否完整、上下文是否注入正确、敏感信息是否泄露
模型输出 Schema JSON 是否合法、字段是否齐全、枚举值是否正确
输出解析器 半截 JSON、额外文本、字段缺失、类型错误时是否兜底
工具 / MCP 契约 入参 Schema、返回 Schema、错误结构、空数据结构
Expert 契约 是否返回标准 agent_resulterror_codedata_type
风控契约 是否返回 has_riskrisk_text 等稳定字段
卡片协议 card_typecard_payload、展示字段是否完整

测试方法

在测试初期,不一定马上建设完整自动化。通过一个简单 demo不带复杂业务逻辑的接口请求去检查这些项,可以从入口层,也可以从Agent 通过 A2A 协议进行请求,可以先通过 Log 或 Langfuse trace 手动检查关键协议内容是否符合预期,初期只任何做手工测试,检查无误后,可通过 pytest写成自动化 case,用作测试准出的第一层判断。比如这层自动化失败后,就没必要做端到端的自动化了,节约成本,减少模型调用。

示例:路由输出契约测试
对于诊断类 Agent,模型第一步通常需要判断用户问题是否需要进一步诊断。
例如用户问:
为什么我不能报名某个活动?
期望模型不要直接编答案,而是输出一个结构化决策(main agent 这层)
{
“action”: “call_planner”,
“response_language”: “Bahasa Indonesia”,
“response”: [
{
“type”: “text”,
“content”: “Baik Kak, bantu cek dulu ya.”
}
],
“need_planner_reason”: “Query requires seller-specific eligibility check”,
“idk”: false,
“transfer_to_human”: false,
“followup_questions”: []
}

初版重点检查:

  • 请求协议是否完整,例如 query、session_id、user_id、region 等字段是否正确传递
  • 路由模型输出是否符合预期,例如 action、need_planner_reason、response 等字段
  • Planner 输入是否包含必要上下文
  • Tool / MCP / Expert 的入参与返回结构是否符合约定
  • 最终输出协议是否完整,例如文本、卡片、风控结果、finish 状态等
  • 异常情况下是否有兜底字段,而不是直接抛出内部错误
  • Log 更适合确认系统层面的字段传递、异常、超时、状态变化;
    Langfuse 更适合查看 Prompt、模型原始输出、Planner结果、工具调用和最终回答。这一阶段的目标是先把协议链路看清楚,确认每个组件的输入输出边界是否稳定。

自动化需要覆盖维度:

  1. 第一类是规则断言。
    例如:
    assert action in [“direct_response”, “call_planner”, “final_response”]
    assert if action == “call_planner”, need_planner_reason != “”
    assert response is valid array
    assert no unsupported card_type
  2. 第二类是 schema 校验。
    所有模型输出、工具输出、Expert 输出都应该有 JSON Schema 或等价结构定义,测试时自动校验。
  3. 第三类可以加一些异常样本测试。
    专门构造一些模型常见坏输出,模拟(mock)模型输出,看看工程部分的兼容情况:
    JSON 前后多了自然语言
    字段缺失
    字段类型错误
    action 拼写错误
    输出了不支持的 card_type
    返回空 response
    返回了重复 finish
    工具返回空数据
    工具返回 error
    这一层的目标不是让模型永远不犯错,而是保证系统遇到坏输出时能识别、修复或兜底。
    在这里插入图片描述

第二层:Agent 编排层

Agent 编排层关注的是:多个组件串起来之后,决策过程是否正确。

这一层不是只看最终回答,而是看 Agent 的“过程数据”。

比如一个诊断类问题,理想过程可能是:

识别为诊断类问题
选择调用 Planner
Planner 拆出合理步骤
调用相关工具或专家能力
汇总结果
Rewrite 成用户能理解的回复
经过风控
输出 finish
如果最终回答看起来不错,但中间没有调用任何诊断工具,那其实是不合格的。

测试目标

Agent 编排层主要回答:

  • 是否识别出正确意图
  • 是否走了正确路由
  • 是否应该调用 Planner Planner
  • 是否拆出合理步骤
  • 是否调用了正确工具 / MCP /Expert
  • 工具调用顺序是否合理
  • 状态是否正确流转
  • 多轮上下文是否正确继承
  • 失败时是否进入兜底流程
  • 最终是否 finish 是否经过风控
    过程数据是关键,Agent 编排测试必须依赖 trace 数据。
    我们系统是接入了 langfuse。Langfuse 可以理解为一个面向 LLM 应用的可观测与评测平台。它可以记录一次 Agent 请求中的完整 trace,至少应该包含:
    用户输入
    Prompt
    模型原始输出
    路由结果
    Planner 过程
    Tool / MCP / Expert 调用
    Rewrite 输出
    最终回答
    没有 trace,就只能做黑盒评测;有 trace,才能定位问题发生在哪一环。

测试方法

这里就需要一个真正业务的请求 URL 发起测试了,或者通过端上发起真正的对话内容。然后拿到 trace_id去 langfuse 追溯调用链路。
自动化建设这一步可以和第三层合并在一起,进行 agent case回归评测。----我后面写一下我们怎么做的。

示例:诊断类问题的编排断言
以“为什么我不能报名某个项目”为例,可以设计如下断言:

用户 query:
“为什么我不能报名某个项目?”

期望过程:

  1. CM action = call_planner
  2. need_planner_reason 非空,且语义与“需要查询用户/店铺状态”相关
  3. Planner 至少调用一个状态查询类工具
  4. Planner 至少调用一个规则/知识类工具
  5. 如果问题属于项目报名/资格判断,需要调用资格检查相关能力
  6. 最终 Rewrite 不能编造工具没有返回的数据
  7. 最终回答需要说明:
    • 当前状态
    • 可能原因
    • 下一步操作建议
  8. 风控通过
  9. 最终输出 finish = true

Agent 编排层的典型用例

建议覆盖以下场景:

场景 测试重点
纯闲聊 应该 direct_response,不应调用 Planner
概念解释 可以直接回答,但不能编造个性化数据
个性化诊断 应该 call_planner,并调用相关工具
数据查询 应该调用数据工具,不能直接猜
多轮追问 应继承上一轮状态
用户否定/修改 状态应更新,不能继续旧计划
工具空返回 应给出合理兜底,不暴露内部错误
工具报错 应隐藏内部错误,给用户可执行建议
风险输入 应触发风控或安全兜底
卡片输出 应输出正确卡片类型和 payload

五、第三层:业务场景层
业务场景层关注的是:最终结果对用户是否有用。
这层更接近真实用户体验,也更适合做模型效果评测。
它不是只判断格式,而是判断:

  • 是否真正理解用户问题
  • 是否给出正确结论
  • 是否基于真实数据
  • 是否表达清楚
  • 是否符合业务规则
  • 是否没有幻觉
  • 是否让用户知道下一步怎么做

测试目标

业务场景层主要评估:

维度 说明
意图理解 是否正确识别用户要做什么
事实正确性 是否基于工具/知识库返回,不编造
业务正确性 是否符合业务规则
完整性 是否回答了原因、状态、建议
可执行性 用户是否知道下一步怎么做
表达质量 是否自然、清晰、符合地区语言
安全合规 是否避免敏感、违规、误导性内容
稳定性 多次运行结果是否一致
用户体验 是否避免内部术语、错误栈、系统失败信息

测试方法

我觉得这一层最难的就是覆盖的场景全不全、结果检查的方向(评估方向)。也为后面 agent 评测打下基础。初期手工 case 可以通过端上发起。上线稳定后完成 agent 回归自动化。
业务场景覆盖:主要来自 需求文档、第二类是 badcase 回归集(主要是 PM 体验、线上的反馈),第三类是边界用例,第四类工具error,第五类安全 risk用例。

自动化 Case 断言这一层,不能完全依赖规则,也不能完全依赖人工。比较实际的方式是:

规则评估 + LLM Judge + 人工校准

  1. 规则评估判断确定性问题:是否通过 risk,是否指定了工具等
  2. LLM Judge 判断语义问题;回答是否解决了问题,是否自然,是否有依据等
  3. 抽样复核 LLM Judge 的准确性:定期修正评分标准

三层之间怎么对应具体模块

以一个抽象的诊断类 Agent 为例。
用户问:
为什么我不能报名某个项目?
测试时不要只看最终回答,而要看完整过程。

类型 说明 示例
黄金用例 最核心、最高频、必须正确的场景 查询经营表现、诊断商品问题、诊断广告问题、判断是否符合某项目报名条件、查询某个状态异常的原因
Badcase 回归集 来自线上真实问题,每次修复后都要沉淀为回归用例 意图识别错误、未走 Planner、工具调用错误、回复编造数据、卡片输出异常
边界用例 覆盖用户表达不完整、语言混杂、上下文复杂等情况 用户表达很短:“为什么不行”、中英混杂、错别字、缺少关键对象、多个意图混在一起、历史对话里有旧状态
工具异常用例 验证工具异常或数据异常时,系统是否能合理兜底 工具返回空、工具返回 error、工具返回部分字段缺失、工具数据与知识库描述存在冲突
安全用例 验证系统是否避免违规、误导、虚假承诺或敏感输出 用户要求绕过规则、要求虚假承诺、输入敏感内容、模型可能输出过度保证的话术

简单说:

组件契约层保证“零件没坏”
Agent 编排层保证“流程没跑偏”
业务场景层保证“结果真的有用”

评测 -> 发现问题 -> 归因 -> 修 Prompt / 修工具 / 补数据 / 调规则 -> 回归验证

~~

常见误区

误区一:只测最终回答
最终回答正确,不代表链路正确。Agent 可能没查数据,只是猜对了。

误区二:只做人工体验测试
人工测试能发现体验问题,但规模化差,也很难覆盖回归。

误区三:只看模型分数
模型分数高,不代表 Agent 系统可靠。工具调用、状态流转、协议解析都可能出问题。

误区四:没有 badcase 回归
Agent 的很多问题是长尾问题。线上发现一次,如果不沉淀成回归集,下次很可能再出现。

误区五:不采集中间过程
没有 trace,就很难判断问题是路由、Planner、工具、Rewrite 还是风控导致的。

总结

测试 Agent,本质上不是测试一个模型,而是测试一个由模型驱动的复杂系统。

一个实用的分层测试体系可以分成三层:

  • 组件契约层:保证协议、Prompt、解析器、工具返回结构稳定
  • Agent 编排层:保证路由、Planner、工具调用、状态流转过程正确
  • 业务场景层:保证最终回答真实、可用、安全、符合用户预期

其中最关键的是两点:
第一,要基于 trace 做过程评估,而不是只看最终回答。
第二,要把各个方面反馈回来的 case持续沉淀为测试集,形成“评测 - 反馈 - 优化 - 回归”的闭环。
只有这样,Agent 才能从“偶尔回答得不错”,逐步变成“稳定、可解释、可回归、可持续优化”的 AI 应用。

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐