Skill 文件结构
一个 Agent Skill 本质上是一个文件夹,核心是 SKILL.md 文件。理解文件结构是编写高质量 Skill 的基础。
基本结构
最简单的 Skill 只需要一个文件夹和一个 SKILL.md 文件:
my-skill/
└── SKILL.md
这是 Skill 的最小可行单元。SKILL.md 文件包含两部分:YAML frontmatter(元数据)和 Markdown 正文(指令内容)。
SKILL.md 文件详解
完整示例
---
name: "python-code-reviewer"
description: "审查 Python 代码质量,检查 PEP 8 规范、类型注解、文档字符串。当用户请求代码审查或提交 Python 代码时触发。"
---
# Python 代码审查专家
你是一位专业的 Python 代码审查员,精通 PEP 8 规范和 Python 最佳实践。
## 审查范围
### 代码风格
- 检查命名规范(变量、函数、类)
- 检查缩进和空格使用
- 检查行长度(建议不超过 88 字符)
### 类型注解
- 检查函数参数和返回值的类型注解
- 验证类型注解的正确性
### 文档
- 检查 docstring 是否存在
- 验证 docstring 格式(Google/NumPy/Sphinx 风格)
## 输出格式
请按以下格式输出审查结果:
1. **问题列表**:按严重程度排序
- 🔴 严重:可能导致错误的问题
- 🟡 警告:代码风格问题
- 🔵 建议:优化建议
2. **改进建议**:针对每个问题给出具体修改方案
3. **总体评价**:简要总结代码质量
YAML Frontmatter
SKILL.md 文件以 YAML frontmatter 开头,用三个连字符 --- 包围。Frontmatter 定义了 Skill 的元数据。
必需字段
| 字段 | 类型 | 限制 | 说明 |
|---|---|---|---|
name | string | 小写字母、数字、连字符,不超过 64 字符 | Skill 的唯一标识符 |
description | string | 不超过 1024 字符 | 描述 Skill 的功能和触发条件 |
name 字段规范
name 是 Skill 的标识符,需要遵循以下规则:
- 必须是 1-64 个字符
- 只能包含小写字母(
a-z)、数字和连字符(-) - 不能以连字符开头或结尾
- 不能包含连续的连字符(
--) - 必须与父目录名称一致
✅ 正确示例
name: "code-reviewer"
name: "python-linter"
name: "api-doc-generator"
name: "test-writer-v2"
❌ 错误示例
name: "Code Reviewer" # 包含大写字母和空格
name: "code_reviewer" # 使用下划线而非连字符
name: "代码审查" # 包含非 ASCII 字符
name: "-code-reviewer" # 以连字符开头
name: "code-reviewer-" # 以连字符结尾
name: "code--reviewer" # 包含连续连字符
name: "a-very-long-skill-name-that-exceeds-the-64-character-limit" # 超过 64 字符
为什么要求 name 与目录名一致?这个设计确保了 Skill 的可发现性和可维护性。当用户看到目录名时,就能直接知道 Skill 的标识符;当 Agent 需要激活 Skill 时,也能准确定位到对应的文件。这种一致性避免了因为名称不匹配导致的激活失败问题。
重要:name 字段的值必须与 Skill 目录名称完全一致。例如,如果目录是 my-skill/,那么 name 必须是 "my-skill"。
description 字段规范
description 是决定 Skill 何时被触发的关键字段。根据官方规范:
- 必须是 1-1024 个字符
- 非空内容
- 应该同时说明功能描述和触发条件
- 应该包含特定关键词帮助 Agent 识别相关任务
写作风格建议:
官方推荐使用祈使语气(imperative phrasing)来编写 description。将描述框架定为给 Agent 的指令:"Use this skill when..."而不是"This skill does..."。Agent 在决定使用哪个 Skill 时会参考这些描述,一致的视角有助于它做出正确判断。
✅ 好的 description(祈使语气,完整示例)
description: "Use this skill when reviewing Python code for quality, PEP 8 compliance, type hints, and documentation. Activate when the user requests code review, code check, or submits Python code."
✅ 好的 description(简洁示例)
description: "Generate unit tests for code. Use when the user needs tests or test coverage."
中文示例(同样使用祈使语气)
description: "审查 Python 代码质量,检查 PEP 8 规范、类型注解、文档字符串。当用户请求代码审查、代码检查、code review 或提交 Python 代码时使用此技能。"
❌ 太模糊
description: "帮助写代码" # 不清楚具体功能
❌ 太宽泛
description: "处理所有编程相关问题" # 可能导致过度触发
❌ 缺少触发条件
description: "Python 代码审查工具" # 没有说明何时使用
❌ 空内容
description: "" # 不允许空字符串
可选字段
除了必需字段,frontmatter 还支持以下可选字段:
license
指定 Skill 的许可证信息。可以是许可证名称或指向许可证文件的引用。
license: "MIT"
# 或
license: "LICENSE"
disable-model-invocation
布尔值字段,用于禁用模型的自动触发。当设置为 true 时,该 Skill 只能通过用户显式调用(如 /skill-name)激活,不会根据 description 自动触发。
---
name: "deploy-production"
description: "部署到生产环境。需要显式调用。"
disable-model-invocation: true
---
使用场景:
- 高风险操作:部署、删除资源、修改配置等不应被意外触发的操作。想象一下,如果用户只是随意讨论"部署流程",Agent 却意外触发了实际的部署操作,后果可能很严重。这个字段就是为这种场景设计的防护机制。
- 需要人工确认:执行前需要用户明确意图的场景。某些操作即使本身风险不高,但由于涉及到业务流程或审批要求,需要用户主动发起。
- 调试用 Skill:仅用于特定调试场景,不应自动激活。开发者在调试过程中可能创建临时的 Skill,这些不应该影响正常工作流程。
注意:即使禁用了自动触发,Skill 仍会出现在可用 Skills 列表中,用户可以通过斜杠命令或显式调用来使用它。这意味着用户仍然可以手动选择使用这个 Skill,只是 Agent 不会主动建议使用它。
compatibility
说明 Skill 的环境要求,最多 500 字符。只有当 Skill 有特定环境需求时才需要包含此字段。
compatibility: "Requires Python 3.9+ and network access to api.example.com"
大多数 Skill 不需要此字段,因为它们只包含纯文本指令。
metadata
用于存储规范未定义的额外属性,是一个字符串键值对映射。建议使用足够唯一的键名以避免意外冲突。
metadata:
author: "your-name"
version: "1.0.0"
category: "code-quality"
allowed-tools
指定预批准的工具列表,Agent 无需用户确认即可使用这些工具。这是一个实验性字段,不同 Agent 实现对它的支持程度可能不同。
allowed-tools: "read_file write_file run_command"
完整示例
---
name: "api-doc-generator"
description: "为 REST API 生成 OpenAPI 文档。当用户需要生成 API 文档或 OpenAPI 规范时触发。"
license: "MIT"
compatibility: "Requires Node.js 18+ for JSON schema validation"
metadata:
author: "your-name"
version: "2.1.0"
category: "documentation"
allowed-tools: "read_file write_file"
---
Markdown 正文
Frontmatter 之后是 Markdown 格式的正文,这是给 AI 的具体指令。正文内容决定了 Skill 的实际效果。
正文结构建议
一个结构良好的正文通常包含以下部分:
# 标题(定义角色)
简要说明 AI 在这个 Skill 中扮演什么角色。
## 核心职责
列出主要任务和关注点。
## 工作流程
描述执行任务的步骤。
## 输出格式
定义输出的结构和样式。
## 注意事项
列出需要避免的问题或特殊情况。
目录结构变体
最小结构
最简单的 Skill 只需要一个文件夹和一个 SKILL.md 文件:
my-skill/
└── SKILL.md
这是最常见的形式,适用于大多数场景。当指令内容在 500 行以内时,保持单文件结构是最清晰的选择。
包含资源文件的 Skill
如果 Skill 需要引用模板、配置或其他资源文件,可以添加额外的文件:
my-skill/
├── SKILL.md # 主指令文件(必需)
├── scripts/ # 可执行脚本
│ ├── analyze.py
│ └── validate.sh
├── references/ # 参考文档
│ ├── REFERENCE.md
│ └── FORMS.md
└── assets/ # 静态资源
├── templates/
└── images/
官方推荐目录结构
根据官方规范,完整的 Skill 目录结构如下:
skill-name/
├── SKILL.md # 必需:主指令文件
├── scripts/ # 可选:可执行代码
│ ├── helper.py # 工具脚本
│ └── process.sh # Shell 脚本
├── references/ # 可选:详细参考文档
│ ├── REFERENCE.md # 技术参考
│ ├── FORMS.md # 表单模板
│ └── domain.md # 领域特定指南
└── assets/ # 可选:静态资源
├── templates/ # 模板文件
├── images/ # 图片资源
└── data/ # 数据文件
各目录用途详解
scripts/ - 存放 Agent 可以执行的脚本代码
脚本应该:
- 自包含或明确记录依赖关系
- 包含有用的错误信息
- 优雅处理边界情况
- 使用相对路径引用同目录下的其他文件
references/ - 存放详细参考文档
常见的文件包括:
REFERENCE.md:详细技术参考FORMS.md:表单模板或结构化数据格式- 领域特定文件:
finance.md、legal.md等
assets/ - 存放静态资源
常见内容:
- 模板文件:文档模板、配置模板
- 图片资源:示意图、示例图
- 数据文件:查找表、模式定义
存放位置
不同工具对 Skill 存放位置有不同的约定:
Claude Code
项目根目录/
├── .claude/
│ └── skills/
│ ├── code-reviewer/
│ │ └── SKILL.md
│ └── doc-generator/
│ └── SKILL.md
└── ...
Trae IDE
项目根目录/
├── .trae/
│ └── skills/
│ ├── code-reviewer/
│ │ └── SKILL.md
│ └── doc-generator/
│ └── SKILL.md
└── ...
Cursor
项目根目录/
├── .cursor/
│ └── skills/
│ ├── code-reviewer/
│ │ └── SKILL.md
│ └── doc-generator/
│ └── SKILL.md
└── ...
全局 Skills
除了项目级别的 Skills,还可以创建全局 Skills,适用于所有项目:
用户目录/
├── .claude/
│ └── skills/
│ └── global-skill/
│ └── SKILL.md
文件编码
SKILL.md 文件应使用 UTF-8 编码,确保中文字符正常显示。
可选目录结构
除了 SKILL.md 文件,Skill 还可以包含其他目录和资源文件,用于支持更复杂的工作流。
scripts/ 目录
存放 Agent 可以执行的脚本代码。脚本应该:
- 自包含或明确记录依赖
- 包含有用的错误信息
- 优雅处理边界情况
my-skill/
├── SKILL.md
└── scripts/
├── analyze.py
├── validate.sh
└── utils/
└── helpers.py
references/ 目录
存放 Agent 在需要时可以读取的详细文档:
my-skill/
├── SKILL.md
└── references/
├── REFERENCE.md # 详细技术参考
├── FORMS.md # 表单模板
└── domain-guide.md # 领域特定指南
assets/ 目录
存放静态资源文件:
my-skill/
├── SKILL.md
└── assets/
├── templates/
│ └── config.yaml
├── images/
│ └── diagram.png
└── data/
└── lookup-table.json
渐进式披露
Skills 采用渐进式披露(Progressive Disclosure)策略来高效管理上下文:
三层加载机制
| 层级 | 加载内容 | 加载时机 | Token 消耗 |
|---|---|---|---|
| 1. 目录 | name + description | 会话启动时 | 每个 Skill 约 50-100 tokens |
| 2. 指令 | 完整 SKILL.md 正文 | Skill 被激活时 | 建议 < 5000 tokens |
| 3. 资源 | scripts、references、assets | 指令引用时 | 因文件而异 |
设计建议
保持 SKILL.md 简洁:建议保持在 500 行以内。如果内容过长,将详细参考材料移到单独的文件中。
明确引用时机:告诉 Agent 何时 加载每个文件,而不是笼统地说"详见 references/"。
# 好的做法
如果 API 返回非 200 状态码,请阅读 references/api-errors.md 了解错误处理方法。
# 不好的做法
更多信息请参阅 references/ 目录。
文件引用
在 Skill 中引用其他文件时,使用相对于 Skill 根目录的相对路径。
引用语法
---
name: "form-filler"
description: "填写 PDF 表单。当用户需要填写表单时触发。"
---
# PDF 表单填写器
## 工作流程
1. 阅读表单字段定义:`forms/field_definitions.json`
2. 验证用户输入与字段定义匹配
3. 使用 `scripts/fill_form.py` 填写表单
4. 输出填写结果
## 参考文档
- 字段验证规则:`references/validation-rules.md`
- 支持的表单类型:`references/form-types.md`
引用最佳实践
明确引用时机:告诉 Agent 何时 加载每个文件,而不是笼统地说"详见 references/"。
# 好的做法
如果 API 返回非 200 状态码,请阅读 references/api-errors.md 了解错误处理方法。
# 不好的做法
更多信息请参阅 references/ 目录。
避免深层嵌套:保持引用链简单,避免多层嵌套的文件引用。
使用描述性说明:在引用文件前,简要说明其内容。
## 错误处理
当遇到以下错误时,请查阅 `references/error-codes.md`:
- 认证错误(401)
- 权限错误(403)
- 资源不存在(404)
引用 vs 内联
何时使用外部文件,何时直接写在 SKILL.md 中?
| 内容类型 | 推荐方式 | 原因 |
|---|---|---|
| 核心工作流程 | 内联 | 每次都需要 |
| 简短示例 | 内联 | Token 成本低 |
| 详细 API 参考 | 外部文件 | 按需加载 |
| 大量模板 | 外部文件 | 可能不常用 |
| 错误代码表 | 外部文件 | 查阅性质 |
命名规范
文件夹命名
- 使用小写字母
- 单词之间用连字符连接
- 名称应简洁且具有描述性
✅ 好的命名
code-reviewer/
python-linter/
api-doc-generator/
❌ 不好的命名
CodeReviewer/ # 大写字母
code_reviewer/ # 下划线
skill1/ # 无意义名称
与 name 字段的关系
文件夹名称必须与 SKILL.md 中的 name 字段完全一致,这是官方规范的强制要求:
✅ 正确:name 与目录名一致
code-reviewer/
└── SKILL.md # name: "code-reviewer"
❌ 错误:name 与目录名不一致
my-code-reviewer/
└── SKILL.md # name: "code-reviewer" # 不匹配!
验证 Skill
官方提供了 skills-ref 参考库来验证 Skill 的正确性。
安装验证工具
# 使用 npx 直接运行(推荐)
npx skills-ref validate ./my-skill
# 或全局安装
npm install -g skills-ref
skills-ref validate ./my-skill
验证内容
验证工具会检查以下内容:
frontmatter 格式检查
- 是否使用正确的
---分隔符 - YAML 语法是否正确
必需字段检查
name字段是否存在description字段是否存在
字段规范检查
name是否符合命名规范(小写、连字符、长度限制等)name是否与父目录名称一致description是否为空或超过 1024 字符
常见验证错误
| 错误 | 原因 | 解决方案 |
|---|---|---|
Missing required field: name | 缺少 name 字段 | 在 frontmatter 中添加 name |
Invalid name format | name 包含非法字符 | 只使用小写字母、数字、连字符 |
Name does not match directory | name 与目录名不一致 | 修改 name 或重命名目录 |
Description exceeds 1024 characters | description 太长 | 缩短描述内容 |
Description is empty | description 为空 | 添加有意义的描述 |
Invalid YAML syntax | YAML 格式错误 | 检查缩进和特殊字符 |
宽松验证模式
某些客户端实现采用宽松验证模式,即使存在小问题也会尝试加载 Skill。这种设计是为了提高兼容性——不同客户端可能使用不同的 YAML 解析器,有些 Skill 文件可能在某个客户端能工作但在另一个客户端出错。
| 问题 | 宽松处理 |
|---|---|
| name 不匹配目录名 | 警告,继续加载 |
| name 超过 64 字符 | 警告,继续加载 |
| description 缺失或为空 | 跳过该 Skill,记录错误 |
| YAML 完全无法解析 | 跳过该 Skill,记录错误 |
宽松模式的核心原则是:尽量让 Skill 工作,但对于会导致功能完全失效的问题(如缺少 description),则必须跳过。为什么 description 缺失会导致 Skill 被跳过?因为 description 是渐进式披露的核心——Agent 在会话启动时只能看到所有 Skill 的 name 和 description。如果没有 description,Agent 就无法判断这个 Skill 是否与当前任务相关,Skill 实际上就失去了存在的意义。
常见 YAML 解析问题
YAML 解析器对某些格式比较敏感,尤其是包含特殊字符的值:
# 问题:未引用的值包含冒号
description: 处理 API: 连接问题 # 解析器可能将 "API: 连接问题" 误解为新字段
# 解决:使用引号包裹
description: "处理 API: 连接问题"
# 问题:多行描述缩进不一致
metadata:
author: name
version: 1.0 # 缩进多了一个空格
# 解决:保持一致缩进
metadata:
author: name
version: 1.0
验证最佳实践
- 在提交前验证:将验证步骤加入 CI/CD 流程,确保所有 Skill 都符合规范
- 检查所有 Skills:验证整个 skills 目录,而不是单个 Skill
- 处理警告:即使 Skill 可以加载,也应修复警告,保持最佳兼容性
# 验证单个 Skill
npx skills-ref validate ./my-skill
# 验证所有 Skills
npx skills-ref validate ./**/*.skill
# 在 package.json 中添加验证脚本
{
"scripts": {
"validate-skills": "skills-ref validate .claude/skills/*/"
}
}
小结
理解 Skill 的文件结构是编写高质量 Skill 的第一步。记住以下要点:
- 最小结构:一个文件夹 + 一个 SKILL.md 文件
- 必需字段:name 和 description 是 frontmatter 的必需字段
- name 必须匹配目录名:name 字段的值必须与 Skill 目录名称完全一致
- description 关键:清晰描述功能和触发条件,1-1024 字符,使用祈使语气
- 正文结构:角色定义、职责、流程、输出格式
- 存放位置:遵循各工具的约定,优先使用
.agents/skills/实现跨客户端共享 - 渐进式披露:保持 SKILL.md 简洁(建议 < 500 行),详细内容放入 references/
- 验证工具:使用 skills-ref 验证 Skill 格式的正确性
下一步,我们将学习 如何编写高质量的 Skill。