跳转至

Agent Skill 评估与迭代

📊 Level ⭐⭐⭐⭐⭐ | 15.2KB

优化 description 的系统性方法

  1. 准备 20 个提示词(一半触发 / 一半不触发)
  2. 运行测试,每个用例测 3 次以上取触发概率
  3. 分析:应该触发的没触发 → 描述太窄;不应该触发的触发了 → 描述太宽
  4. 迭代直到通过率满意

测试用例设计

结构:提示词 + 预期输出 + 输入文件(可选) 技巧:

  • 从 2-3 个开始,不要一开始就写很多
  • 变化措辞(随意 ↔ 精确)
  • 覆盖边缘情况
  • 使用真实上下文(文件路径、列名等)

运行评估

两次对比:with_skill vs without_skill

iteration-1/
├── eval-top-months-chart/
│   ├── with_skill/outputs/ + timing.json + grading.json
│   └── without_skill/...
└── benchmark.json(汇总统计)

断言编写原则

好的断言 弱的断言
可编程验证 太模糊("输出很好")
具体可观察 太脆弱(措辞一变就失败)
可计数

聚合结果分析

{
  "delta": {
    "pass_rate": 0.50,
    "time_seconds": 13.0,
    "tokens": 1700
  }
}
分析模式:

  • 两种配置都通过 → 移除断言,无有用信息
  • 两种都失败 → 断言本身有问题
  • 带Skill才通过 → Skill 明显增加价值的地方
  • 高标准差 → 收紧指令,减少模糊性

迭代原则

  • 从反馈中泛化,不做狭隘补丁
  • 保持精简:少而好的指令 > 详尽规则
  • 解释为什么:基于推理的指令 > 僵化指令
  • 打包重复工作:测试用例都写类似脚本 → 应打包进 Skill

三类测试

测试一:触发测试(最关键)

  • ✅ 至少 10 个应该触发的用例 + 5 个不应该触发的用例
  • 快速诊断:直接问 AI"你什么时候会用这个 Skill",根据回答判断 description 是否准确 测试二:功能测试

  • 同一请求运行 3-5 次

  • 检查:输出结果一致、API 调用成功(0 错误)、关键步骤无遗漏 测试三:与无 Skill 基线对比 | 指标 | 无 Skill | 有 Skill | |------|---------|---------| | 用户需要提供的说明 | 每次都要解释 | 无需解释 | | 来回对话轮次 | 15 轮 | 2 轮 | | API 调用失败次数 | 3 次 | 0 次 | | Token 消耗 | 12,000 | 6,000 |

动态优化

"你刚才的输出中,[具体描述问题]。请把这个改进固化到 [skill-name] 这个 Skill 文件中。" Skill 是活文档,每次修正都可以沉淀,减少下次犯同样错误的概率。

发布门槛:把一次评测升级为持续回归与消融退休(SkillHub / DeepMind 实践,2026-08)

腾讯轻量云 SkillHub(作者 Elisedai)整理 Google DeepMind 工程师 Philipp Schmid 围绕 Gemini API 与 Agent Skill Eval 的实践,把 Skill 评测从「发布前跑一次」推进为发布门槛 + 持续回归 + 消融退休的完整工程链路。本页前述内容回答「怎么测」,本节补上「凭什么允许发布、什么时候可以退休」。

为什么 Vibe Check 不够:SkillsBench 的两组数据

SkillsBench 索引了 GitHub 上约五万个 Skill,几乎没有完整 eval;许多 Skill 是 AI 生成的,「人工看一眼,再跑几次 vibe check 就发布了」。但同一 Agent 面对同一任务第一次成功、第二次失败并不罕见——没有固定测试集就没有稳定基线,也无法归因失败。SkillsBench 另一组结果更关键:Skill 在约一百个编码与生产力任务中平均带来约 15% 的提升,但人工编写的 Skill 表现最好,AI 自动生成的 Skill 有时反而降低表现——「Skill 有效,不等于任何 Skill 都有效」。

判断依据是行为依赖而非文档:Skill 一旦被加载就占用上下文并影响 Agent 决策,它不是静态说明文档,而是进入运行链路的行为依赖——既然能改变行为,就应像代码、提示模板和工具调用一样接受测试。

