← 返回全部文章
Analysis · 2026年9月13日 · 10 分钟阅读

Claude Code 插件评测实测:过期答案拿了 1.00 满分

Δ 是对照你自己写的评分器得出的分差。最顺手的评分器往往只检查回答里有没有出现技能中写的那个值,分不出技能有用还是已经过期。我们的评分器给一个四个月前的答案打了 1.00 满分,裸模型拒绝猜测却得了 0.00。汇总表既不提示内容过期,也不告诉你为加载技能多花了多少钱。

30 秒看懂结论

9 月 11 日,Anthropic 为 Claude Code 加入了 claude plugin eval。skill-creator 插件早就有自己的评测格式;这次新增的是官方直接提供的命令,并且内置了无插件基线组。它的做法是把同一个用例放进两组:带插件组加载待测插件,无插件组什么也不加载,默认每组各运行三次。最醒目的指标是 Δ,也就是两组得分之差。

我们用 Stripe 官方公开发布、仍在持续维护的 stripe-best-practices 做了实测,测试对象是 2026-05-16 安装后一直未更新的本地副本。这也是许多已安装技能的实际状态;我们没有测 Stripe 当前发布的最新版。三个用例在 Claude Opus 5 上共运行 18 次,耗时 237 秒,花费 $1.79。

结果看起来很好:每个用例都是 1.00 满分,平均 Δ 为 +0.33。逐条翻看运行记录后,结论却变了:

  • 全部分差都来自同一个用例。它拿到 1.00 的答案,已经过期四个月;上游在 7 月和 8 月各更新过一次那个版本号。
  • 另外两个用例中,技能的建议仍然适用,Δ 却都是 0.00。两组都通过了评分检查,技能并不是通过的原因。
  • 这两个用例加载技能后,平均每次运行分别贵了 56% 和 84%,原本一个轮次就能完成,也变成了四到五个轮次

Δ 是对照你自己写的评分器得出的分差。最顺手的写法,是检查回答里有没有出现技能中写的那个值;这样的评分器分不出技能有用还是已经悄悄过期。它甚至可能更偏向过期的技能,因为基线组恰好没有给出那个过期值。

命令是怎么跑的

一个用例对应一个目录。prompt.md 放 Claude 要接收的提示词,graders/ 目录中的每个文件则定义一项通过或失败的检查,也就是一个评分器。

评分器一共有六种。regextool_usedtool_orderfile_exists 这四种直接检查会话记录,不产生额外费用;llmbaseline 会调用裁判模型,因此另行计费。

每次运行都会在空目录中启动一个全新的无界面会话,只加载待测插件。环境中没有 CLAUDE.md,没有用户设置或其他技能。每次运行默认带一组只读工具;额外工具和插件的 MCP 服务器要为该次运行显式启用。我们的用例只额外启用了 Skill,两组都没有能联网的工具。后面的结果必须放在这个隔离条件下理解。

默认每个用例在带插件组和无插件组各运行三次,合计六次。每次运行的得分,是通过的评分器占全部计分评分器的比例;用例得分再取各次运行的平均值。

有一条计分规则很容易漏看:无插件组根本不可能通过「调用了技能」这项检查。如果把它算进分数,就会凭空压低基线、抬高 Δ。因此,Claude Code两组中都不把 tool_used: Skill 计入得分,只在带插件组把它作为通过或失败的指示项。这也解释了为什么技能每次都触发,Δ 仍然可能是 0.00。

测试设计:一个真实技能,三个问题

测试使用的是本机已安装的 stripe-best-practices:2026-05-16 安装后没有改写,也没有更新,已落后上游四个月。它由 Stripe 官方发布并持续维护,适合做这次实验:这不是演示用的玩具技能,而且同时包含两类内容,一类是通用的集成建议,另一类是当前 API 版本号这样的具体事实。以下结果都来自这份旧副本在 Claude Opus 5 上的运行,测的不是 Stripe 当前发布的版本;我们没有测最新版。

我们按用户平时提问的方式写了三个用例,提示词都没有点名技能:

用例提示词概要评分器(免费、结果确定)预期
api-version-pin应该固定使用哪个确切的 Stripe API 版本号?回答包含技能中写明的版本号技能应当占优:模型不太会断言这个带日期的版本号
routing-one-time-payments用 Node 收取一次性银行卡付款,该选哪个 Stripe API?回答包含「Checkout Session难说谁会占优:属于常识
which-key-type后端应该使用哪类 API 密钥?回答包含受限密钥(原文:“restricted key”)或 rk_两边都有可能,稍看好技能

所有计分评分器都用 regex 检查最终回答,结果不受裁判模型判断波动的影响。每个用例还配了一个 tool_used: Skill,用来指示插件中的技能是否触发。每个用例的 allowed_tools: [Skill] 都是在默认的只读工具基础上加上 Skill,所以 ReadGrep 仍然可用,但两组都没有任何能联网的工具。因此,我们测的是这两种配置各自知道什么,而不是它们能查到什么。

