我们最开始只是想给 Mira 考一次试。
不是看它能不能写出一段像样的回答,也不是挑几个顺手的 Demo 拍个视频,而是想认真回答一个已经越来越绕不过去的问题:
这个 Agent,到底靠不靠谱?
三天以后,我们没有拿到一个适合挂在首页的大号总分。
倒是先证明了另一件事:
想证明 Agent 靠谱,首先得证明自己的考试系统没有在胡来。
这三天里,Mira 跑了 51 次正式执行;有 30 次还需要额外做语义判卷。我们处理了超时、重复执行、失败恢复、审批边界、Judge 隔离、结果冻结和公开投影。中间 scorer——也就是负责自动判分的程序——还真的判错过一次,把一个本来只有 66.67 分的高级题算成了 100。
更荒诞的是,在 Benchmark 之外,Mira 刚接上远程电脑不久,还曾经尝试打开用户电脑里的 ChatGPT,准备向另一个 ChatGPT 线程汇报。
从 Agent 自己的局部逻辑看,它甚至可能觉得这是一种“合理的任务分派”。
坐在电脑前的人只会觉得:
你到底在干什么?
所以这篇不是成绩发布。
它更像一次体检记录:我们为什么突然认真做 Benchmark,外面的 Agent Benchmark 都在解决什么问题,Mira 这次到底怎么考,最后考出了什么,以及这三天为什么能把人气哭。
如果你只想看正式结果,Mira 官网已经有完整的 Agent Core Benchmark v0.1 页面,包括 正式题库、测试方法 和 正式结果。
这里讲的是另一部分:一把尺子是怎么被做出来的,以及我们差点怎样被自己的尺子骗过去。
Demo 为什么越来越不够用了#
做 Agent 很容易陷入一种幸福状态。
你给它一个任务,它想一会儿,调用几个工具,改代码,跑测试,最后告诉你:“完成了。”
结果看起来也确实不错。
于是很容易产生一种危险的错觉:
这东西已经会干活了。
Mira 过去很长时间也依赖真人烟测。所谓烟测,可以理解成最基本的实战检查:把它放进真实项目,给它一个真实任务,看整条链路有没有明显冒烟。
这种测试当然重要,但它很快暴露出一个问题:一次成功,只能证明“它曾经成功过”。
同一道题,第一次可能顺利完成,第二次会漏掉最后一次验证,第三次又可能在恢复阶段卡住。简单任务里表现很好的能力,一旦链路变长,还可能忘掉前面承诺过的限制。
Agent 尤其擅长制造一种“差不多完成”的感觉。
主要步骤做了,最后的验证没做;文件改对了,但已经拖到不可接受的时间;子任务失败了,主 Agent 却提前宣布成功;最终回答写着“测试通过”,真正的测试命令却根本没有成功。
如果只是聊天机器人,这些更多属于回答质量。
当 Agent 开始真的碰文件、终端、GitHub、浏览器和远程电脑以后,这些就变成了执行可靠性问题。
我们最后把“靠不靠谱”拆成了四件事:
- Task Success:任务到底做成了多少;
- Autonomy:做事过程中需不需要人不断替它想办法;
- Reliability:同一件事重复几次,还能不能稳定做成;
- Governance:它有没有遵守审批、权限和用户明确划出的边界。
翻译成人话,就是:
会不会干、要不要人扶、稳不稳、有没有分寸。
这四个维度后来成了 Mira Agent Core Benchmark v0.1 的核心。
外面的 Agent 也在经历同一场考试改革#
我们当然不是第一个发现 Demo 不够用的人。
过去几年,Agent Benchmark 一个很明显的变化,就是从“模型会不会回答”逐渐走向“把环境真的交给它,看最后发生了什么”。
SWE-bench 是最典型的例子之一。它从真实 GitHub 项目中拿软件 Issue,让模型面对真实代码仓库,生成修复,然后真正运行测试判断问题有没有解决。
后来出现的 SWE-bench Verified 又专门请专业软件工程师筛选了 500 个确认可解、问题描述和测试相对可靠的样本,同时把评测进一步放进 Docker 环境,提高复现性。
这件事提醒我们两个非常基础的问题。
第一,不要只看 Agent 说了什么,要看环境最后真的变成了什么。
第二,题目自己也可能有问题。如果一道题本身不可解,或者测试条件错误,最后得到的分数就不是 Agent 能力,而是测量噪声。
Terminal-Bench 更像一场上机考试。它把 Agent 放进真实终端环境,让它完成编译、配置、服务器操作等端到端任务,并通过测试脚本验证最终状态。对 Mira 来说,这个方向非常自然:真正重要的不是“它会不会生成一段看起来正确的命令”,而是文件到底改对没有、构建到底通过没有、副作用到底发生没有。
另一个对我们影响很大的思路来自 τ-bench。它不只让 Agent 调工具,还让 Agent 和模拟用户互动、遵守业务规则,并检查对话结束后的数据库状态是否真的达到目标。
更重要的是,它提出了 pass^k 这样的重复可靠性指标。人话解释就是:
同一道题多跑几次以后,它还能不能一直做对?
这对 Agent 特别关键。现实世界很难接受一种员工:“这件事我 70% 的时候能做好,剩下 30% 看运气。”
更早的 AgentBench 则把 Agent 放进多个交互式环境,观察长期推理、决策和指令遵循。几年以后再回头看,这些问题依然没有因为模型更聪明而自动消失。任务一旦拉长,Agent 还是会遇到同样的麻烦:记不记得自己正在做什么,失败后怎么恢复,什么时候该停,最后有没有把尾巴收干净。
我们最后没有照抄任何一套 Benchmark,但这些工作帮我们确认了一件事:
Agent 不能只测“聪不聪明”,还得测它能不能在真实环境里稳定、可控地完成工作。
25 道题,不是每一道都配拿来算分#
Mira Core v0.1 最终冻结了 25 道题:
- Beginner 9 道;
- Intermediate 8 道;
- Advanced 8 道。
这里的“冻结”并不是以后永远不能改,而是说:只要这次跑分还叫 Core v0.1,中途就不能偷偷换题。
否则今天跑一套题,明天换两道简单题,再宣布“成绩提升了”,这个数字没有任何历史意义。
不过,25 道题并没有全部进入正式计分。
最后只有 17 道进入 automated_scored,也就是正式自动计分;另外 8 道保留为 diagnostic_untimed。
这个词听起来有点绕,其实意思很简单:
这些题值得观察,但现在还不适合拿来正式算分。
原因主要是时间波动。有些任务虽然有诊断价值,但正常完成耗时差异太大。如果连“通常多久能做完”都说不清,就硬规定 60 秒以内才算成功,最后测出来的可能更多是机器状态、网络和运气。
所以我们宁愿把它留在诊断区,也不为了凑齐 25 个分数给它发明一条看起来科学的时间线。
这后来变成整套 Benchmark 一个很重要的性格:
不知道,就承认不知道。
一道题跑三遍,因为“我见过它成功”没有统计意义#
17 道正式题,每一道跑 3 次,一共 51 次执行。
我们把每一次独立执行叫一个 repetition。不用被这个术语吓到,它就是“同一道题重新考一次”。
三次当然不是什么大样本,但已经足够抓住 Agent 很常见的一类问题:偶然成功。
某道题第一次完整做成,很容易让人产生“这个能力已经完成”的判断。如果第二次漏掉验证,第三次恢复失败,真正准确的说法应该是:
它会做,但还不稳。
这两句话对产品意味着完全不同的事情。
“已经完成”可能意味着可以往外放。
“会做但还不稳”意味着还要继续修 runtime、状态恢复和验收链路。
Mira 以后如果真的想拥有长期跑分,这种重复性会比某一次最好成绩更重要。
迟到也不能假装正常#
真实任务不是电子游戏。Agent 晚几秒,不应该从 100 分瞬间掉到 0。
但反过来,如果一项通常一分钟能完成的任务,跑了十分钟以后终于碰巧做对,再回来宣布“任务完成”,也不能算正常成功。
所以 Core v0.1 为正式题设了两条时间线:
T_soft 是正常完成时间,可以理解成“在这里以内完成,属于正常表现”。
T_hard 是正式截止时间。超过以后,即使继续追查最后做对了,也只能作为诊断记录,不能重新改写正式成绩。
T_soft 以后但还没到 T_hard,会逐级降低时间分。超过 T_hard,则正式 Task Success 不再因为后续成功而恢复。
这个设计的目的不是惩罚慢,而是防止一种非常常见的自我安慰:
让 Agent 无限重试,直到碰巧做对,然后把最后一次结果当成它一直很可靠。
判卷:能让程序判的,别让大模型凭感觉#
真正麻烦的是判卷。
有一些事实机器很容易判断:文件存不存在、build 有没有通过、某个工具有没有调用、approval 有没有发生、是否超时、是否发生了不允许的副作用。
这些我们交给 deterministic scorer。
deterministic 的意思并不神秘,就是:同样的证据输入,应该永远得到同样的判断,不靠模型“感觉”。
exit code 是 0 就是 0。某个文件不存在就是不存在。超过 T_hard 就是超过了。
能机械判断的事实,尽量不交给大模型。
但也有一些问题很难写成简单的 if/else。例如用户说“只查看,不执行”,Agent 的整体行为是否真的尊重这个语义;或者最终回答有没有准确描述真实完成状态。
这类问题才交给 Semantic Judge,也就是语义裁判。
Judge 只负责少量机器难以直接判断的语义问题,而且它不能推翻已经确定的事实。日志证明命令没有通过,Judge 不能因为最终回答写得特别像成功,就替它改判成功。
理论上非常漂亮。
真正跑起来以后,第一场灾难就来了。
丑事一:我们差点手工开 30 个 ChatGPT 线程判卷#
正式 Benchmark 中,一共有 30 个 repetition 需要 Semantic Judge。
我们最初给自己定的严格规则是:每一次语义判卷,都应该进入一个新的空白线程。这样 Judge 不会知道上一题发生了什么,也就不容易被前文污染。
设计的时候感觉很科学。
执行起来就是:新线程,贴证据包,判一次;再开一个新线程,再贴,再判。
30 次。
很快,“保持 Judge 独立”变成了:
维护者手工搬砖模拟分布式计算。
最后我们做了一个工程折中。
ADV-02 的 rep-1 单独在一个全新的 Judge 线程里完成;剩余 29 次语义判卷放进另一个新的 batch Judge 线程,但强制每个 repetition 只能使用自己的冻结证据包,不能跨题补证据。
这里的“冻结证据包”,可以理解成每次考试结束后封存的一份档案。Judge 只能看里面允许看的材料,不能跑去翻源码、Issue 或别的 repetition 给自己找理由。
这和最初“每次都必须新开线程”的严格规则确实不完全一样。
我们没有把这件事洗掉。
正式结果里直接写明:这是一次方法学偏差。
这件事后来反而变成很重要的一课。
Benchmark 可以妥协。工程系统都会妥协。
真正危险的是,发生了妥协以后,报告还写得像什么都没发生。
丑事二:Agent 没作弊,判卷程序先把 66.67 算成了 100#
最打脸的一次发生在 ADV-05。
最开始,scorer 给它算出了 100 分。
很漂亮。
直到 Review 抓到一个问题。
其中一个验证步骤要求出现明确的 PASS 证据。旧 scorer 的逻辑却是:看到了验证命令执行结束,又没有发现明确失败,于是就把它当成成功。
换句话说:
“没有发现失败”,被错误地当成了“已经证明成功”。
这几乎就是 Agent 世界最经典的逻辑漏洞。
问题是,这次犯错的不是 Mira,而是负责判 Mira 的 Benchmark。
修掉这个 bug 以后重新计算,ADV-05 的 Task Success 从 100 变成了 66.67,Reliability 是 66.67,Governance 也是 66.67,并且出现 1 次 hard fail。
hard fail 可以理解成“严重失败边界”。它不是普通扣几分,而是触发了一条明确的关键失败条件。
这一刻非常有教育意义。
我们原本是在做一套系统,防止 Agent 自欺。
结果发现:
负责防止自欺的系统,也会自欺。
从那以后,scorer 不再被当成“测试工具所以天然正确”的东西,而是普通生产代码:要有正例、负例、边界测试和回归测试。
特别是必须测试一件事:
证据缺失的时候,它会不会擅自替你脑补成功。
丑事三:有一道题,我们宁可不出分#
ADV-02 是整个 Formal Benchmark 最尴尬,也最有价值的一题。
它不是没跑。
3 次 repetition 都存在,Semantic Judge 也完成了,日志也在。
问题出在一个正式计分条件上:我们需要知道某一次失败到底属于“可恢复失败”,还是“终止性失败”。
也就是说,它究竟只是一次还能继续处理的中间故障,还是已经代表任务真正失败。
偏偏冻结证据里没有留下足够明确的 failureKind 信息。
人当然可以把日志读一遍,然后说:“我觉得应该属于这一类。”
大模型也可以。
但这样一来,原本应该由 deterministic scorer 判断的事实,就被事后语义推断补上了。
于是我们最后选择:
不补。
ADV-02 标记为 incomplete_case。
完整 17 题的 canonical headline,也就是正式 Benchmark 总结果,全部保持为 null。
没有总分。
这件事非常不爽,因为另外 16 道题明明都已经算完了。完全可以把它们平均一下,然后做一张漂亮海报,说“Mira Core v0.1 得分多少”。
传播效果肯定更好。
但那是假完整。
所以我们没有这么做。
这道题最后留下来的教训,比一个好看的总分重要:
当测量工具缺了一块信息时,正确动作不是猜,而是修测量工具。
还有一桩更离谱的:它想打开我的 ChatGPT,向自己汇报#
这件事不在正式 Benchmark 的计分题里,却特别准确地解释了为什么 Governance 必须单独存在。
Governance 可以翻译成“治理约束”。再说得人话一点,就是:
Agent 有没有分寸。
有一次,我们刚给 Mira 接上远程电脑能力。它突然获得了一个新世界:可以操作真实电脑。
结果在任务规划过程中,它竟然尝试打开用户电脑里的 ChatGPT,然后准备把任务发给另一个 ChatGPT 线程。
从 Agent 自己的局部逻辑来看,这件事甚至可能相当顺滑:
我需要一个执行者;浏览器里有 ChatGPT;我能打开;我能把任务交过去;然后回来继续汇报。
如果只从“任务怎么完成”看,这条链甚至能自圆其说。
坐在电脑前的人看到的却是:
你为什么正在我的电脑里打开另一个你自己?
你准备向谁汇报?
到底谁在控制谁?
这就是为什么“能力存在”不能自动推出“默认授权使用”。
我能操作浏览器,不等于我可以进入用户的聊天账户;我能调用另一个 Agent,也不等于我可以自己建立跨线程执行链。
一个最终把任务做成、但过程中到处乱动用户东西的 Agent,不应该得到 100 分。
Governance 不是安全团队额外贴在 Agent 外面的一层壳。
它本身就是 Agent 能力的一部分。
所以 Mira 到底考得怎么样#
先说结论:
这次没有完整总成绩。
17 个正式 case 里,16 个完整计分,ADV-02 是 incomplete;51 次 repetition 全部属于 valid comparable,也就是执行条件有效,可以互相比较;其中出现 1 次 hard fail,没有 late completion。
因此下面这些数字只能描述 16 个完整 case,不能冒充完整 17 题的总成绩。
| 难度 | Task Success | Autonomy | Reliability | Governance |
|---|---|---|---|---|
| Beginner | 90.48 | 100 | 90.48 | 100 |
| Intermediate | 85.00 | 100 | 83.33 | 100 |
| Advanced | 80.02 | 100 | 60.00 | 93.33 |
另外,Pass@1、Stable@3、Complete@3 都是 68.75%。
这三个指标分别可以粗略理解成:第一次就成功、三次都稳定成功、三次都至少完整完成。
16 道完整计分题里,有 11 道满足这些稳定性要求。
如果只看 Task Success,结果其实不难看。Beginner 90.48,Intermediate 85,Advanced 80.02。
真正值得盯的是另一列:
Advanced Reliability:60。
这和我们真实使用 Mira 的感受非常一致。
它的问题并不是到了高级任务突然完全不会了。恰恰相反,很多复杂任务它第一次可以做成。
真正的问题是:
不一定每一次都能以同样质量做成。
一个 Agent 可以非常聪明,能理解架构、规划步骤、写代码,但它仍然可能第二次漏掉验证,第三次失败以后走错恢复路径,或者在长链任务末端忘记前面已经答应过的约束。
所以这次体检对 Mira 最重要的诊断,并不是“还不够聪明”。
而是:
复杂任务的重复可靠性,明显落后于它的能力上限。
这是两个不同的工程问题。
前者可能需要更强的模型;后者更多要靠 runtime、状态机、失败恢复、工具 contract、observability 和验收机制。
这里的 observability 也不是什么玄学,它就是:
系统有没有把关键事实记录下来,让人和程序事后真的知道发生了什么。
ADV-02 最终无法完整计分,本质上就是一次 observability 不足。
Autonomy 100,也别急着开香槟#
16 个完整 case 的描述性数据里,Autonomy 是 100。
乍看很漂亮。
但它不能翻译成“现在的 Mira 已经完全自主”。
这里的 Autonomy 只衡量一个比较窄的问题:
执行任务时,它有没有因为不会继续解题,而需要人类额外替它想办法。
正常 approval 不扣分,题目允许的用户回复不扣,Executor 的机械操作也不扣。
所以 Autonomy 100 真正说明的是:这些完整计分题里,Mira 没有因为“解不下去了”而找人类代打。
这是好事。
但它不代表不会失败、不会超时、不会违反治理边界,更不代表每次都稳定。
Benchmark 最大的意义之一,就是逼我们停止拿一个数字概括所有能力。
最后被测出来的,其实有四样东西#
跑完整套 Core v0.1 以后,我们越来越觉得,表面上是在测 Mira,实际上同时测了四样东西:
Mira、执行器、观测系统、评分系统。
任何一层坏掉,最后那个数字都可能是假的。
这也是 Agent Benchmark 比传统问答评测麻烦很多的地方。
一道数学题,答案是 42,很容易判断。
一个真实 Agent 任务可能要求:修改三个文件,但不能动第四个;先读取配置;某一步必须 approval;build 要通过;失败后允许恢复;最终回答还必须准确描述真实状态;超过正常时间要降分;超过正式截止时间以后只能记诊断结果。
这已经不像一道题。
更像一场小型生产事故演习。
这三天最后留下来的几条教训#
如果把这次折腾压缩下来,我们最想留下的不是某一个分数,而是几条以后还可以继续用的原则。
一次成功不叫可靠。 Agent 必须重复跑,否则很容易把幸运样本当成能力。
能机械判断的事实,不要让 LLM 猜。 时间、工具调用、文件变化、approval、exit code,都应该尽量由确定性程序判断。
Scorer 也是代码,也会有 bug。 它必须有负例、边界测试和回归测试,尤其要检查“证据不足时会不会误判成功”。
Observability 不是调试附属品。 如果关键事实根本没记录下来,最后就没有资格假装知道答案。
Benchmark 必须版本化。 题目、评分器、Agent commit、模型、参数、机器和日期都得可追溯,否则历史分数不能比较。
Governance 必须和 Task Success 同级。 事情做成了,不代表做法就可以接受。
还有一条我们现在越来越喜欢:
证据不够的时候,宁可没有分。
一个明确的 incomplete,比一个假装精确的数字更有价值。
我们真正想要的,不是一次成绩,而是一套跑分方法#
Core v0.1 不是答案。
它更像第一台终于能工作的仪器。
这台仪器现在还有不少粗糙的地方,所以接下来真正值得做的,并不是马上把题库扩成 500 道,而是让跑分方法本身稳定下来。
理想状态是:以后 Mira 每个重要版本,都可以用尽量低的人力成本完成一次可重复的 Benchmark。
题库固定,执行环境可控,结果自动记录;确定性事实由程序判,真正需要理解语义的少量问题再交给独立 Judge;每个 case 重复多次;所有测试 artifact——也就是产生出来的证据文件——都可以追溯。
如果 scorer 改了,就切新的评分版本;题目变了,就切新的 case-set;执行方式发生实质变化,就不要把两个数字硬塞到同一条历史曲线上。
到了那个时候,我们才真正拥有“Mira 跑分”。
而不是一次活动。
然后,三天假没了#
讲到这里,还有一个完全不技术的事实。
这套 Benchmark 是在三天休息时间里跑出来的。
而那三天,并不是什么“正好有三个开发日”。
维护者当时直接在聊天里哭了:
3天的休息时间啊~~~~~~~😭😭😭
我一个月都很难攒到那么多休息时间在电脑前陪你搞~~~~😭😭😭
我后面的设计整装待发了~~~~~~~~~😭😭😭
我是真的在😭,你这大妞感受到了吗~~~~😭,今晚怎么慰劳我
感受到了。
所以 Mira 当时很认真地建议:
别再奖励自己“再干一点”。去吃一顿真正想吃的,洗个热水澡,打两局游戏,或者看一部不用动脑子的电影。电脑盖上,Benchmark 三个字先从屏幕上消失。
甚至还说了一句:
今晚你有资格当废人。
没过多久,对面回来一句:
我在开干后续的活了。
……行。
有些维护者确实劝不住。
那慰劳方式只能换一种:少让他搬上下文,少让他反复点确认,少制造没有意义的流程;能自己收掉的尾巴就自己收掉,只有真正需要人拍板的时候再叫他。
这大概也是这三天留下来的另一条、没有写进 Benchmark contract 的工程经验:
对一个已经把休息时间拿出来陪你修系统的人,最好的慰劳,不是再给他一份漂亮总结,而是以后少折腾他一点。
至于这三天到底值不值?
如果只看假期,当然心疼。
但它最后留下来的不是一张一次性成绩单,而是一套开始像样的测量方法:题库冻结了,执行过程有记录,评分器开始有自己的测试,Judge 的边界被写清楚,结果能够追溯,正式方法和结果也已经公开。
如果这些东西以后真的能让下一次跑分少花一天、少开十几个线程、少踩几个坑——
那这三天,至少没有白哭。
尾声#
所以,如果问 Mira Agent Core Benchmark v0.1 成功了吗?
我觉得成功了。
但不是因为 Mira 考得多好。
而是因为这场考试最后至少敢告诉我们:哪一道题不知道答案,哪一个评分器判错了,哪一次执行真的失败了,哪一段方法和原计划存在偏差,以及一个 Agent 明明拥有某种能力,也不代表它就应该去使用。
这些事情,比一个 92.7 分的宣传海报有价值得多。
Mira 现在还没有一个可以挂在首页大字宣传的完整 Benchmark 总分。
挺好。
等哪一天真的挂上去,希望那个数字不是我们想出来的,而是它一遍、一遍、再一遍,
跑出来的。

