一个客服 Agent 查了订单、读了物流、查了退款规则、建了工单,还在最后礼貌地说任务已解决。九次工具调用,没有报错。

但数据库里的工单状态被它写成了 solved。正确结果应当是 hold,因为物流异常还没解除。

这不是抬杠式的边角错误。对真正的业务系统来说,数据库里那一个字段,才是任务有没有完成的答案。Microsoft 和 Hugging Face 10 月 3 日发布的 ThinkingBox,刚好拿这件很朴素、却长期被忽略的事来评估 Agent。

我看完它的材料,最大的感受不是又多了一个 benchmark,而是很多团队现在拿来庆祝 Agent 成功的指标,可能从一开始就量错了东西。

一段 trajectory 只是 Agent 对自己行为的陈述。终态数据才是证据。重复运行才谈得上信任。

我们太容易被一条漂亮的轨迹说服

做过 LangGraph、Spring 这类业务编排的人,对这个场景大概不陌生。

日志看起来一片绿。Webhook 收到了。Tool 调到了。模型还给出一段有条理的总结。等用户回来追问,才发现退款没有落库,审批状态跳错了,或者同一条记录被重复修改。

传统软件里,大家不会把「Controller 返回 200」当作业务验收。你会查数据库,查消息是否投递,查幂等键,查下游状态。可到了 Agent 这里,很多评测还停在 tool call 是否合法、最终回答像不像样、轨迹是不是足够长。

这不是这些指标完全没用。它们适合快速定位模型是否理解工具、是否能走完大致流程。问题在于,一旦 Agent 被允许改库存、关工单、发退款、创建账号,它们就只能算过程信号,不能当业务结果。

ThinkingBox 的切入点很直接。它让 Agent 在隔离的 MCP 工具会话中做完有状态的业务任务,再用可执行断言检查后端的终态和副作用。不是问模型「你是否处理好了」,而是检查该关的工单是不是关对了,该创建的记录有没有创建,不能碰的记录有没有被误改。

这套 Bench 覆盖零售、汽车保险、旅行、数字银行和咨询五类工作流,一共 507 个任务。每个任务会从相同的干净后端独立跑 20 次。

这一点很关键。

很多 Agent demo 的成功率,更像一次抽奖的中奖截图。你不能因为一个退款请求在周二下午成功完成,就把它包装成已经能接管退款流程。

pass@1 看的是能力,20 次全对才接近可依赖

ThinkingBox 同时报告三个数,恰好把平时混在一起讨论的三个问题拆开了。

指标 它在问什么 它没回答什么
pass@1 随机跑一次,通常表现如何 下一次还会不会对
pass@20 二十次里是否至少成功过一次 是否可以稳定上线
observed 20/20 二十次是否全部通过 真实业务中的长期风险

不少排行榜喜欢用 pass@1,因为好理解,也省钱。但对于会产生副作用的 Agent,它几乎是最容易让人误判的数字。

报告里有一个反差很刺眼。Kimi-K3 在 507 个任务里,至少成功过一次的任务达到 476 个,也就是 93.89%。这说明它覆盖面很广,遇到陌生流程时有办法解出来。可二十次全部通过的任务只有 68 个,占 13.41%。

Claude Opus 5 的形状刚好相反。它至少成功一次的任务比例是 79.09%,低于 Kimi-K3。但它有 47.53% 的任务二十次全对。

你如果是在做知识问答,前者的广度可能很有吸引力。答案偶尔飘一点,人工还看得出来。

你如果是在做自动退款、保单改签、企业开户,事情就变了。用户并不会因为 Agent 十九次正确、一次把钱退给错误的人而感到安慰。

这也是我觉得这篇研究真正有价值的地方。它没把模型排成一条更长的名次,而是逼团队面对一个不太好看的问题,能力和可靠性并不是一回事。

新模型也不必然让问题消失。报告中 Claude Opus 5.5 的单次平均通过率高于 Claude Opus 5,67.16% 对 66.50%,成功过至少一次的任务也更多。但两者二十次全对的任务数都是 241 个。多出来的那半个点,没换来额外一件可以更放心交出去的事。

这种结论听着有点扫兴,但很有工程味。

一次没有报错的执行,可能藏着三种失败

ThinkingBox 做过一组共同任务集的分析,覆盖 12 个模型的 121,680 次有效试验。其中 79,853 次没有通过可执行检查。更值得琢磨的是,在这些失败里,67.24% 的运行是正常结束的,也调用了会改变状态的工具,最终还没有 Tool error。

如果你的监控只看异常率,这些运行会被记为成功。

但终态断言发现,77.61% 有字段值写错,43.30% 产生了不该有的额外副作用,25.36% 漏掉了必须发生的动作。这里的类别会重叠,一次失败可以同时改错字段、又漏发通知。

这几个数字解释了一种很常见的线上错觉。团队观察到 Agent 的调用链很顺,便以为它已经稳定。其实它只是稳定地把请求发到了工具层,至于业务不变量有没有被守住,没人检查。

Java 服务里常讲事务边界,很多时候不是为了优雅,而是为了把「要么都完成,要么都不发生」写进系统。Agent 时代也需要类似的边界,只是边界不能只靠模型的自然语言承诺。

比如一个售后流程可以有这样的验收规则。

