Skill Creator 全阶段详解
本文摘要: Claude Skill开发流程分为两个核心目录结构:Skill目录存放定义和源码,Workspace目录存放评估结果。完整工作流包含8个阶段:意图捕获、访谈调研、编写SKILL.md、设计测试用例、并行测试、评分聚合、迭代改进、触发优化和打包分发。每个阶段都有明确的目标、输入输出和文件关联,其中特别强调需求澄清的重要性,以及渐进式加载、主动触发描述等设计细节。流程注重从对话历史反向提
从意图到交付的完整流水线——每个阶段的目标、输入输出、涉及文件和值得学习的设计细节。
两个核心目录
整个流程涉及两个并列的目录,理解它们的分工是理解后续所有阶段的前提:
.claude/skills/ ← 两者的共同父目录
├── my-skill/ ← 📁 Skill 目录:存放 Skill 定义和源码
│ ├── SKILL.md # Skill 本体
│ ├── evals/evals.json # 测试用例主文件
│ ├── scripts/ # 辅助脚本
│ ├── references/ # 参考文档
│ └── assets/ # 模板/资源
my-skill-workspace/ ← 📁 Workspace 目录:Skill 目录的兄弟(sibling)
├── iteration-1/ # 第 1 轮迭代
│ ├── eval-xxx/ # 每个测试用例的目录
│ │ ├── eval_metadata.json # 单条 eval 的 prompt + assertions
│ │ ├── with_skill/ # 带 Skill 的运行结果
│ │ └── without_skill/ # 基线对照的运行结果
│ ├── benchmark.json # 聚合统计
│ └── feedback.json # 用户反馈
├── iteration-2/ # 第 2 轮迭代
└── ...
SKILL.md 原文:“Put results in
<skill-name>-workspace/as a sibling to the skill directory.” 即 Workspace 与 Skill 目录同级并列。
简记:Skill 目录存"怎么做"是最终想得到的skill产物,Workspace 目录存"做得怎么样"是用来存放评估的。后续各阶段的输入输出都会标注属于哪个目录。
全局视角:八个阶段
Skill Creator 的完整工作流可以拆解为八个阶段。它们构成一个主循环 + 两个后处理的结构:
┌─────────────────────────────────────────────────────────────────┐
│ 主循环(可多轮迭代) │
│ │
│ ① 意图捕获 → ② 访谈调研 → ③ 编写 SKILL.md → ④ 设计测试用例 │
│ → ⑤ 并行运行测试 → ⑥ 评分/聚合/可视化 → ⑦ 迭代改进 │
│ ↑ │ │
│ └────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────┘
↓
⑧ Description 触发优化
↓
⑨ 打包分发
各阶段的关系说明:
- 阶段 ①②③ 只在第一轮完整执行,后续迭代从 ⑤ 开始
- 阶段 ④ 在第一轮后可能扩展测试集
- 阶段 ⑤⑥⑦ 是核心迭代循环,每一轮都走完
- 阶段 ⑧ 在主循环结束后单独运行
- 阶段 ⑨ 在一切都稳定后执行
- 用户可以在任何阶段介入,Skill Creator 会判断用户处于哪个阶段并接续工作
阶段 ①:意图捕获(Capture Intent)
目标
把模糊的需求转化为明确的问题定义:这个 Skill 解决什么问题、在什么场景触发、输出什么、怎么判断它成功。
输入
- 用户的自然语言描述(可能很简单,如"帮我做一个 XX 的 skill")
- 当前对话历史(如果用户说"把刚才的工作流变成 skill",则历史中包含工具调用、步骤顺序、用户纠正等)
输出
四个问题的答案(需用户确认):
- 这个 Skill 让 Claude 能做什么?
- 什么场景应该触发?
- 输出格式是什么?
- 是否需要设置测试用例?
涉及文件
| 文件 | 作用 |
|---|---|
SKILL.md 的 “Capture Intent” 段落 |
定义了四个核心问题和从对话历史提取上下文的指导 |
值得学习的细节
1. 从对话历史中反向提取需求
SKILL.md 原文明确指出:如果对话中已经包含了用户想沉淀的工作流,应该先从历史中提取答案(用了哪些工具、步骤顺序、用户的纠正、输入输出格式),再让用户补缺和确认。这避免了重复询问已知信息。
2. 根据 Skill 类型建议是否测试
不是所有 Skill 都适合自动化测试。SKILL.md 区分了两类:
- 客观可验证的(文件转换、数据提取、代码生成)→ 适合测试
- 主观输出的(写作风格、艺术创作)→ 不需要强行加断言
这一判断在第一步就做出,避免后续流程无意义地"走形式"。
3. 这一步的关键词不是"写",而是"问清楚"
整个阶段没有产出任何代码或文档,纯粹是在做需求澄清。这体现了一个工程思想:问题定义比解决方案更重要。
阶段 ②:访谈与调研(Interview and Research)
目标
补齐阶段 ① 遗留的所有细节:边界情况、输入输出格式、示例文件、成功标准、依赖项。直到这些全部确认清楚才能动手写代码。
输入
- 阶段 ① 的四个问题答案
- 用户提供的补充材料(示例文件、文档链接等)
输出
- 完整的需求规格(隐式存在于对话中,不单独落文件)
- 对可用工具和 MCP 的调研结果(如果相关)
涉及文件
| 文件 | 作用 |
|---|---|
SKILL.md 的 “Interview and Research” 段落 |
指导主动提问和利用 MCP 做调研 |
值得学习的细节
1. "等确认了再写测试"的纪律
SKILL.md 原文:“Wait to write test prompts until you’ve got this part ironed out.” 这防止了在需求不清晰时就进入实施,然后不得不反复返工。
2. 利用 MCP 做并行调研
如果有 MCP(Model Context Protocol)可用,建议通过 subagent 并行搜索文档、查找类似 Skill、了解最佳实践。这减轻了用户的问答负担——不是什么都等用户告诉你,而是自己先尽量做功课。
阶段 ③:编写 SKILL.md
目标
将需求规格转化为结构化的 SKILL.md 文件和必要的附属资源目录。
输入
- 阶段 ①② 确认的需求细节
输出
📁 以下产出均在 Skill 目录(如
my-skill/)下
my-skill/SKILL.md文件(含 frontmatter 和正文)- 必要时创建
my-skill/scripts/、my-skill/references/、my-skill/assets/目录
涉及文件
| 文件 | 作用 |
|---|---|
SKILL.md 的 “Write the SKILL.md” + “Skill Writing Guide” 段落 |
定义 frontmatter 规范、目录结构、渐进式加载机制、写作模式 |
scripts/quick_validate.py |
校验 SKILL.md 格式是否合规(kebab-case 命名、字符限制等) |
scripts/utils.py |
提供 parse_skill_md() 函数,解析 frontmatter 的 name 和 description |
值得学习的细节
1. 三层渐进式加载(Progressive Disclosure)
第一层:name + description → 始终在上下文中 → ~100 词
第二层:SKILL.md 正文 → 触发时才加载 → <500 行
第三层:references/scripts → 按需读取 → 不限大小
这解决了一个核心矛盾:上下文空间有限,但复杂 Skill 需要大量指令。三层机制让触发决策保持轻量,执行时按需展开细节。
2. Description 要"积极主动"
SKILL.md 明确指出 Claude 有"欠触发"倾向。因此 description 不能只描述 Skill 做什么,还要主动列举使用场景,风格稍微"pushy"一点。原文给的对比:
❌ "How to build a simple fast dashboard to display internal Anthropic data."
✅ "How to build a simple fast dashboard to display internal Anthropic data.
Make sure to use this skill whenever the user mentions dashboards, data
visualization, internal metrics, or wants to display any kind of company
data, even if they don't explicitly ask for a 'dashboard.'"
3. 指令用解释代替命令
原文:“Try to explain to the model why things are important in lieu of heavy-handed musty MUSTs.” 这不是审美偏好,而是工程策略——LLM 有 Theory of Mind,理解"为什么"后能在未覆盖的边界情况中做更好的推断。
4. 多域 Skill 按变体组织
cloud-deploy/
├── SKILL.md (workflow + selection)
└── references/
├── aws.md
├── gcp.md
└── azure.md
Claude 只读相关的 reference 文件,避免把所有变体塞进一个巨大的 SKILL.md。
5. quick_validate.py 的校验规则
该脚本检查:
- frontmatter 必须以
---开头和结尾 name必须是 kebab-case(小写字母+数字+连字符),最长 64 字符description不能包含尖括号< >,最长 1024 字符- 只允许
name、description、license、allowed-tools、metadata、compatibility这几个 frontmatter 属性
阶段 ④:设计测试用例
目标
构造 2-3 个真实、具体的测试 prompt,作为后续运行和评测的基础。
输入
- 阶段 ③ 完成的 SKILL.md
输出
📁 以下产出在 Skill 目录(如
my-skill/)下
my-skill/evals/evals.json文件(此时只含 prompt,不含 assertions)
注意:
eval_metadata.json不在此阶段生成,而是在阶段 ⑤ 运行测试时为每个 eval 运行目录创建。evals.json是 Skill 目录下所有测试用例的主定义文件,eval_metadata.json是运行时投影到 Workspace 各 eval 目录的单条副本。
涉及文件
| 文件 | 作用 |
|---|---|
SKILL.md 的 “Test Cases” 段落 |
定义测试用例格式和设计要求 |
references/schemas.md |
定义 evals.json 的完整 JSON Schema |
值得学习的细节
1. 先写 prompt,后写 assertions
SKILL.md 明确要求:“Don’t write assertions yet — just the prompts. You’ll draft assertions in the next step while the runs are in progress.” 这是一个精妙的时间安排——assertions 在跑测试的"等待期"写,充分利用并行时间。
2. 测试用例必须像真人说的话
这一点文档反复强调,在 Description 优化阶段更为突出。好的测试 prompt 应该包含:
- 文件路径、列名、公司名等具体细节
- 背景故事和个人上下文
- 口语化、缩写、不完美的拼写
- 不同长度的混合
3. 用描述性名称命名 eval
不叫 “eval-0”,而叫有意义的名字(如 “ocean-pdf-form-fill”),这样在 benchmark 报告里一眼能看懂每个测试在验证什么。
4. 与用户确认测试用例
SKILL.md 建议展示测试用例给用户看,问"这些看起来对吗?你想加更多吗?"——测试用例的质量直接决定后续所有迭代的有效性。
阶段 ⑤:并行运行测试
目标
对每个测试 prompt 同时跑两条线——一条带 Skill,一条不带(或带旧版)——建立对照实验。
输入
📁 来自 Skill 目录
my-skill/SKILL.md(阶段 ③ 产出)my-skill/evals/evals.json(阶段 ④ 产出)- 如果是改进已有 Skill:旧版 Skill 的快照(
cp -r到 Workspace 下的skill-snapshot/)
输出
📁 以下产出均在 Workspace 目录(
my-skill-workspace/)下——它是 Skill 目录的兄弟目录
my-skill/ ← Skill 目录(存放 SKILL.md、evals/ 等)
my-skill-workspace/ ← Workspace 目录(存放运行结果)
└── iteration-1/
├── eval-descriptive-name/
│ ├── eval_metadata.json # 从 evals.json 投影的单条 prompt + assertions
│ ├── with_skill/
│ │ ├── outputs/ # subagent 产出的业务文件(给用户看的)
│ │ │ └── metrics.json # 工具调用统计(subagent 执行框架自动生成)
│ │ ├── transcript.md # subagent 执行记录(框架自动生成,给 Grader 看的)
│ │ ├── user_notes.md # subagent 自己标记的不确定点(可选)
│ │ └── timing.json # token 和耗时
│ └── without_skill/
│ ├── outputs/
│ │ └── metrics.json
│ ├── transcript.md
│ ├── user_notes.md
│ └── timing.json
└── eval-another-name/
└── ...
run 目录下各文件说明
文件 谁生成的 包含什么 谁消费 outputs/subagent 执行任务时产出 Skill 的业务输出文件(如 .pdf、.csv、.docx 等用户关心的产物) 用户(通过 Viewer)、Grader outputs/metrics.jsonsubagent 执行框架自动生成 工具调用计数(Read/Write/Bash/Edit 等各多少次)、总步骤数、产出文件列表、错误次数、输出字符数。Schema 定义在 references/schemas.mdGrader(写入 grading.json 的 execution_metrics字段)transcript.mdsubagent 执行框架自动生成 subagent 完整的执行过程——每一步的推理、工具调用、中间输出、遇到的错误和恢复。是一个 markdown 格式的"执行日志" Grader 的主要输入(Step 1 完整阅读),也是阶段 ⑦ 改进 Skill 时的重要参考 user_notes.mdsubagent 在执行过程中主动写入(可选) subagent 自己标记的不确定点、需要人工审查的问题、使用的临时方案。如"Used 2023 data, may be stale"、“Fell back to text overlay for non-fillable fields” Grader(Step 5 专门读取,即使断言全部 PASS 也可能暴露问题) timing.jsonSkill Creator 从 subagent 完成通知中捕获 total_tokens、duration_ms、total_duration_seconds。Schema 定义在references/schemas.mdaggregate_benchmark.py(聚合为 benchmark 的时间/token 统计)
涉及文件
| 文件 | 作用 |
|---|---|
SKILL.md 的 “Running and evaluating test cases” 的 Step 1-3 |
定义并行运行策略、目录布局、timing 数据捕获,以及 eval_metadata.json 的格式(内联示例,仅此处定义) |
SKILL.md 的 “Step 2: While runs are in progress, draft assertions” |
定义 assertions 的起草时机和写入规则 |
references/schemas.md |
定义 evals.json 的完整 JSON Schema(注意:eval_metadata.json 的 schema 不在此文件中,仅在 SKILL.md 内联定义) |
references/schemas.md |
定义 timing.json 的 Schema |
值得学习的细节
1. 同一轮同时发出 with-skill 和 baseline
SKILL.md 原文用加粗强调:“This is important: don’t spawn the with-skill runs first and then come back for baselines later. Launch everything at once.” 原因是并行执行节省时间,且避免环境漂移导致不公平对比。
2. Baseline 的选择策略
| 场景 | Baseline |
|---|---|
| 创建新 Skill | without_skill——同样的 prompt,不给 Skill |
| 改进已有 Skill | 旧版 Skill(先 cp -r 做快照,指向快照目录) |
这让每次比较都有明确参照物,而不是靠"感觉变好了"。
3. timing.json 数据必须立即捕获
原文强调:“This is the only opportunity to capture this data — it comes through the task notification and isn’t persisted elsewhere.” subagent 完成时的通知中包含 total_tokens 和 duration_ms,如果不当场保存就永久丢失了。
4. 等待期间不是闲着——处理 assertions
测试在跑的时候不用干等,正好用这段时间处理断言。但第一次迭代和后续迭代的操作不同:
| 情况 | 对 evals/evals.json 的操作 |
对 eval_metadata.json 的操作 |
|---|---|---|
| 第一次迭代(assertions 还不存在) | 新起草 assertions,写入 evals.json,与用户确认 |
在 iteration-1/eval-X/ 下新建,写入 prompt + assertions |
| 后续迭代(assertions 已存在) | 审阅现有的 assertions,必要时根据 Grader 反馈微调 | 在 iteration-N/eval-X/ 下重新创建(不从上一轮复制) |
关键点:eval_metadata.json 每轮都重新创建,不会从上一轮目录复制过来——因为 prompt 或 assertions 都可能已经改了。SKILL.md 原文:“If this iteration uses new or modified eval prompts, create these files for each new eval directory — don’t assume they carry over from previous iterations.”
阶段 ⑥:评分 / 聚合 / 可视化
目标
对所有运行结果做定量评分、统计聚合和模式分析,同时生成可视化页面供用户定性审查。
输入
📁 均来自 Workspace 目录(
my-skill-workspace/iteration-N/)
- 各 eval 下的
with_skill/outputs/、without_skill/outputs/(业务输出文件) - 各 eval 下的
transcript.md(subagent 执行记录,由执行框架自动生成,Grader 的主要读取对象) - 各 eval 下的
timing.json - 各 eval 下的
eval_metadata.json中的assertions列表 - 各 eval 下的
user_notes.md(可选,subagent 标记的不确定点) - 各 eval 下的
outputs/metrics.json(可选,工具调用统计)
输出
📁 均写入 Workspace 目录(
my-skill-workspace/iteration-N/)
| 产出 | 位置 | 说明 |
|---|---|---|
grading.json |
每个 run 目录下(如 eval-X/with_skill/grading.json) |
每条断言的 PASS/FAIL + 证据 |
benchmark.json |
iteration-N/benchmark.json |
整个 iteration 的聚合统计 |
benchmark.md |
iteration-N/benchmark.md |
人类可读的统计摘要 |
| HTML Viewer | 本地 HTTP 服务器 或 --static 输出文件 |
浏览器中的交互式评审页面 |
feedback.json |
iteration-N/feedback.json(用户提交后生成) |
用户对各 run 的评语 |
涉及文件
| 文件 | 作用 |
|---|---|
agents/grader.md |
Grader Agent 的完整指令——如何评分、如何引用证据、如何批判 eval 本身 |
agents/analyzer.md 的 “Analyzing Benchmark Results” 段落 |
Benchmark Analyzer 模式——只看数据,找异常模式(如无区分度断言、高方差 eval),不提改进建议。注意:同一个文件在阶段 ⑦ 以另一种模式使用,见下文 |
scripts/aggregate_benchmark.py |
读取所有 grading.json,计算 mean/stddev/min/max,生成 benchmark.json |
eval-viewer/generate_review.py |
生成 HTML 评审页面(含 Outputs 和 Benchmark 两个标签页) |
eval-viewer/viewer.html |
HTML 模板 |
references/schemas.md |
定义 grading.json、benchmark.json 等的完整 Schema |
值得学习的细节
1. Grader Agent 的"双重使命"
Grader 不只是打分——它还要批判 eval 本身。原文举例:
“A passing grade on a weak assertion is worse than useless — it creates false confidence.”
具体来说,Grader 会指出:
- 断言太容易通过(如只检查文件名存在,不检查内容)
- 重要结果没有断言覆盖
- 断言无法从可用输出中验证
2. PASS 的判定标准极为严格
不是"看起来通过了"就算 PASS:
- 必须有明确证据
- 证据必须反映真正的任务完成(文件存在 + 内容正确,不是只有文件名对)
- 表面合规不算通过——碰巧满足断言但实际未完成任务 = FAIL
3. 隐含声明的提取和验证
Grader 会在预定义断言之外,额外提取输出中的隐含声明:
- 事实声明:如"表单有 12 个字段"→ 可以验证
- 过程声明:如"使用了 pypdf 填充表单"→ 可以从 transcript 验证
- 质量声明:如"所有字段都已正确填充"→ 需要评估是否有证据支撑
这能捕获预定义断言遗漏的问题。
4. Analyzer Agent 寻找的模式
Analyzer 专门寻找聚合指标掩盖的信号:
| 模式 | 含义 |
|---|---|
| 某断言在两组都 100% 通过 | 没有区分度,不能说明 Skill 的价值 |
| 某断言在两组都 0% 通过 | 可能超出当前能力,或断言本身有问题 |
| 某 eval 方差极高 | 可能是 flaky 测试或非确定性行为 |
| with_skill 某断言反而比 without 差 | Skill 可能在特定方面产生负面影响 |
5. grading.json 的字段名必须精确匹配
SKILL.md 特别强调:“The grading.json expectations array must use the fields text, passed, and evidence (not name/met/details or other variants) — the viewer depends on these exact field names.” 这是因为 generate_review.py 会直接解析这些字段名来渲染 HTML。
6. aggregate_benchmark.py 支持两种目录布局
布局 A(workspace 布局): 布局 B(legacy 布局):
iteration-N/ benchmark_dir/
└── eval-N/ └── runs/
├── with_skill/ └── eval-N/
└── without_skill/ ├── with_skill/
└── without_skill/
脚本会自动检测是哪种布局,增加了兼容性。
7. HTML Viewer 的功能细节
Viewer 有两个标签页:
Outputs 标签(定性审查):
- 逐个展示测试用例的 prompt 和输出
- 支持内联渲染文本文件、图片、代码
- 对不可渲染的文件(如 .docx)提供下载
- 迭代 2+ 时折叠显示上一版输出(对比改进效果)
- 折叠显示断言评分结果
- 每个用例有 Feedback 文本框,自动保存
Benchmark 标签(定量统计):
- pass_rate / time / tokens 的 mean ± stddev
- with_skill vs without_skill 的 delta
- 按 eval 分项展示
- Analyst 的观察笔记
用户审查完点击 “Submit All Reviews” → 生成 feedback.json。
阶段 ⑦:迭代改进
目标
根据用户反馈和量化数据改进 Skill,然后重新进入阶段 ⑤ 开始下一轮迭代。
输入
📁 来自 Workspace 目录(
my-skill-workspace/iteration-N/)
iteration-N/feedback.json(用户对每个 run 的评语)iteration-N/benchmark.json(量化数据)- Analyst notes(
benchmark.json的notes字段) - 各 run 的 transcript(subagent 的执行过程记录)
输出
📁 分别写入 Skill 目录 和 Workspace 目录
my-skill/SKILL.md(改进后覆盖原文件,可能同时改scripts/、references/)← Skill 目录my-skill-workspace/iteration-<N+1>/(新一轮运行的空目录)← Workspace 目录
涉及文件
| 文件 | 作用 |
|---|---|
SKILL.md 的 “Improving the skill” + “The iteration loop” 段落 |
定义四条改进原则和循环逻辑 |
agents/comparator.md |
Comparator Agent(可选)——盲评对比两个版本的输出 |
agents/analyzer.md 的 “Post-hoc Analyzer Agent” 段落 |
Post-hoc Analyzer 模式(可选)——与阶段 ⑥ 用的是同一个文件,但使用不同段落、扮演不同角色,见下面说明 |
agents/analyzer.md的两种模式对比
阶段 ⑥ 的 Benchmark Analyzer 阶段 ⑦ 的 Post-hoc Analyzer 使用段落 文件中的 “Analyzing Benchmark Results” 文件开头的 “Post-hoc Analyzer Agent” 触发时机 每轮必做,聚合完 benchmark 后 可选,仅在 Blind Comparison 之后 输入 benchmark.json(聚合统计)盲评结果 + 两个 Skill 源码 + 两份 transcript 做什么 分析数据模式——断言区分度、方差、token/时间异常 分析为什么赢——对比指令差异、指令遵循度、执行路径 是否建议改 Skill ❌ 只报告观察 ✅ 按 high/medium/low 给出改进建议 输出 字符串数组,写入 benchmark.json的notes结构化 JSON,含 improvement_suggestions
值得学习的细节
1. 四条改进原则
这是整个 Skill Creator 中工程思想最密集的部分:
原则一:从反馈中泛化,不要过拟合
原文:“we’re trying to create skills that can be used a million times across many different prompts”。当前只在几个例子上迭代是为了快速获得反馈,但改进必须是通用的。遇到顽固问题时,应该换隐喻、换工作模式,而不是加更多 MUST。
原则二:保持精简
读 transcript 而不只是最终输出。如果 Skill 让模型花大量时间做无用的事(比如过度详细的日志、不必要的中间步骤),就删掉对应的指令。
原则三:解释"为什么"
原文:“If you find yourself writing ALWAYS or NEVER in all caps, or using super rigid structures, that’s a yellow flag.” 这不是说永远不能用强制性语言,而是说应该优先尝试解释原理,让模型理解后自主判断。
原则四:发现重复劳动 → 抽取为脚本
如果 3 个测试用例都独立写了类似的 helper script,说明这是稳定的模式,应该放进 scripts/。这是把"发现—归纳—固化"的工程方法论直接嵌入到了迭代流程中。
2. 高级功能:盲评对比(Blind Comparison)
对于更严格的比较,可以启动 Comparator Agent:
两个输出 → 标记为 A 和 B → Comparator 不知道谁来自谁 → 按 Rubric 评分 → 判定赢家
↓
Analyzer "揭盲"分析原因
Comparator 的 Rubric 包含两个维度:
- 内容:正确性、完整性、准确性(各 1-5 分)
- 结构:组织性、格式、可用性(各 1-5 分)
核心规则:绝对不能试图推断哪个来自哪个 Skill,纯粹基于输出质量判断。
Analyzer "揭盲"后会对比两个 Skill 的指令、脚本、示例差异,评估指令遵循度(1-10 分),并生成优先级排序的改进建议(高/中/低)。
3. 迭代循环的终止条件
- 用户说满意了
feedback.json中所有评语为空(说明一切看起来都好)- 改进不再产生有意义的提升
4. Baseline 策略在迭代中的变化
- 创建新 Skill:baseline 始终是
without_skill(跨迭代不变) - 改进已有 Skill:baseline 可以是最初用户提供的版本,也可以是上一轮迭代——需要根据情况判断
阶段 ⑧:Description 触发优化
目标
在 Skill 逻辑稳定后,单独优化 SKILL.md frontmatter 中的 description 字段,提高触发准确率(该触发时触发,不该触发时不触发)。
输入
- 完成迭代的 SKILL.md
- 用户审阅过的 20 条触发评测查询(JSON 格式)
输出
- 优化后的
best_description - HTML 报告(显示每轮迭代的结果)
- 更新后的 SKILL.md frontmatter
涉及文件
这个阶段涉及的文件最多,是 Skill Creator 最独立、最精巧的子系统:
| 文件 | 作用 |
|---|---|
SKILL.md 的 “Description Optimization” 整个段落 |
定义四步优化流程和触发机制原理 |
assets/eval_review.html |
交互式审阅模板——用户在浏览器中编辑/审阅触发查询 |
scripts/run_eval.py |
单次触发评测——通过 claude -p + stream-json 检测 Skill 是否被触发 |
scripts/run_loop.py |
完整的优化循环——eval + improve 交替迭代,自动 train/test 划分 |
scripts/improve_description.py |
用 Claude + Extended Thinking 生成改进后的 description |
scripts/generate_report.py |
生成可视化 HTML 报告 |
scripts/utils.py |
parse_skill_md() 解析 frontmatter |
四步流程详解
Step 1:生成触发评测查询
创建 20 条查询(8-10 条 should-trigger + 8-10 条 should-not-trigger)。
should-trigger 的设计要点:
- 不同措辞方式(正式/随意/口语化/含错别字)
- 不同长度
- 用户不显式说出 Skill 名称但明显需要它的场景
- 与其他 Skill 竞争时应该赢的场景
should-not-trigger 的设计要点:
- 关键词重叠但实际需要不同东西的"近似查询"
- 相邻领域的任务
- 朴素关键词匹配会误触发但不应该触发的查询
- 避免过于简单的反例("写斐波那契函数"对 PDF Skill 来说太容易了,测不出什么)
Step 2:用户审阅
将查询集渲染到 assets/eval_review.html 模板中:
- 替换
__EVAL_DATA_PLACEHOLDER__→ JSON 数组 - 替换
__SKILL_NAME_PLACEHOLDER__→ Skill 名称 - 替换
__SKILL_DESCRIPTION_PLACEHOLDER__→ 当前 description
用户在浏览器中编辑查询、切换 should-trigger、添加/删除条目,最后导出 eval_set.json。
Step 3:运行优化循环
python -m scripts.run_loop \
--eval-set <path> --skill-path <path> --model <model-id> \
--max-iterations 5 --verbose
Step 4:应用最优 description
值得学习的细节
1. run_eval.py 的触发检测机制
为了判断一个查询是否"触发"了某个 Skill,run_eval.py 采用了一个巧妙的方法:
- 在
.claude/commands/目录临时创建一个以 Skill description 为内容的命令文件 - 调用
claude -p <query> --output-format stream-json --include-partial-messages - 实时解析流式 JSON 事件,检测 Claude 是否调用了该命令
- 使用
ProcessPoolExecutor并行运行多个查询 - 测试完成后删除临时命令文件
关键技术点:它拦截的是 content_block_start 事件(partial message),而不是等待完整的 assistant message——后者要等到工具执行完成才返回,太慢了。
2. run_loop.py 的防过拟合设计
这是整个系统中最具 ML 工程思想的部分:
- 分层划分:按
should_trigger标签分别对 trigger/no-trigger 查询做 shuffle,再各取一定比例,保证 train 和 test 中正负例都有覆盖 - 默认 60/40 train/test 划分
- 每个查询跑 3 次以获得可靠触发率(而不是跑一次就下结论)
- 使用
trigger_threshold判定一个查询是否算"被触发" - 历史信息剥离 test 分数:传给
improve_description的历史中删除了test_*字段,防止改进模型利用 test 信息 - 按 test score(而非 train score)选最优——经典防过拟合
3. improve_description.py 的 prompt 设计
该脚本调用 Claude + Extended Thinking(budget_tokens=10000)来生成新 description。其 prompt 包含:
- 当前 description
- 触发失败的查询列表
- 误触发的查询列表
- 所有历史尝试及其得分
- Skill 正文(作为上下文)
它还明确要求模型不要过拟合到具体查询:
“What I DON’T want you to do is produce an ever-expanding list of specific queries that this skill should or shouldn’t trigger for. Instead, try to generalize from the failures to broader categories of user intent.”
如果生成的 description 超过 1024 字符,会自动发起第二轮对话要求缩短。
4. 实时 HTML 报告
run_loop.py 支持 --live-report-path 参数,在每轮迭代后写入带 <meta http-equiv="refresh" content="5"> 的 HTML 报告,用户在浏览器中可以实时看到优化进展,每 5 秒自动刷新。
5. 触发机制的核心洞察
SKILL.md 解释了一个关键事实:Claude 只在它自己搞不定的任务中才会查阅 Skill。简单的一步操作(如"读这个文件")即使 description 完美匹配也可能不触发。因此评测查询必须足够复杂——是那种 Claude 确实需要额外指导才能做好的任务。
阶段 ⑨:打包分发
目标
将完成的 Skill 打包为可分发的 .skill 文件。
输入
📁 Skill 目录(如
my-skill/)
- 完成所有迭代和 description 优化的
my-skill/整个目录
输出
my-skill.skill文件(实质是 zip 格式,默认输出到当前工作目录)
涉及文件
| 文件 | 作用 |
|---|---|
scripts/package_skill.py |
打包脚本 |
scripts/quick_validate.py |
打包前的格式校验 |
值得学习的细节
1. 打包前自动校验
package_skill.py 在打包前会调用 quick_validate.py 做完整的格式校验。校验不通过则拒绝打包。
2. 智能排除规则
打包时自动排除:
__pycache__、node_modules、.DS_Store*.pyc文件- 根目录下的
evals/目录(测试数据不分发)
3. 最终产物是标准 zip
.skill 文件实质是 zipfile.ZIP_DEFLATED 压缩的 zip 包,内部保留了完整的目录结构。
跨环境适配
Skill Creator 为三种环境做了差异化适配:
| 能力 | Claude Code | Claude.ai | Cowork |
|---|---|---|---|
| 阶段 ⑤ 并行 subagent | ✅ | ❌ 串行执行,跳过 baseline | ✅ |
| 阶段 ⑥ HTML Viewer | 本地 HTTP 服务器 | ❌ 在对话中直接展示 | --static 输出 HTML 文件 |
| 阶段 ⑥ 定量 Benchmark | ✅ | ❌ 跳过 | ✅ |
| 阶段 ⑦ 盲评对比 | ✅ | ❌ 需要 subagent | ✅ |
| 阶段 ⑧ Description 优化 | ✅ | ❌ 需要 claude CLI |
✅ |
| 阶段 ⑨ 打包 | ✅ | ✅ | ✅ |
核心原则是功能降级而非功能缺失——在 Claude.ai 上跳过了 baseline 和定量评测,但仍然保持了"起草→运行→用户反馈→改进"的基本循环。
Subagent 使用全景
Skill Creator 大量依赖 Claude Code 的 subagent 能力(在主 agent 内启动独立的子 agent 执行任务)。以下是各阶段的 subagent 使用情况:
哪些阶段用了 subagent
| 阶段 | subagent 类型 | 是否必须 | 做什么 | SKILL.md 原文 |
|---|---|---|---|---|
| ② | 调研 subagent | 可选 | 并行搜索文档、查找类似 Skill | “research in parallel via subagents if available, otherwise inline” |
| ⑤ | Executor subagent ×2 | 必须 | 一个带 Skill 执行任务,一个不带(baseline) | “spawn two subagents in the same turn” |
| ⑥ | Grader subagent | 可选(也可 inline) | 读 grader.md 指令,对每个 run 评分 |
“spawn a grader subagent (or grade inline)” |
| ⑦ | Comparator subagent | 可选 | 盲评对比两个版本的输出 | “This is optional, requires subagents” |
| ⑦ | Analyzer subagent | 可选 | "揭盲"后分析赢家为什么赢 | 同上 |
没有用 subagent 的阶段
| 阶段 | 怎么实现的 |
|---|---|
| ① 意图捕获 | 主 agent 与用户对话 |
| ③ 编写 SKILL.md | 主 agent 直接写文件 |
| ④ 设计测试用例 | 主 agent 直接写 evals.json |
| ⑧ Description 触发优化 | Python 脚本(run_loop.py 通过 subprocess.Popen("claude", "-p", ...) 调用 CLI,不是 subagent) |
| ⑨ 打包 | Python 脚本(package_skill.py) |
subagent vs
claude -p子进程的区别:subagent 是 Claude Code 平台内的任务分发机制,共享工作区;claude -p是直接调用 CLI 启动一个独立的 Claude 进程。阶段 ⑧ 用后者是因为它只需要判断"description 是否触发了 Skill"这个简单问题,不需要 subagent 的完整能力。
Executor subagent 的隐含契约
阶段 ⑤ 的 Executor subagent 是最核心的 subagent 使用点。SKILL.md 定义了它的 prompt 模板(Skill path、Task、输出目录),但没有定义 executor 应该产出哪些元数据文件。以下文件被后续阶段消费,但其生成规范不在 Skill Creator 文档中:
| 文件 | 后续谁消费 | Skill Creator 中的定义状态 |
|---|---|---|
outputs/ |
Viewer、Grader | ✅ SKILL.md 明确指定输出目录 |
timing.json |
aggregate_benchmark.py |
✅ SKILL.md 明确说"Save this data immediately" |
transcript.md |
Grader(Step 1)、Analyzer、阶段 ⑦ 改进参考 | ❌ 未定义生成方式,仅定义读取路径(grader.md 的 transcript_path 参数) |
metrics.json |
Grader(Step 8) | ❌ 描述为 “from executor’s metrics.json”,但未说 executor 如何生成 |
user_notes.md |
Grader(Step 5) | ❌ 描述为 “if exists”,当可选文件处理 |
这意味着 transcript.md、metrics.json、user_notes.md 的生成是 Claude Code 平台层或 executor 自身行为规范中定义的,不在 Skill Creator 的文档范围内。Skill Creator 只定义了"Grader 应该从哪里读取什么",把 executor 的产出当作一个隐含假设。
为什么 Grader 建议用 subagent
SKILL.md 说 Grader 可以 “spawn a grader subagent (or grade inline)”,但用 subagent 有一个关键好处:上下文隔离。如果由主 agent 自己评分,它已经知道 Skill 的全部内容和设计意图,评分可能有偏见。独立的 Grader subagent 只看到 transcript、outputs 和 assertions,不知道 Skill 是怎么设计的,评分更客观。
为什么 Comparator 必须用 subagent
盲评的核心前提是"不知道哪个输出来自哪个 Skill"。如果由主 agent 做,它写了 Skill、跑了测试,知道一切——盲评就失去了意义。Comparator 必须是独立 subagent 才能保证"盲"的有效性。
全局设计模式总结
| 编号 | 模式 | 体现 |
|---|---|---|
| 1 | 渐进式加载 | 三层信息架构,按需展开 |
| 2 | 对照实验 | 每次测试都跑 with/without 两条线 |
| 3 | 人机协同 | 机器评分 + 人审查 + 机器改进 |
| 4 | Train/Test 防过拟合 | Description 优化中严格划分,按 test 选优 |
| 5 | 脚本复用发现 | 从 subagent 重复劳动中归纳出公共脚本 |
| 6 | Eval 自身质量保证 | Grader 批判断言本身,而非只机械评分 |
| 7 | 盲评消除偏见 | Comparator 不知道谁来自谁,Analyzer 再"揭盲" |
| 8 | 解释 > 命令 | 用"为什么"代替 ALWAYS/NEVER |
| 9 | 稳定逻辑外置 | 确定性工作放 scripts/,判断权留给模型 |
| 10 | 功能降级适配 | 不同环境走不同路径,核心循环不变 |
本文档基于 skill-creator/ 全部源码和文档综合整理。
更多推荐




所有评论(0)