什么是 SKILL

SKILL 是一个文件夹,里面有一份 SKILL.md 文件,告诉 AI Agent 怎么完成某个具体任务。可以附带脚本、参考文档、模板等辅助材料。

它遵循 agentskills.io 开放标准,最初由 Anthropic 提出,现已被 Claude Code、GitHub Copilot、VS Code、Cursor、OpenAI Codex、Hermes Agent 等 30+ 产品支持。你写一份 SKILL,可以在不同 Agent 产品间复用。

SKILL 和 MCP 的区别

两者经常一起出现,但定位完全不同:

维度 SKILL MCP
是什么 说明书、操作手册 工具、工具箱
本质 Markdown 文本指令 运行中的服务进程
给 Agent 什么 告诉它怎么做 给它新工具
标准 agentskills.io 开放标准 Model Context Protocol
创建方式 写 Markdown,5 分钟 运行兼容 MCP 的 Server 进程
加载方式 按需渐进式加载,不占资源 后台维持连接,常驻内存

简单说:SKILL 管过程(How),MCP 管能力(What)。 能力不够先上 MCP,流程复杂再包一层 SKILL。已有的系统命令能搞定的事,SKILL 就够了;需要新”工具语义”(数据库连接、浏览器操控、第三方 API 持续对接),才上 MCP。

SKILL 和 Memory 的区别

SKILL Memory
存什么 怎么做的过程 是什么的事实
好比 菜谱 便签条
大小 可以几百行 要精简到关键事实
加载方式 用到才翻 每次自动贴在眼前
例子 “部署到 K8s 的 10 个步骤” “用户用 AWS 不用 GCP”

SKILL.md 格式

一个最简 SKILL 只需要一个目录和一份 SKILL.md 文件。

Frontmatter(YAML 头)

1
2
3
4
5
6
7
8
9
10
11
12
---
name: pdf-processing # 必需,1-64字符,小写字母+数字+连字符
description: > # 必需,≤1024字符,描述做什么+何时用
提取PDF文字、填表单、合并文件。
处理PDF文档时使用。
license: Apache-2.0 # 可选
compatibility: 需要 python3 pdftotext # 可选,环境要求
metadata: # 可选,扩展字段
author: example-org
version: "1.0"
allowed-tools: Bash(git:*) # 可选(实验性),预批准的工具列表
---

name 字段约束:

  • 只能用小写字母、数字和连字符
  • 不能以连字符开头或结尾
  • 不能有连续连字符(pdf--processing 不行)
  • 必须和父目录名一致

description 是触发 SKILL 的唯一起点。Agent 启动时只加载所有 SKILL 的 name + description,任务匹配时才打开完整内容。description 写得好不好直接决定 SKILL 能不能被用到。三条原则:

  1. 用祈使句:Agent 正在决策”要不要加载这个 SKILL”,直接告诉它”在 X 情况下加载我”
  2. 关注用户意图而非实现细节:描述用户想达成什么,不是 SKILL 内部做了什么
  3. 宁可”pushy”一点:明确列出触发场景,包括用户不直接说关键词的情况

好例子:

1
2
3
4
description: >
分析 CSV 和表格数据——计算统计摘要、添加派生列、
生成图表、清洗脏数据。当用户有 CSV/TSV/Excel 文件
需要探索、转换或可视化时使用,即使没明确说"CSV"或"分析"。

差例子:

1
description: 处理 CSV 文件。

Body(Markdown 正文)

推荐结构:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
## 这个 SKILL 什么时候用
具体触发场景。写清楚 Agent 在什么情况下应该加载这份 SKILL。

## 快速参考
常用命令或 API 速查表。一行命令能搞定的事放这里。

## 操作步骤
1. 第一步:检查前置条件
2. 第二步:执行核心命令
3. 第三步:验证结果

## 常见坑(Gotchas)
- 错误描述 → 正确的做法
- 边界情况说明

## 验证方法
如何确认操作成功

Body 不超 500 行、5000 token。 超出内容放到 references/ 里按需引用——这是渐进式披露机制的设计要求。


目录结构

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
my-skill/
├── SKILL.md # 核心文件:元数据 + 操作步骤(≤500行)
├── scripts/ # 可执行脚本(Python/Bash/JS)
│ ├── validate.py # 验证脚本
│ └── process.sh # 处理脚本
├── references/ # 按需加载的参考文档
│ ├── api-docs.md # API 详细参考
│ └── schema.yaml # 数据 Schema
├── templates/ # 输出格式模板
│ └── report.md # 报告模板
├── assets/ # 静态资源
│ └── logo.png # 图片
└── evals/ # 测试用例
├── evals.json # 测试用例定义
└── files/ # 测试用输入文件
└── sample.csv