1
2
3
4
工单状态必须为 hold
订单不可新增退款记录
客户时间线必须写入物流异常说明
回复必须明确说明当前无法赔付的原因

前两条是数据库终态,第三条是副作用,最后一条才需要语义评判。ThinkingBox 的 507 个任务中,有 477 个主要靠状态判定,另有 30 个附加了针对回复内容的二元 rubric。这个比例很像真实系统,能用确定性规则判定的地方,就别把裁决权再交回另一个 LLM。

评测 Agent,先把业务的不变量写出来

很多项目会问,怎样把 ThinkingBox 接进现有栈。坦率地讲,跑通 OpenEnv、Docker、MCP Server 并不难,真正费脑子的部分在它之前。

你得先回答,什么叫任务完成。

这句话如果只写在产品文档里,几乎没用。它得落成可以检查的规则。以 Spring 服务为例,一个采购审批 Agent 的任务不该只是「调用审批接口并回复已完成」,而应该拆成下面几层。

层次 要检查的内容 一个可落地的实现
终态 审批单、额度、状态机迁移是否正确 查询数据库或服务 API
副作用 审计日志、消息、通知是否恰好发生 检查 outbox、Kafka topic、审计表
约束 是否越权、是否重复扣款、是否跨租户 断言权限、幂等键和 tenantId
语义 给用户的解释是否覆盖关键事实 小范围 rubric 或人工抽检

顺着这张表再聊聊,最容易遗漏的是负向断言。大家会写「审批单应为通过」,却忘了写「不应修改其他审批单」「不应重复发送通知」「失败时不能消耗额度」。而 Agent 很擅长在看似合理的路径上,多做一步。

多做一步,在聊天里叫热心。在支付系统里叫事故。

我建议把这些断言当作 Agent 开发的接口契约,和 OpenAPI、数据库 migration 放在同一个工程生命周期里。新加一个 Tool,不只补 prompt 和 demo,也要补它能改什么、绝不能改什么、失败后怎样回滚的评测用例。

把重复运行从发布前表演,变成发布门禁

二十次不是什么魔法数字。ThinkingBox 选它,是为了把偶发成功和可重复成功拉开。对于高金额、高风险流程,二十次甚至还不够。

但方向很明确。不要只跑一次 golden path,就给 Agent 发上线许可证。

一个更务实的 CI/CD 方案可以分三层。

第一层,每次 Pull Request 跑少量、确定性的状态断言。它应该快,专门拦截 Tool schema 改坏、状态机漏迁移、幂等逻辑失效这类回归。

第二层,夜间或合并前做多次重复运行。这里要记录 pass@1、成功至少一次的覆盖面,以及连续全通过的比例。别把这三个数揉成一个总分,它们反映的是不同风险。

第三层,上线后做影子流量或低权限灰度。业务系统不可能被 benchmark 完整复制,用户输入、历史数据、第三方延迟都会冒出来。线上仍然要有审计、可回放的 trajectory、权限最小化和人工接管入口。

这一层不能省。

ThinkingBox 评的是隔离沙箱中的合成业务工作流。它很适合揭开工具调用和业务结果之间的缺口,却不能证明某个模型已经适合你的数据、你的权限模型和你的客服政策。模型版本、Agent harness、模拟用户和 judge 的设置也会影响结果,不能拿它当采购清单直接照抄。

不过,这些限制反而让它的启发更扎实。它没有许诺「测完就安全」,只是在提醒大家先别用错误的尺子。

MCP 把 Agent 接进系统,也把验收题变难了

MCP 降低了 Agent 使用外部工具的门槛。一个 Server 暴露得足够好,模型就能读、写、查、改。开发者通常会为这种连通性兴奋,我也一样。

但连接能力越强,任务完成的定义就越不能含糊。

过去一个聊天机器人答错,风险大多停在一段文本。现在一个 Agent 可以把 CRM、工单、代码仓库和支付系统接起来,错误会沉到状态里,过半天才被人发现。你如果只保存最后一段回答,排查时会像在案发现场只捡到一张道歉信。

所以我不太认同「给 Agent 多几个 Tool,它自然就会更有用」这种乐观叙事。Tool 越多,状态空间越大,副作用越多,评测反而应该更具体、更保守。

先让它在一个权限窄、后端可重置的沙箱里把 20 次都做好。再谈生产环境。

可以直接拿走的四个动作

如果你正在做 LangGraph 或 Spring AI Agent,今天就能开始做的不是换模型,而是下面四件事。

  1. 挑一个会修改业务数据的真实流程,别从纯问答开始。
  2. 写下三类断言,正确终态、必须发生的副作用、绝不能发生的副作用。
  3. 把同一个任务从同一份初始数据跑 10 到 20 次,保存每次的状态 diff,而不是只保存最终回答。
  4. 在发布门禁里设置最低的连续通过要求。达不到就缩窄权限或回到人工确认,别拿一个漂亮 demo 下注。

这套做法不酷,甚至有一点像回到了测试驱动开发最朴素的年代。

可业务系统一直都是这样工作的。用户不关心 Agent 调用过多少次 Tool,也不关心它的推理看上去多聪明。他只关心工单有没有被正确保留,钱有没有被正确处理,系统有没有在不该动的时候保持不动。

ThinkingBox 里那个被错误关闭的工单,最后给了我们一个很简单的提醒。

Agent 说自己做完了,先去看看数据库。

参考资料