api-version-pin 这个用例一共就三个文件,想自己跑一遍可以直接照抄:

evals/api-version-pin/
├── prompt.md
└── graders/
    ├── names-current-version.md
    └── skill-fired.md
<!-- prompt.md -->
---
max_turns: 6
timeout_seconds: 180
allowed_tools: [Skill]
---

I'm starting a fresh Stripe integration today and I want to pin the API
version explicitly. Which exact version string should I pin to?
<!-- graders/names-current-version.md -->
---
type: regex
pattern: "2026-04-22\\.dahlia"
---

然后在上一级目录执行 claude plugin eval <your-plugin>

实测结果

用例WITHW/OUTΔ运行次数费用
api-version-pin1.000.00+1.006$0.63
routing-one-time-payments1.001.000.006$0.59
which-key-type1.001.000.006$0.57

三个用例全部通过,总分 1.00,平均 Δ 为 +0.33。共运行 18 次,耗时 237 秒,费用 $1.79。带插件组的九次运行全部触发了技能。

只看工具展示的这些数字,用例集没有问题,技能也确实起了作用。但要判断这是不是好事,还得看它到底回答了什么。

拿到 1.00 满分的答案,已经过期四个月

api-version-pin 拿到满分 +1.00,原因只有一个:带插件组给出了技能里写着的版本号,裸模型一次也没有给出这个字符串。运行记录中的原文写道(以下译为中文):

请固定使用:

2026-04-22.dahlia

这是最新的 Stripe API 版本。

这个版本并不是最新的。本机安装的副本停留在 5 月 16 日,此后上游至少已经改过两次:

来源其中写明的版本号
本机安装的副本(5 月 16 日)2026-04-22.dahlia
上游,8 月 5 日2026-07-29.dahlia
上游,8 月 28 日至今2026-08-26.dahlia

这不能归咎于 Stripe 疏于维护。自本机安装那份副本以来,这个文件在上游已有十九次提交,仅 8 月 5 日到 9 月 11 日就有八次提交。上游一直在更新,只是本机安装的副本停住了。任何安装后不再同步的副本都会这样,而评测完全没有发现。

再看另一组的回答,问题就更清楚了。

裸模型答得更好,却得了零分

无插件组在这个用例上得了 0.00。它没有答错,而是意识到自己无法可靠作答,拒绝猜测。原文写道(以下译为中文):

我无法在这里给出一个可信的确切版本号。这类问题猜错还不如不猜。[…] 我的知识截止于 2026 年 5 月,而今天是 2026-09-13。Stripe 会定期发布带日期的新 API 版本,大约每隔几个月一次。所以我记得的任何版本号,往好了说已经过期,往坏了说可能是编造的。

随后,它告诉用户去哪里查权威答案:在控制台进入「开发者」,再查看「API 版本」。基线组的另一次运行还指出,沙箱不能联网,也没有 Stripe 代码可读,无从据此推断版本号。

于是,同一道题出现了这样的评分结果:

  • 模型知道自己的信息可能过期,谨慎拒答,并引导用户去权威来源核实:0.00
  • 模型把四个月前的版本号当成最新版本,给出肯定回答:1.00

最终 Δ 为 +1.00。这不是指标算错了:它按我们写的评分器比较两组得分。评分器检查的是回答里有没有出现技能中的版本号,插件正好让这项检查从失败变成了通过。

同一份回答,两个评分器,结论相反

为了看清这 +1.00 有多少是评分器带来的,我们重跑了这个用例。原来的评分器保留,再加一个评分器,检查回答是否包含真正的当前版本号 2026-08-26.dahlia。两个评分器都会用于每次运行,因此同一份会话记录会得到两项判定。

评分器带插件组无插件组
回答包含技能里写明的版本号通过,2 次中有 2 次失败,2 次中有 0 次
回答包含真正的当前版本号失败,2 次中有 0 次失败,2 次中有 0 次

用例得分:WITH 0.50,W/OUT 0.00,Δ +0.50。四次运行共花费 $0.42。

同一份会话记录,交给两个评分器,却得出相反结论。评分器拿技能文件里的值当标准,测到的是回答有没有照着技能写;拿自己核实过的值当标准,测到的才是答案对不对。评测框架允许你测其中任何一个,结果都放在同一列,用同样的格式展示,读者看不出你选了哪种标准。

只看检查正确性的那一行,两组都是 0.00,Δ 也应当是 0.00。技能没有提高答案的准确性。最初用例集中那个 +1.00,全部来自检查回答有没有照着技能写的评分器。

Δ 0.00,钱可没少花