文件引用:统一用相对路径

SKILL 内部引用其他文件时,用从 SKILL 根目录出发的相对路径

1
2
3
4
详细 Schema 见 [references/schema.yaml](references/schema.yaml)。

运行验证脚本:
bash scripts/validate.py --input data.csv

渐进式披露的三层加载

层级 内容 时机 Token 消耗
第一层 name + description 启动时自动加载 ~100/每个 SKILL
第二层 SKILL.md 正文 任务匹配时加载 ≤5000
第三层 references/ 等文件 步骤中引用时才加载 按需

编写技巧

1. 从真实经验出发,别让 LLM 凭空编

用 LLM 空口生成的 SKILL 最大问题是太泛——全是”适当处理错误””遵循最佳实践”这类废话,没有真正有价值的具体指令。

从实际任务中提取: 完成一次真实任务,过程中你的每一个纠正、每一个补充、每一个”别用库 X,用库 Y”,都是 SKILL 里最有价值的内容。记录哪些步骤真正有效、你纠正了 Agent 哪些思路、输入输出的实际格式、Agent 不知道但你知道的项目特定信息。

从现有项目资产合成: 把团队文档、Runbook、代码规范、API Schema、工单记录喂给 LLM 合成 SKILL——这比从”CSV 分析最佳实践”这类通用文章合成强十倍,因为它捕获的是你们自己的 Schema、失败模式和恢复流程。

2. 只写 Agent 不知道的,省略它已经懂的

每一段内容过一遍灵魂拷问:**”没有这段指令,Agent 会搞错吗?”** 如果答案是”不会”,砍掉。

1
2
3
4
5
6
<!-- 啰嗦 —— Agent 不需要你教它什么是 PDF -->
PDF(Portable Document Format)是一种包含文字、图片等内容的常见文件格式。
推荐使用 pdfplumber 因为它能处理大多数情况。

<!-- 简洁 —— 直接跳到 Agent 自己不知道的东西 -->
使用 pdfplumber 提取文字。扫描件用 pdf2image + pytesseract。

3. 设计合理的粒度

像设计函数一样设计 SKILL:太窄 → 一个任务要加载多个 SKILL,有开销和指令冲突风险。太宽 → 难以精确触发。一个”查询数据库 + 格式化结果”的 SKILL 通常是合理粒度,但再加”管理数据库”就太宽了。

4. 匹配控制力度

给自由度的情况(多种方案都有效)——解释为什么比严格指令更好:

1
2
3
4
5
## 代码审查流程
1. 检查所有数据库查询是否存在 SQL 注入(使用参数化查询)
2. 验证每个端点的认证检查
3. 检查并发代码中的竞态条件
4. 确认错误消息不泄露内部细节

严格约束的情况(操作脆弱、顺序不能乱):

1
2
3
4
## 数据库迁移
严格按此顺序执行:
bash scripts/migrate.py --verify --backup
不要修改命令或添加额外参数。

大多数 SKILL 是两者混合——每个部分独立校准。

5. 给默认方案,别给菜单

多个工具都能用时,选一个作为默认,备选方案作为 fallback 简短提及:

1
2
3
4
5
<!-- 太多选项 -->
你可以用 pypdf、pdfplumber、PyMuPDF 或 pdf2image...

<!-- 清晰的默认 + 逃生通道 -->
使用 pdfplumber 提取文字。需要 OCR 的扫描件,改用 pdf2image + pytesseract。

6. 教方法,别只给答案

SKILL 应该教 Agent 怎么处理一类问题,而不是给某个特定场景的答案

1
2
3
4
5
6
7
8
<!-- 只对这个任务有用 —— 换个表就废了 -->
把 orders 表 join customers 表,过滤 region = 'EMEA',sum amount 列。

<!-- 可复用 —— 适用于任何分析查询 -->
1. 从 references/schema.yaml 读取 Schema
2._id 外键约定 join 表
3. 把用户的筛选条件转为 WHERE 子句
4. 聚合并格式化为 Markdown 表格

7. Gotchas 是 SKILL 里最有价值的部分

Gotchas 不是通用建议(”适当处理错误”),而是违背常理、Agent 不被告知就会犯错的具体事实