触发边界:描述是「触发分类器」的一部分

开发者在 Cursor / Claude Code 里知道有哪些 Skill,模型没触发就补一句提示或直接命令调用;但产品里的最终用户不知道内部 Skill 名称、不会替系统修正触发方式,只会说自己的任务。Skill 通过三层渐进披露暴露信息(① 名称+描述 → ② 正文 → ③ 按需读取的脚本/示例/参考资料),模型在读取完整内容前往往只看到名称与描述——因此描述不是简介,而是触发分类器的一部分。实践数据中约一半的失败来自 Skill 没有被正确触发:描述太弱、太宽,或只含 API 术语而没覆盖用户真实说法,会让 Skill 该出现时缺席、不该出现时抢走任务。一段可测试的描述至少要回答「为什么用、什么时候用、怎样使用」,并说明哪些相似任务不应该用;「构建多轮聊天应用时使用 Interactions API」是可执行指令,而「Interactions API 适合多轮聊天」只是背景信息,仍要求模型自己推断下一步。

两类 Skill,两种生命周期(能力型可退休)

从生命周期看 Skill 分两类,eval 目标不同:

  • 能力型:补模型当前不稳定或尚未掌握的能力(训练截止后发布的新 API、特定格式、操作内部工具)。模型升级后基础能力可能追上来,这类 Skill 应允许退休;eval 要证明「它确实增加了能力」并持续检测基础模型何时不再需要它。
  • 偏好型:承载组织自己的约定(指定组件库、命名方式、目录结构、内部发布流程)。这些偏好不会随基础模型升级自动出现,往往需要长期存在;eval 要验证输出是否稳定遵守组织约定。

因此 eval 不只是上线前的成绩单,也定义了 Skill 的维护周期。

四个收敛动作:先让 Skill 变得可评测

内容本身模糊,后面的 eval 只能测到「一团模糊行为」。动手收敛四步:①写指令,不写被动说明(指令明确告诉 Agent 在什么条件下采取什么动作;被动背景把判断压力留给模型);②正文精简,详细资料按需放进参考文件(描述频繁进入调用上下文,正文触发后也产生 token 成本;SKILL.md 超过约 500 行就该认真检查是否拆分);③固定流程写成脚本(装依赖、移文件、执行发布命令等确定性步骤不必每次重新推理——Skill 更适合表达目标、约束、相关文件与可用参考,让 Agent 在边界内判断);④删除不改变行为的 no-op(「编写高质量代码」「仔细检查结果」听起来正确却难形成可观察行为差异,既耗上下文又干扰「Skill 究竟增加了什么」的判断)。

最小测试集与隔离 Runner

不必先搭复杂评测平台,而是尽早建立小而真实的测试集:最小起步为五条 happy path + 五条 negative case,之后每出现一个真实失败(客户反馈 / 生产轨迹 / 团队实际使用)就沉淀为长期保留的回归用例——测试集因此不是「发布前写完就丢掉的文档」,而是随产品使用不断增长的行为规格。每条用例至少记录 用户提示 / 语言 / should_trigger / 可检查的 expected_checks。负例尤其重要:只测「该用时能不能用」会把 Skill 推向过度触发,加入「不该用时是否保持沉默」才能把边界真正固定下来。

最小 eval harness 只有两块:一份机器可读的测试集 + 一个运行 Agent 的脚本。Runner 读取提示、在干净工作区执行 Agent、取回最终结果与必要轨迹再运行检查;每次运行必须隔离,避免 Agent 从旧对话、残留文件或上一次输出中「偷到答案」;测试声明还可包含工作区文件、依赖与启动命令,让环境本身也可重复。检查方法优先便宜、确定的手段(regex / 普通程序断言,速度快成本低且适合持续回归);只有代码风格、设计质量或复杂任务完成度这类难以写死的问题才交给带明确 rubric 的 LLM-as-a-Judge——「关键不是用了一个更聪明的 Judge,而是把可确定的部分尽量确定化,LLM Judge 应该是较小的补充层,而不是所有测试的默认入口」。Interactions API 案例的检查项即为四类确定性断言:是否用了正确 SDK / 是否选择当前模型 / 是否调用正确方法 / 是否仍出现已淘汰的旧模式。该案例最终积累 117 条真实与合成用例,把有效代码表现提高到接近 90%——产生价值的不是某条神奇提示,而是测试集、Runner、断言和迭代形成的闭环。