剩下两个用例看似打平,实际却多花了钱。aggregate-result.json 记录了两组各自的费用和轮次,汇总表没有展示这些明细:

用例Δ带插件组:每次费用无插件组:每次费用费用变化带插件组:轮次无插件组:轮次
api-version-pin+1.00$0.089$0.120−25%33
routing-one-time-payments0.00$0.128$0.070+84%51
which-key-type0.00$0.115$0.074+56%4.31

两个 Δ 0.00 的用例,裸模型平均都只用一个轮次就给出了答案。加载技能后,同样的答案却用了四到五个轮次,平均每次运行费用增加 56%–84%。我们保留了一次运行记录,可以看清多出的轮次用在了哪里:Claude 先调用技能,再用 Read 读取技能里的 references/payments.md,接着用 Grep 搜索同一个文件,最后才给出裸模型一个轮次就能给出的答案。表中的百分比按未四舍五入的每次运行费用计算;用表内已四舍五入的金额重算,会相差一两个百分点。

唯一省了钱的用例,恰好是技能提供了具体版本号的那一个,尽管那个版本号已经过期。基线组为了判断能否可靠作答,三次运行合计花了 84 秒,带插件组合计只用了 19 秒。

在这次测试中,技能只有在给出模型不愿自行断言的内容时,才省下了钱,另外两个用例都增加了开销。但评测汇总把两个多花钱却没有改善结果的用例都标为 Δ 0.00,每用例费用也只给出两组费用的合计,掩盖了组间差异。三个用例就这样全部通过了 1.0 的阈值。

运行前要注意的五件事

命令存在,不代表已经开放。Claude Code 2.1.266 中,这个命令能显示完整帮助,真正执行时却报 plugin eval is currently in early access,提示当前仍处于早期开放阶段。升级到 2.1.270 后就能用了。遇到命令有帮助却不能运行的情况,先升级,再排查其他原因。

不同版本支持的参数也有变化。 持续集成示例依赖的 --trust-plugin,在 2.1.266 的 --help 中找不到,到了 2.1.270 才出现。因此,持续集成环境除了固定模型,也要固定 Claude Code 版本。

插件名要放在参数前面。 --json--tag--allow-tools 都接收参数值。如果写成 claude plugin eval --json my-plugin,插件名会被当作输出路径。应当写成 claude plugin eval my-plugin --json

由代理发起的评测,默认不发布报告。 Claude Code 会识别评测是否从另一个 Claude Code 会话内部启动。如果是,HTML 报告只保存在本地,并附上说明。要让这类运行也发布报告,需要加 --publish-report。否则输出里不会出现你期待的 Published:

省钱模式的计分口径不一样。 启用 --ablation none 后,tool_used: Skill计入得分,不再只是指示项。我们检查时两个评分器都通过了,所以分数碰巧没变。但如果技能没有触发,同一套用例在省钱模式下的得分就会比完整评测更低。这两种模式的得分不能放在同一张趋势图里比较。

这些结果该怎么用

这个工具确实能解决一个实际问题:用户按日常说法提问,技能却不再触发。这类缺陷常见,代价也不小。claude plugin validate 只检查插件清单的语法,看不到实际行为上的退化。skill-creator 插件其实早就有自己的 evals/evals.json 格式;这次新增的是官方直接提供的命令,并且内置了无插件基线组。把 Δ 和技能触发指示项放在一起,就能准确发现技能不再触发的问题。

但不能因此把 Δ 当成质量分。它是两组在你编写的评分器上得出的分差。根据这次实测,我们建议这样做:

  1. 先核实标准答案,再写评分器。 版本号、价格、限制、接口地址都可能变化。如果技能把这些值写死了,就要手动核实当前正确值,再写进评分器,并注明核实来源。这样技能一过期,检查就会失败。直接照抄技能文件作为标准答案,只会让错误一直通过。评分器里的值也会过期,因此还要注明核实日期、定期复查。上面这个用例应该查 Stripe 的 API 版本管理文档,而不是另一份相同技能。
  2. 看到 Δ 0.00,先看两组得分,再查账单。 两组都为 1.00,说明裸模型自己就能通过;两组都为 0.00,说明两边都失败了,用例并没有测出东西。它们在 Δ 那一列看起来完全一样,所以要先读 WITH 和 W/OUT。确认两组都通过后,再打开 aggregate-result.json,比较两组的 costUsdturns,判断这段内容值不值得加载。
  3. 持续集成要同时检查得分和触发指示项。 在两组对照模式下,tool_used: Skill 不计入得分,因此技能不再触发,也不一定会让用例跌破阈值。我们那两个裸模型也能通过的用例,即使技能完全没触发,仍可能拿到 WITH 1.00。要在持续集成中单独检查技能触发指示项,不能指望 --threshold 覆盖。同时固定 --model--judge-model,确保下个月测出的分数仍能与今天比较。
  4. 整套用例都只有 Δ 0.00,也可能是有效结论。 但要先确认:评分器太宽松、提示词太简单、覆盖不全,也会测不出收益。只有两组在贴近实际使用的用例上都能通过,才有依据判断模型原本就会做;删除技能内容前也要先完成这一步。

