跳到主要内容

优化 Skill 描述

只有被激活的 Skill 才能发挥作用。SKILL.md 头部信息(frontmatter)中的 description 字段是 Agent 用来决定是否为特定任务加载 Skill 的主要机制。描述不够明确意味着 Skill 在该触发时不会触发;描述过于宽泛则意味着它会在不该触发时触发。

本指南介绍了如何系统地测试和改进你的 Skill 描述,以提高触发的准确性。

Skill 触发机制是如何工作的

Agent 使用渐进式披露(progressive disclosure)来管理上下文。在启动时,它们只加载每个可用 Skill 的 namedescription —— 这足以决定某个 Skill 何时可能相关。当用户的任务与描述匹配时,Agent 会将完整的 SKILL.md 读取到上下文中并遵循其指令。

这意味着描述承担了触发的全部重任。如果描述没有传达出该 Skill 何时有用,Agent 就不会知道去调用它。

一个重要的细微差别是:Agent 通常只在任务需要超出其自身处理能力的知识或功能时,才会去查阅 Skills。像“阅读这个 PDF”这样简单的一步请求,即使描述完美匹配,也可能不会触发 PDF Skill,因为 Agent 可以用基础工具处理它。涉及专业知识的任务——不熟悉的 API、特定领域的工作流或不常见的格式——才是精心编写的描述能发挥关键作用的地方。

编写有效的描述

在测试之前,了解好的描述是什么样的会很有帮助。以下是一些原则:

  • 使用祈使句。 将描述构建为对 Agent 的指令:“当……时使用此 Skill(Use this skill when...)”而不是“这个 Skill 的功能是……(This skill does...)”。Agent 正在决定是否采取行动,所以要告诉它何时行动。
  • 关注用户意图,而非实现细节。 描述用户试图实现的目标,而不是 Skill 的内部机制。Agent 是根据用户的请求进行匹配的。
  • 宁可显得有些“强势”。 明确列出适用该 Skill 的上下文,包括用户没有直接说出该领域名称的情况:“即使他们没有明确提及‘CSV’或‘分析’。”
  • 保持简洁。 几句话到一个简短的段落通常是合适的——足够长以涵盖 Skill 的范围,又足够短以免在众多 Skills 中使 Agent 的上下文变得臃肿。规范强制规定了 1024 个字符的硬性限制。

设计触发评估查询

为了测试触发情况,你需要一组评估查询(eval queries)—— 带有是否应该触发你的 Skill 标签的真实用户提示词。

[
{ "query": "I've got a spreadsheet in ~/data/q4_results.xlsx with revenue in col C and expenses in col D — can you add a profit margin column and highlight anything under 10%?", "should_trigger": true },
{ "query": "whats the quickest way to convert this json file to yaml", "should_trigger": false }
]

目标是准备大约 20 个查询:8-10 个应该触发的,以及 8-10 个不应该触发的。

应该触发的查询(Should-trigger queries)

这些查询用于测试描述是否涵盖了 Skill 的范围。在以下几个维度上使它们多样化:

  • 措辞(Phrasing):有些正式,有些随意,有些带有拼写错误或缩写。
  • 明确性(Explicitness):有些直接说出 Skill 的领域(“分析这个 CSV”),有些则只描述需求而不直接点名(“我老板想要根据这个数据文件做个图表”)。
  • 细节(Detail):将简短的提示词与包含大量上下文的提示词混合使用——例如简短的“分析我的销售 CSV 并制作图表”,以及包含文件路径、列名和背景故事的较长消息。
  • 复杂性(Complexity):改变步骤和决策点的数量。将单步任务与多步工作流结合起来,以测试当 Skill 所处理的任务被埋藏在更大的任务链中时,Agent 是否能识别出该 Skill 是相关的。

最有用的“应该触发”查询是那些 Skill 能帮上忙,但仅从查询本身看联系并不明显的查询。在这些情况下,描述的措辞将起到决定性作用——如果查询已经准确地要求了 Skill 所做的事情,任何合理的描述都会触发。

不应触发的查询(Should-not-trigger queries)

