跳转到主要内容
跑完一次 niceeval exp,失败的 Attempt 都带一个 @ 开头的定位符(如 @1qrdcfq8)。它出现在运行摘要、CI 日志和报告里,定位符本身不会过期——只要 .niceeval/ 里对应的结果快照还在,今天的定位符下周还能用同一条命令打开同一次 Attempt。所有排查都从它开始。 先说一条通用规则:NiceEval 自己的报错和警告都在消息末尾直接给出下一步。能用一条命令解决的,消息里就是替换好实验名的完整命令,复制执行即可(网页里还可以一键复制);可以不管的警告会写明「什么情况下可以忽略」。所以看到报错先读完最后一句;本手册处理的是消息之外还需要人工判断的场景——判定失败了怎么定位、环境错误怎么进现场。

第一步永远是 niceeval show @<定位符>

不带任何参数打开 Attempt,第一页就是为排查设计的:判定、失败的断言、耗时分布、改动概览,以及下一步可用的命令。
看这一页先回答一个问题:是 agent 答错了(failed),还是环境根本没跑起来(errored)? 两种情况的排查路线完全不同。

场景一:断言失败(failed)——agent 跑完了,但结果不对

排查顺序是「哪条断言挂了 → agent 当时做了什么 → 它到底改了什么」。 1. 把断言放回源码。 --source 显示运行时保存的那份评估用例源码(不是你工作区里可能已经改过的版本),失败的断言直接标在对应行上;t.send(...) 的调用行标出它产生的那一轮——轮标签(s1/t1,与 --execution / --timing 用同一套)、这轮成没成、花了多久:
2. 看 agent 当时做了什么。 --execution 把这次 Attempt 的对话按时间线展开——用户消息、assistant 回复、每次工具调用的入参和结果:
对话按轮分段,每轮头行给出编号(s1/t1)、状态、耗时和用量——这个编号和 --diff--timing 里的轮次标签是同一套,能互相对照。 不想通读全文时,接 grep 定向查。列出这次 Attempt 用过哪些工具、各多少次:
想确认它有没有跑过某条命令、有没有提到某个文件,直接搜关键词:
3. 看它到底改了什么。 --diff 只显示 agent 自己改动的文件——你上传的起始文件、跑完后写入的验证材料不会混在里面,所以列表里的每一行都真的是 agent 干的:
行尾的 s1/t1 表示这个文件是在第几轮对话里被改的,能和 --execution 的轮次对上。要看单个文件的逐行改动,用 = 连写文件路径:
到这里通常能下结论:是任务描述有歧义、agent 理解错了,还是断言本身写得太死。 要看文件本身,而不只是改动? 落盘的证据刻意不保存整个工作区——--diff 只有 agent 改过的文件,agent 该写没写的文件、你上传的起始材料、setup 装出来的东西都不在里面。想看它们的实际内容,进活现场:重跑这一条评估用例加 --keep-sandboxfailed 的 Attempt 同样会保留,不只是环境错误),用下面场景二的方式进 Sandbox,workdir 里就是这次跑完时的完整文件树。

场景二:环境错误(errored)——agent 根本没跑起来

errored 的第一页不列断言,而是列出错误发生在哪个阶段、什么原因:
phase 直接告诉你死在哪一步,而且决定了下一步走哪条路: sandbox.create 失败——Sandbox 根本没创建出来,没有现场可留。 这类错误(配额、限流、凭据、镜像 / 模板不存在)在你自己的机器和账号侧排查:核对 API key 和配额、降低 --max-concurrency、确认镜像 / 模板名。示例里的 rate-limit 就属于这类,重跑加 --keep-sandbox 只会原地再死一次。 sandbox.setup / agent.setup / eval.run 失败——Sandbox 活过,值得留现场。 装依赖失败、agent CLI 起不来、跑到一半超时,这类问题事件流往往是空的,落盘证据帮不上忙,最快的办法是留住现场进去手动重跑一遍出错的命令:
niceeval sandbox enter a3f9c2d1 会唤醒现场并在 workdir 打开 shell——手动执行安装命令看真实报错、翻 $HOME 下的配置、检查 PATH,这些都在 artifact 之外,只有活现场能回答;退出 shell 后现场自动回到休眠,不白烧资源。保留策略、各 provider 的差别见保留 Sandbox 现场

查看和清理留下的 Sandbox

保留下来的 Sandbox 不会一直烧资源:Docker 容器停驻在磁盘上,E2B 微 VM 暂停计费,进入时自动唤醒。用 niceeval sandbox 管理:
dormant 是「睡着但随时能进」,expired 是「现场已经没了,只剩记录」。排查完记得清理:

场景三:复盘旧的运行

每次运行都会在 .niceeval/<实验>/<时间戳>/ 下留一份完整的结果快照,判定、断言、事件流、diff 都在里面,不会被下一次运行覆盖。复盘有三个入口: 用旧定位符直接打开。 从上周的终端记录、CI 日志或报告里复制 @ 定位符,niceeval show @<定位符> 照常工作,上面的 --source / --execution / --diff 全部可用——包括那份运行时的评估用例源码,哪怕你后来把评估用例改了。 按实验回看现在的判定。 不记得定位符时,从实验入手:
列表里每道题、每次 Attempt 都带定位符,接着往深处钻就回到上面的场景一 / 场景二。 同一个检查刷一批 Attempt。 从实验列表里复制定位符,套一层循环。比如核对这几次 Attempt 里谁调用过 file_change
在浏览器里翻。 复盘一批失败、对比多次 Attempt 时,网页比终端顺手:
首页是成本 × 通过率总览和实验对比表;每个 Attempt 的详情页有判定、断言、完整时间树、对话、trace 和 diff,还有「Copy fix prompt」按钮——把失败整理成一段可以直接交给 coding agent 的修复提示词。报告里的 Attempt 深链和 show 用同一套定位符。 打开归档或别人发来的结果。 结果目录是自包含的——从 CI 下载的、同事拷给你的、发布到静态站前生成的目录,都能直接指过去:
一个注意点:如果本地清理过旧快照目录,之后的运行里「沿用上次结果」的条目会找不到原始证据(显示为缺失)。要长期归档某次运行,先用 copySnapshots 复制出一份再删。

速查:症状 → 命令