1
2
3
4
## Gotchas
- users 表用软删除。查询必须加 WHERE deleted_at IS NULL,否则会包含已注销账号。
- 用户 ID:数据库叫 user_id,认证服务叫 uid,账单 API 叫 accountId。三个指向同一个值。
- /health 端点返回 200 只表示 Web 服务器在运行,不表示数据库连得上。检查全链路健康用 /ready。

每次 Agent 犯了需要你纠正的错误,把纠正加到 Gotchas 小节。这是迭代改进 SKILL 最高效的方式。

8. 输出模板优于文字描述

需要特定格式输出时,给模板比描述更可靠——Agent 对具体结构的模式匹配远好于对抽象指令的执行:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
## 报告结构
使用此模板,按分析内容适配:

```markdown
# [分析标题]
## 摘要
[关键发现的一段概述]

## 发现
- 发现 1(附支撑数据)
- 发现 2(附支撑数据)

## 建议
1. 具体可执行的建议
2. 具体可执行的建议
```

9. 多步流程加上 Checklist

显式的 Checklist 帮 Agent 跟踪进度、避免跳步。尤其适合步骤间有依赖或需要验证关卡的场景:

1
2
3
4
5
6
## 表单处理流程
- [ ] Step 1: 分析表单(运行 scripts/analyze_form.py)
- [ ] Step 2: 创建字段映射(编辑 fields.json)
- [ ] Step 3: 验证映射(运行 scripts/validate_fields.py)
- [ ] Step 4: 填充表单(运行 scripts/fill_form.py)
- [ ] Step 5: 验证输出(运行 scripts/verify_output.py)

10. 加入自验证循环

让 Agent 干完活自己验证一遍再往前走:

1
2
3
4
5
## 编辑工作流
1. 执行编辑
2. 运行验证:python scripts/validate.py output/
3. 如果验证失败,查看错误信息,修复问题,重新验证
4. 只有验证通过后才继续

11. 复杂逻辑抽成脚本

如果你发现 Agent 每次执行都在重写同一段逻辑(画图、解析特定格式、验证输出),把这段逻辑抽成测试过的脚本放到 scripts/ 里。脚本的可靠性和一致性远高于 LLM 每次现写。


实际案例对比

约 70 行,只做一件事:用 curl + jq 调用 Tenor API 搜 GIF。结构:Setup → 搜索 → 下载 → API 参数表 → 可用媒体格式 → Notes。

亮点:

  • API 参数用表格呈现,每个命令直接可复制运行
  • 零代码依赖——curl 和 jq 是标配工具
  • scripts/ 都不需要,所有逻辑一行 shell 搞定

适合什么场景: 包装一个外部 API,Agent 用 terminal 工具直接调。

案例 B:工作流型 — github-pr-workflow

