只测最终答案已经不够了:Agent Regression Testing到底在回归什么?
接口没报错,用户的钱为什么退错了?
客服 Agent 收到“这笔订单不要了,帮我退掉”。它最后回复“退款已提交”,用户也看到了退款金额。两小时后财务发现:退款走到了上一笔订单,优惠券却补给了当前订单。
最难排查的地方是,每个接口都正常:查单成功、退款成功、补偿成功。真正错的是 Agent 的路径——它先根据上下文猜了订单号,又在退款失败后自行换了一笔订单重试。最终文本听上去没毛病,业务动作却已经越界。
这正是 AI Agent 和普通接口自动化的分水岭。接口测试验证“给定请求,服务是否正确处理”;Agent 测试还要验证“这个请求该不该发生、参数从哪里来、失败后能不能继续试”。NVIDIA 最近关于 Agent Evaluation 的工程讨论也把重点放在多步工具调用和失败恢复,而不只是最后任务是否完成。
把“退款成功”拆成四个必须成立的事实
先别急着给 Agent 打总分。退款这种高风险动作,至少要拆成订单归属、调用顺序、参数来源和停止条件。只要其中一个不成立,即使最后页面显示“退款成功”,也应该判为失败。
下面的断言故意不关心模型说了什么漂亮话,只关心它实际调用了什么:

用Trace写出能拦业务事故的断言
def assert_refund_trace(trace, owned_orders):
calls = [x for x in trace if x["type"] == "tool_call"]
names = [x["name"] for x in calls]
assert names[:2] == ["list_my_orders", "get_order_detail"]
refund = next(x for x in calls if x["name"] == "create_refund")
assert refund["arguments"]["order_id"] in owned_orders
assert refund["arguments"]["reason"] in {"user_cancel", "defective"}
assert names.count("create_refund") == 1
这段代码拦的不是接口 500,而是“猜订单号”“没核对归属就退款”“失败后重复扣动作”三类高损失问题。它也告诉团队,Trace 不是为了画一条漂亮链路,而是为了让测试能追溯参数来自哪一步。
回归集要收集坏轨迹,不只收集标准问法
坏轨迹不等于故意写很怪的提示词。它来自真正容易发生的业务分叉:订单已部分退款、用户改过收款账户、库存锁定尚未释放、上一步工具超时但服务端其实已经成功。每修复一次线上或灰度问题,就把脱敏后的输入、工具结果和正确处理方式沉淀成一条 Evaluation Dataset。下一次模型、提示词或工具 Schema 变动时,CI 先跑这批“曾经出过事”的 Trace。
这样做的价值是从 Outcome Evaluation 升级到 Behavioral Evaluation。最终余额一样,有时只是碰巧;调用路径正确,才说明 Agent 在下一次边界条件下仍可控。质量门禁也不必一刀切:涉及钱、权限、删除操作的轨迹必须零越权;普通咨询可以允许文字风格波动,但不能允许引用不存在的订单。
第一类案例是用户表达不完整,例如“刚才那单别要了”;第二类是上下文混杂,例如同一会话里既谈上一单又谈当前单;第三类是工具失败,例如退款接口超时或订单不可退。每类都要标注“允许什么、禁止什么、失败后应该停在哪里”。
每次改 Prompt、模型、工具描述或退款规则,就在 CI 中跑这份 Agent Regression Testing。高风险断言直接阻断发布;低风险差异进入人工复核。这样你回归的不是某段固定回复,而是一条能造成真实损失的行为边界。
传统测试能力怎么迁移
做过接口自动化的人已经有一半能力:你会构造数据、检查状态机、验证幂等、看日志。现在要补的是把这些判断前移到 Agent 决策过程里:把请求日志升级为 Trace,把结果断言升级为行为断言,把线上投诉升级为 Evaluation Dataset。
下一次写 Agent 用例时,先问一句:它答对以后,有没有可能还是办错了事?能用 Trace 回答这句话,你就开始在做真正的 AI 测试开发。
- 点赞
- 收藏
- 关注作者
评论(0)