最有价值的负面测试用例是差一点就命中的(near-misses)——这些查询与你的 Skill 共享关键字或概念,但实际上需要不同的东西。这些测试用于检验描述是否精确,而不仅仅是宽泛。

对于一个 CSV 分析 Skill,较弱的负面示例可能是:

  • "Write a fibonacci function" —— 明显不相关,测试不出任何东西。
  • "What's the weather today?" —— 没有关键字重叠,太简单了。

较强的负面示例:

  • "I need to update the formulas in my Excel budget spreadsheet" —— 共享了“电子表格(spreadsheet)”和“数据(data)”的概念,但需要的是 Excel 编辑,而不是 CSV 分析。
  • "can you write a python script that reads a csv and uploads each row to our postgres database" —— 涉及 CSV,但任务是数据库 ETL,而不是分析。

增加真实感的提示

真实用户的提示词包含通用测试查询所缺乏的上下文。请包含:

  • 文件路径(~/Downloads/report_final_v2.xlsx
  • 个人背景("my manager asked me to..."
  • 具体细节(列名、公司名称、数据值)
  • 随意的语言、缩写和偶尔的拼写错误

测试描述是否触发

基本方法:在安装了该 Skill 的情况下,让你的 Agent 运行每个查询,并观察 Agent 是否调用了它。确保该 Skill 已注册并能被你的 Agent 发现——具体如何操作因客户端而异(例如,通过 Skills 目录、配置文件或 CLI 标志)。

大多数 Agent 客户端提供某种形式的可观测性——执行日志、工具调用历史或详细输出——让你能够看到在运行期间查阅了哪些 Skills。请查看客户端的文档以获取详细信息。如果 Agent 加载了你的 Skill 的 SKILL.md,则说明该 Skill 触发了;如果 Agent 没有查阅它就继续执行,则说明没有触发。

如果满足以下条件,则查询“通过(passes)”:

  • should_triggertrue 且 Skill 被调用,或者
  • should_triggerfalse 且 Skill 未被调用。

多次运行

模型行为是非确定性的——同一个查询可能在一次运行中触发了 Skill,但在下一次却没有。多次运行每个查询(3 次是一个合理的起点)并计算触发率(trigger rate):即调用了 Skill 的运行次数所占的比例。

如果一个“应该触发”的查询的触发率高于某个阈值(0.5 是一个合理的默认值),则该查询通过。如果一个“不应触发”的查询的触发率低于该阈值,则该查询通过。

20 个查询,每个运行 3 次,那就是 60 次调用。你会希望用脚本来自动化这个过程。以下是总体结构——请将 check_triggered 中的 claude 调用和检测逻辑替换为你的 Agent 客户端提供的任何内容:

#!/bin/bash
QUERIES_FILE="${1:?Usage: $0 <queries.json>}"
SKILL_NAME="my-skill"
RUNS=3

# 此示例使用 Claude Code 的 JSON 输出来检查 Skill 工具调用。
# 请将此函数替换为你的 Agent 客户端的检测逻辑。
# 如果调用了该 Skill,应返回 0(成功),否则返回 1。
check_triggered() {
local query="$1"
claude -p "$query" --output-format json 2>/dev/null \
| jq -e --arg skill "$SKILL_NAME" \
'any(.messages[].content[]; .type == "tool_use" and .name == "Skill" and .input.skill == $skill)' \
> /dev/null 2>&1
}

count=$(jq length "$QUERIES_FILE")
for i in $(seq 0 $((count - 1))); do
query=$(jq -r ".[$i].query" "$QUERIES_FILE")
should_trigger=$(jq -r ".[$i].should_trigger" "$QUERIES_FILE")
triggers=0

for run in $(seq 1 $RUNS); do
check_triggered "$query" && triggers=$((triggers + 1))
done

jq -n \
--arg query "$query" \
--argjson should_trigger "$should_trigger" \
--argjson triggers "$triggers" \
--argjson runs "$RUNS" \
'{query: $query, should_trigger: $should_trigger, triggers: $triggers, runs: $runs, trigger_rate: ($triggers / $runs)}'
done | jq -s '.'

如果你的 Agent 客户端支持,一旦结果明朗,你可以提前停止运行——Agent 要么查阅了该 Skill,要么在没有它的情况下开始工作。这可以显著减少运行完整评估集的时间和成本。

使用训练/验证集划分来避免过拟合

如果你针对所有查询来优化描述,就会面临过拟合的风险——即精心制作的描述适用于这些特定的措辞,但在新的措辞上却失效了。

解决方案是拆分你的查询集:

  • 训练集(约 60%):用于识别失败用例并指导改进的查询。
  • 验证集(约 40%):预留出来的查询,仅用于检查改进是否具有泛化能力。

确保两个集合都包含按比例混合的“应该触发”和“不应触发”查询——不要意外地将所有正例都放在一个集合中。随机打乱并在各次迭代中保持划分固定,这样你才能进行公平的比较。

如果你使用的是像上面那样的脚本,你可以将查询拆分为两个文件——train_queries.jsonvalidation_queries.json——并分别对它们运行脚本。

优化循环

  1. 评估当前描述在训练集和验证集上的表现。训练结果指导你的修改;验证结果告诉你这些修改是否具有泛化能力。
  2. 识别失败用例(在训练集中):哪些“应该触发”的查询没有触发?哪些“不应触发”的查询触发了?
    • 仅使用训练集的失败用例来指导你的修改——无论你是自己修改描述还是提示 LLM 来修改,都不要将验证集的结果引入此过程。
  3. 修改描述。 专注于泛化能力:
    • 如果“应该触发”的查询失败了,描述可能太窄。扩大范围或添加有关该 Skill 何时有用的上下文。
    • 如果“不应触发”的查询被错误触发了,描述可能太宽泛。增加关于该 Skill 做什么的具体说明,或者澄清此 Skill 与相邻功能之间的边界。
    • 避免添加来自失败查询的特定关键字——那是过拟合。相反,找到这些查询所代表的通用类别或概念并加以解决。
    • 如果在几次迭代后卡住了,尝试在结构上采用不同的方法来编写描述,而不是进行增量微调。不同的框架或句子结构可能会在微调无法奏效的地方取得突破。
    • 检查描述是否保持在 1024 个字符的限制内——描述在优化过程中往往会变长。
  4. 重复步骤 1-3,直到所有训练集查询都通过,或者你不再看到有意义的改进。
  5. 选择最佳迭代版本,依据是其验证通过率——即验证集中通过的查询比例。请注意,最佳描述可能不是你生成的最后一个;较早的迭代版本可能比较晚的、对训练集过拟合的版本具有更高的验证通过率。

通常五次迭代就足够了。如果性能没有提高,问题可能出在查询上(太简单、太难或标签错误),而不是描述。

skill-creator Skill 端到端地自动化了这个循环:它拆分评估集,并行评估触发率,使用 Claude 提出描述改进建议,并生成一个实时的 HTML 报告供你在运行时查看。

应用结果

一旦你选择了最佳描述:

  1. 更新你的 SKILL.md 头部信息中的 description 字段。
  2. 验证描述是否在 1024 个字符的限制内。
  3. 验证描述是否按预期触发。手动尝试几个提示词作为快速的健全性检查(sanity check)。为了进行更严格的测试,编写 5-10 个全新的查询(混合“应该触发”和“不应触发”的查询)并通过评估脚本运行它们——由于这些查询从未参与过优化过程,它们能为你提供关于描述是否具有泛化能力的真实检验。

优化前后对比:

# 优化前
description: Process CSV files.

# 优化后
description: >
Analyze CSV and tabular data files — compute summary statistics,
add derived columns, generate charts, and clean messy data. Use this
skill when the user has a CSV, TSV, or Excel file and wants to
explore, transform, or visualize the data, even if they don't
explicitly mention "CSV" or "analysis."

改进后的描述在 Skill 的功能上更加具体(汇总统计、派生列、图表、清理),而在适用场景上更加宽泛(CSV、TSV、Excel;即使没有明确的关键字)。

下一步

一旦你的 Skill 能够可靠地触发,你就会想要评估它是否能产生良好的输出。请参阅评估 Skill 输出质量,了解如何设置测试用例、对结果进行评分并进行迭代。