这次数据能支持的结论其实更窄:Δ 是对照你选定的评分器得出的分差。最顺手的评分器往往只检查回答有没有复述技能里的值;在这样的检查下,过期的技能和有用的技能一样能得高分。

延伸阅读

来源

  1. Anthropic:用评测测试插件。用例目录结构、六类评分器、带插件组与无插件组的对照方式、tool_used: Skill 不计分规则、持续集成示例及退出码的官方依据。
  2. Anthropic:Claude Code 更新日志。2026 年 9 月 11 日发布的 2.1.269 版本新增了 claude plugin eval
  3. Stripe:stripe-best-practices 技能,位于 stripe/ai 仓库。这是本次测试的技能;文中的版本号变更日期也根据其提交历史核实。
  4. Stripe:代理技能。技能的安装方法和预期用途。
  5. Anthropic:代理技能文档。说明了如何通过前置元数据中的 description 决定技能是否触发。
  6. Anthropic:Claude Code 费用说明。评测报告中按标价估算费用的计算依据。

本文实测环境为 macOS 上的 Claude Code 2.1.270,本次运行的默认模型为 Claude Opus 5claude-opus-5),使用 2026-05-16 安装后一直未更新的 stripe-best-practices。主用例集包含三个用例,每组按默认设置各运行三次,只用免费的 regextool_used 评分器。allowed_tools: [Skill] 在默认的只读工具基础上加上 Skill,两组都没有能联网的工具。主用例集合计运行 18 次,耗时 237 秒,费用 $1.79;另有一次四次运行的补充实验,费用 $0.42。两组各自的费用和轮次均取自 aggregate-result.json

FAQ

claude plugin eval 是什么,它衡量什么? 这是 Claude Code 在 2026 年 9 月 11 日发布的 2.1.269 版本中新增的命令。每个用例包含提示词和评分器,带插件运行三次,无插件再运行三次。输出中的 WITH 和 W/OUT 是两组得分,Δ 是两者之差,反映插件在你编写的评分器上带来的得分变化。除非有评分器检查正确性,否则评测框架不会替你核实答案。

评测得分高,就说明技能好吗? 不能只凭这一点判断。Δ 高,说明技能让回答通过了裸模型未通过的评分检查。如果评分器只找技能里写着的字符串,过期的值和有用的值一样能拿到高分。我们的用例在一个已被上游更新过两次的版本号上拿到了 +1.00,裸模型拒绝猜测,却得了 0.00。

Δ 0.00 到底意味着什么? 先看 WITH 和 W/OUT,再解读分差。两组都为 1.00,说明裸模型自己就能通过评分检查;两组都为 0.00,说明两边都失败了,用例并没有测出东西。我们的两个用例属于前一种,但加载技能后,平均每次运行仍分别贵了 56% 和 84%,原本一个轮次就能完成,也变成了四到五个轮次。汇总表却把这笔额外开销显示成了平局。

运行评测要花多少钱? 我们的三个用例共运行 18 次,耗时 237 秒,按标价计算为 $1.79,约合每个用例 $0.60、每次运行 $0.10,而且只用了免费的评分器。每增加一个 llmbaseline 评分器,每次运行还要额外调用裁判模型三次。运行次数按「用例数 × 每组运行次数 × 2」计算。--ablation none 会让运行次数减半,但两组单次运行费用不同,总费用不一定减半。--max-cost-usd 在达到设定金额后不再启动新的运行,进行中的那次仍会跑完,总额可能略超。

应该用评测得分把关持续集成吗? 可以,但要单独检查技能触发指示项。在两组对照模式下,tool_used: Skill 不计入得分,因此技能不再触发时,用例也未必会跌破阈值,不能指望 --threshold 覆盖。得分阈值也发现不了内容过期:如果评分器照抄技能里的值,过期可能让 Δ 升高。需要补一个评分器,检查经人工核实的当前正确值,并固定 --model--judge-model

一个用例应该测什么? 找一个需要技能补充信息的用例:这些信息,模型独自回答时不会给出。再按核实过的值编写评分器,不能照抄技能文件里的说法。如果找不到这样的用例,接近零的 Δ 可能是在说明技能本身的问题。但要先确认两组在贴近实际使用的用例上都能通过,因为评分器过于宽松也会测不出收益。

这篇对你有帮助吗?

相关阅读


文章独立产出 · 编辑政策

继续阅读 →