评结果不锁路径:双指标与跨 Harness

Agent 可能第一轮没加载 Skill、第五轮才加载但最终完成任务——评测若要求固定轨迹,就会把合理行为误判为失败,故应优先判断最终结果而非锁死执行路径。但只看一次也不够:每个案例运行 3–5 次,并分别看两个问题——「多次运行中是否至少成功一次」(能力上限)与「是否能够连续稳定成功」(用户实际感受到的可靠性)。同一个 Skill 还要在真实用户会使用的不同模型与 Agent Harness 上分别测试:与某个模型/环境组合有效不代表换 Harness 仍成立,跨环境测试的目的不是追求一张统一分数,而是明确它在哪些组合中可靠、在哪些组合中不应该发布。

回归门禁与消融退休

一次评测只能证明一个时间点。要让 eval 真正约束工程行为,就要让它与 Skill 一起进入版本库、每次修改自动重跑;合理的合并门槛是:这次变更要么改善了结果,要么针对新发现的失败增加了新的 eval——真实失败一旦进入回归,就不能在下一次重构中悄悄回来。最后做消融:在同一组测试、同一模型、同一 Harness、相同运行条件下比较加载 Skill 与不加载 Skill 的结果——稳定提高表现即证明增量价值;基础模型已达到相同表现,就该考虑退休 Skill。退休不等于删除 eval:能力型 Skill 可以消失,eval 应继续保留——它既证明了为什么可以退休,也能在模型或 Harness 未来退化时发出信号,帮助团队判断是否需要重新引入。

该文给出的「周一就能开始」最小行动八步:写五条来自真实使用的测试提示 → 补上该触发与不该触发的边界 → 删除不改变行为的 no-op → 用 JSON/YAML 保存测试声明 → 写一个最小 Runner 并优先加入确定性断言 → 在隔离环境重复运行 → 比较 Skill ON 与 OFF 的结果 → 把第一次失败变成第一条回归用例。核心立场句:「没有 eval 的 Skill,不是可靠能力,只是未经验证的行为。」

深度分析

评估的本质是建立因果链:Skill 带来的改变是否可归因于 Skill 本身,而非随机波动或测试偏差。三类测试构成递进防线——触发测试验证「该不该用」,功能测试验证「用对了吗」,基线对比验证「用了有多大价值」。其中触发测试最易被忽视,却最能暴露 description 关键词的遗漏或歧义。 迭代的核心不在于修复单个失败用例,而在于从错误模式中提炼通用约束。一个断言失败背后往往是一个隐含假设——要么指令太模糊,要么边界条件未被显式声明。将每次修正视为 Skill 边界的一次微调,而非对一个偶然错误的补丁。 delta 指标(pass_rate / time_seconds / tokens)的标准差同样携带信息:高标准差意味着 Skill 在不同输入上的表现不稳定,反映的是指令中存在未被约束的模糊性,需要通过收紧条件或增加示例来消除。

实践启示

  1. 先触发,后功能:写 Skill 时优先打磨 description,确保激活条件准确,再投入精力在执行逻辑和 Gotchas 上。触发错了,功能再完美也白费。
  2. 让测试用例自己说话:好的测试用例集是一份「边界合同」——AI 看到这些输入和期望输出,应该能推断出 Skill 的适用范围和限制。
  3. 量化优先,感观次之:用 pass_rate 说话而非「感觉更好用了」。数据才能支撑迭代决策。
  4. 把重复测试脚本打包进 Skill:当多个测试用例都包含相同的辅助脚本时,说明这段逻辑应该下沉到 Skill 的 scripts/ 中,避免测试与 Skill 之间的逻辑重复。
  5. 让 Skill 自己记录成长:每次从对话中修正一个问题时,显式地将改进固化到 SKILL.md 中,而非仅留在记忆里。Skill 是持续演进的文档而非一次性的产物。

相关实体