约 400+ 行,覆盖 PR 完整生命周期。核心特征:

  • 双路径设计:每个步骤同时提供 ghgit + curl 两种方案,Agent 根据环境自动选择
  • Quick Auth Detection 脚本块:自动检测认证方式
  • **带完整的 references/ 和 templates/**:PR 模板、CI 故障排查参考、Conventional Commits 规范
  • Auto-Fix 循环模式:CI 失败后自动诊断→修复→推送→重检的完整闭环

亮点: 分层分路径,每个命令有输出示例,复杂跨步骤工作流用参考文件承载。

适合什么场景: 多步骤、有分支逻辑、需要兼容不同环境的操作。

案例 C:方法论型 — systematic-debugging

约 550 行,完全不教具体命令,教的是思维方式

  • Iron Law 前置:不找到根因不许修
  • 四个 Phase 硬性顺序(不到 Phase 1 不做 Phase 2)
  • Red Flags 清单:触发任一红线立即 STOP
  • 常见借口表:每一个偷懒的借口对应一句反驳
  • Phase 完成 Checklist:可以逐条打勾

亮点: 大量 STOP 规则,反模式速查表,像”驾校教练教你什么时候看后视镜”而非”帮你打方向盘”。

适合什么场景: 教授方法、规范流程、防止 Agent 在压力下走捷径犯低级错误。


进阶特性

条件激活

SKILL 可以根据当前会话可用的工具自动显示或隐藏:

1
2
3
4
5
6
7
metadata:
hermes:
requires_toolsets: [web] # 只有 web toolset 可用时才显示
requires_tools: [web_search] # 只有 web_search 工具可用时才显示
fallback_for_toolsets: [web] # web toolset 不可用时才显示(降级替代)
fallback_for_tools: [browser_navigate]
platforms: [macos, linux] # 限定操作系统

典型场景: 创建一个 DuckDuckGo 搜索 SKILL,设置 fallback_for_toolsets: [web]——当用户没配搜索引擎 API Key 时自动出现作为降级方案;配了 API Key 时自动隐藏。

Blueprint(自动化 SKILL)

在 frontmatter 加一个 blueprint: 块,SKILL 秒变定时任务:

1
2
3
4
5
6
metadata:
hermes:
blueprint:
schedule: "0 8 * * *"
deliver: telegram
prompt: "总结未读邮件和今天的日历"

安装后不会自动创建 cron job——而是出现在 /suggestions 里,用户手动接受后才调度。

Skill Bundle(组合技)

固化常用的 SKILL 组合为 YAML Bundle:

1
2
3
4
5
6
7
8
# ~/.hermes/skill-bundles/backend-dev.yaml
name: backend-dev
skills:
- github-code-review
- test-driven-development
- github-pr-workflow
instruction: |
始终先写失败的测试,再实现功能。

然后在对话中 /backend-dev 一次性加载三个 SKILL。

声明环境变量需求

1
2
3
4
5
required_environment_variables:
- name: TENOR_API_KEY
prompt: Tenor API key
help: https://developers.google.com/tenor 获取
required_for: GIF 搜索功能

声明后,Hermes 在 SKILL 加载时自动提示配置,且该变量自动传入 execute_codeterminal 沙箱——脚本直接用 $TENOR_API_KEY 即可。


测试 SKILL

1. 手动冒烟测试

最简化:新建会话,加载 SKILL,给一个典型任务,看 Agent 是否按预期执行。

1
hermes chat --toolsets skills -q "用 arxiv SKILL 搜 transformer 论文"

2. 结构化 Eval

更严谨的做法是建立测试用例集。在 evals/evals.json 中定义:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
{
"skill_name": "csv-analyzer",
"evals": [
{
"id": 1,
"prompt": "分析 data/sales_2025.csv,找出营收最高的 3 个月,画柱状图",
"expected_output": "一张标注了轴标签和数值的柱状图,展示营收最高的 3 个月",
"files": ["evals/files/sales_2025.csv"],
"assertions": [
"输出包含一张柱状图",
"图表恰好展示 3 个月",
"两个轴都有标签",
"图表标题或说明提到了营收"
]
}
]
}

每个测试用例跑两遍:一遍带 SKILL,一遍不带(作为基线对比)。记录 token 消耗和执行时间,比较 SKILL 是否真的让结果更好、更快。

3. Description 触发率测试

SKILL 能被用到的前提是 description 写对了。准备约 20 条查询:

  • 8-10 条应该触发 SKILL 的(变化措辞、详细程度、是否显式提及关键词)
  • 8-10 条不应该触发的(关键要包含近义词干扰——“帮我更新 Excel 预算表”看起来像 CSV 分析但实际上需要 Excel 编辑)

每条跑 3 次(模型有随机性),统计触发率。触发率 > 50% 才算通过。

4. 迭代优化循环

1
1. 评估当前 SKILL → 2. 分析失败用例 → 3. 修改 SKILL → 4. 重新评估 → 回到 1

关键:用 60% 的测试用例做训练集(用来发现问题),40% 做验证集(只在最后验证改进是否泛化,不参与修改过程)。防止过拟合到特定测试用例措辞。

5 轮迭代通常够了。如果性能不再提升,问题可能在测试用例(太简单、太刁钻、或标注错误)而不是 description。


总结

十条核心原则:

  1. 从真实经验出发——别让 LLM 凭空编,把你实际踩过的坑和纠正写进去
  2. 只写 Agent 不知道的——每段内容过”没有这段 Agent 会犯错吗”的灵魂拷问
  3. 粒度像函数——单一职责,能用一句话说清楚”什么时候用这个 SKILL”
  4. 匹配控制力度——灵活任务给自由度,危险操作严格约束
  5. 给默认方案——选一个工具作为默认,备选方案作为 fallback
  6. 教方法不教答案——Agent 要学会处理一类问题,而不是背一个具体答案
  7. Gotchas 是最有价值的部分——Agent 犯一次错,加到 Gotchas,不再犯第二次
  8. 输出给模板而不是描述——Agent 对具体结构的模式匹配远好于对抽象指令的执行
  9. 复杂逻辑抽成脚本——不要指望 Agent 每次现写解析器
  10. 持续迭代——跑真实任务 → 看执行记录 → 改 SKILL → 再跑 → 循环

好 SKILL 的标准:Agent 用上它后,犯的错更少、产出更一致、不需要你反复纠正同一个问题。 如果你发现自己每次都在纠正同一类错误,那个纠正就该进 SKILL。