主题模式
AI 智能体 Skill 开发深度解析:从原理到实战的完整指南
智能体的能力边界,由 Skill 决定。学会开发 Skill,就等于给 AI 装上了可插拔的专业模块。本文从 SKILL.md 规范出发,结合 QClaw/OpenClaw 生态中的真实 Skill 源码,深入讲解 Skill 的设计哲学、目录结构、SKILL.md 语法、工具集成,以及如何通过 Skill Workshop 发布和管理自己的 Skill。读完这篇,你将具备从零构建生产级 Skill 的能力。
一、为什么需要 Skill?
在 AI 智能体系统中,模型本身是通用的,但真实世界的问题需要专业能力。Skill(技能包)正是解决这个矛盾的核心机制——它将特定领域的专业知识、工作流程、工具调用规范打包成可插拔的模块,让智能体在面对专业任务时自动加载对应的 Skill,从而"变身为"该领域的专家。
通用大模型 ── + Skill (Web检索) ──→ 专业研究员
── + Skill (日历管理) ──→ 个人助理
── + Skill (代码执行) ──→ 开发助手
── + Skill (PDF处理) ──→ 文档分析专家Skill vs Prompt Template 的本质区别:
| 维度 | Prompt Template | Skill |
|---|---|---|
| 持久性 | 每次对话重置 | 一次性加载,长期有效 |
| 工具能力 | 依赖模型内化 | 可声明专用工具接口 |
| 上下文占用 | 全部占用上下文 | 按需加载,按需读取 |
| 版本管理 | 分散在对话历史中 | 独立文件,可版本控制 |
| 团队共享 | 复制粘贴 | 分发安装,标准化复用 |
二、SKILL.md 规范详解
每个 Skill 的核心是 SKILL.md 文件,它是 Skill 的"身份证"和"使用说明书"。先看一个最小完整的示例:
markdown
---
name: my-first-skill
description: 这是我的第一个 Skill。当用户说"做什么 XX"或"如何 XX"时触发。
---
# 我的第一个 Skill
这是 Skill 的主体说明文档。这个结构看似简单,但 description 字段是 Skill 系统的核心——它决定了何时触发这个 Skill。让我们深入了解每个部分。
2.1 Frontmatter:Skill 的元数据
yaml
---
name: skill-name # 唯一标识,字母/数字/下划线/连字符
description: 触发描述 # 【关键】决定何时自动加载
license: MIT # 可选,许可证声明
compatibility: # 可选,环境兼容性说明
- openclaw >= 1.0
---description 字段的触发机制:
Skill 触发系统会分析用户消息,匹配最相关的 Skill 描述。因此 description 的写法直接影响 Skill 的激活率。好的描述应该:
yaml
# ❌ 过于抽象,触发词模糊
description: "用于处理各种任务"
# ❌ 过于冗长,关键词不突出
description: "当用户在处理文档相关工作时,如果涉及到 Word 文档的创建、编辑,或者 PDF 文件的读取,或者需要将某个内容转换为特定格式,并且用户可能使用中文或英文描述相关需求,这种情况下应使用本 Skill"
# ✅ 精准触发词 + 核心能力描述
description: "当用户想要创建、编辑、读取或转换 Word 文档(.docx)时使用。也用于报告、备忘录、信函等 Word 文件的生成、格式化和内容插入。触发词:Word文档、docx、Word doc"
# ✅ 功能场景覆盖
description: "当用户提出类似'我怎么做 X'、'有没有可以……的技能'、'找一个能做 X 的技能'等问题,或表达出扩展功能的需求时触发"触发词设计模式:
yaml
# 模式1:直接动作词
description: "当用户提到【生成图片】【AI 作画】【画一张】【text-to-image】时触发"
# 模式2:任务场景词
description: "当用户说'做一个地图'、'生成地图网页'、'在地图上标点'、'展示路线'、'热力图'时使用"
# 模式3:文件类型关联词
description: "处理 PDF 文件时使用,包括读取文本、提取表格、合并/拆分、添加水印、OCR 识别"
# 模式4:组合触发
description: "当涉及定时/提醒/闹钟/周期执行/打卡/签到/cron/schedule/remind 等需求,或修改/暂停/删除已有定时任务时,【必须】读取本 Skill"2.2 Body:Skill 的工作流程
Body 部分是 Skill 的核心指令集,决定 Skill 被触发后智能体如何工作:
markdown
---
name: example-skill
description: 处理 XX 任务
---
# Example Skill
## 概述
简要说明本 Skill 做什么,什么时候使用。
## 工作流程
当用户请求 XX 时,按以下步骤执行:
### Step 1: 准备
[具体操作步骤]
### Step 2: 执行
[代码示例或命令]
### Step 3: 交付
[结果如何返回给用户]
## 注意事项
- 要点1
- 要点2
## 工具接口
如果 Skill 提供了专用工具,描述它们的用法。Body 的三种自由度层级:
markdown
# 高自由度:适合需要判断力的任务
## 工作流程
1. 分析用户需求,判断是否属于本 Skill 范围
2. 选择最合适的方案(给出多种选项)
3. 执行并返回结果
# 中自由度:适合有推荐路径但允许变化的任务
## 工作流程
1. 首先尝试使用默认方法(如下)
2. 如果失败,使用备选方案
3. 记录失败原因供下次改进
# 低自由度:适合需要精确执行序列的任务
## 工作流程
1. 执行命令 A(不可跳过)
2. 等待完成
3. 执行命令 B(使用如下具体命令)三、目录结构:Skill 的物理形态
一个完整的 Skill 包含 SKILL.md 和可选的捆绑资源:
skill-name/
├── SKILL.md # 【必须】技能定义文件
├── scripts/ # 【可选】可执行脚本(Python/Bash/JS)
│ ├── main.py
│ └── utils.sh
├── references/ # 【可选】参考文档(按需加载)
│ ├── api_spec.md
│ └── schemas.md
└── assets/ # 【可选】输出资源(模板/图片/字体)
├── template.docx
└── logo.png3.1 scripts/:确定性任务的可执行保障
当任务需要确定性执行(每次结果必须完全一致)或重复执行(避免每次重新生成相同代码)时,应该将逻辑放入 scripts/:
python
#!/usr/bin/env python3
# scripts/rotate_pdf.py
"""
PDF 旋转工具:精确控制每页旋转角度
支持:顺时针 90°/180°/270°
"""
import sys
from pypdf import PdfReader, PdfWriter
def rotate_pdf(input_path, output_path, degrees=90):
reader = PdfReader(input_path)
writer = PdfWriter()
for page in reader.pages:
page.rotate(degrees)
writer.add_page(page)
with open(output_path, 'wb') as f:
writer.write(f)
print(f"旋转完成:{degrees}° → {output_path}")
if __name__ == '__main__':
_, input_path, output_path, degrees = sys.argv
rotate_pdf(input_path, output_path, int(degrees))在 SKILL.md 中调用:
markdown
## 旋转 PDF
使用内置脚本旋转 PDF:
```bash
python3 scripts/rotate_pdf.py input.pdf output.pdf 90
**scripts/ 适用场景判断:**
- ✅ 同一段代码被重复使用(避免每次重新生成)
- ✅ 需要确定性结果(不接受 LLM 幻觉)
- ✅ 依赖特定环境/包(标准化执行环境)
- ❌ 一次性探索性任务
- ❌ 代码需要根据上下文灵活变化(此时放在 SKILL.md 中更合适)
### 3.2 references/:大型文档的按需加载
将大型参考文档放在 `references/`,只在需要时才让智能体读取,避免占用不必要的上下文:
```markdown
# SKILL.md(精简)
---
name: finance-advisor
description: 财务分析和报告任务
---
## 工作流程
### Step 1: 理解需求
与用户确认财务报告的类型和分析维度。
### Step 2: 加载参考数据
根据任务类型,按需加载对应参考文档:
- 资产负债表分析 → `references/balance_sheet_schema.md`
- 现金流量表分析 → `references/cashflow_schema.md`
- 财务比率计算 → `references/ratio_formulas.md`
### Step 3: 执行分析
使用加载的参考数据进行具体分析。
---
# references/ratio_formulas.md(大型参考文档)
# 财务比率公式参考
## 盈利能力指标
- 毛利率 = (营收 - 销货成本) / 营收 × 100%
- 净利率 = 净利润 / 营收 × 100%
- ROE = 净利润 / 股东权益 × 100%
...(大量详细公式和示例)使用建议: 当参考文档超过 10,000 字时,强烈建议放到 references/,并在 SKILL.md 中写明"在需要时加载 references/xxx.md"。
3.3 assets/:产出物的模板资源
当 Skill 需要生成标准化输出(文档、演示文稿、图片)时,将模板文件放在 assets/:
frontend-design-skill/
├── SKILL.md
└── assets/
├── base-template.html
├── style-guide.css
└── components/
└── button-variants.json在 SKILL.md 中使用:
markdown
## 生成前端页面
使用模板生成标准化的前端页面:
1. 复制 `assets/base-template.html` 作为起点
2. 根据用户需求填充内容
3. 应用 `assets/style-guide.css` 中的设计系统四、真实 Skill 源码解析
4.1 路由型 Skill:email-skill
路由型 Skill 本身不执行业务逻辑,而是根据用户意图分发到下游 Skill。这是复杂系统中的常见模式:
markdown
# email-skill/SKILL.md
---
name: email-skill
description: 邮件统一入口(纯路由层),自身不执行任何脚本与接口,识别用户意图后路由到下游。
---
# Email Skill
## 路由决策流程
### L0:用户是否显式指定邮箱通道?
- **是** → 'Agent/AI 邮箱' → 读取 `agent-email/SKILL.md`
- **是** → '用我的 QQ/163/Gmail/Outlook' → 读取 `imap-smtp-email/SKILL.md`
- **是** → '发到我邮箱/推到我邮箱/保存到邮箱' → 读取 `public-skill/SKILL.md`
### L1:L0 未指定时
- **发给自己/结果留存** → 读取 `public-skill/SKILL.md`
- **发给别人/完整收发** → 读取 `personal-mail-skill/SKILL.md`
## 关键原则
**绝不向用户追问账号选择**,由系统拦截层统一处理。
**自身不执行任何脚本与接口**,只做路由决策。路由型 Skill 的设计要点:
- 职责单一:只判断 + 路由,不做实际工作
- 决策树清晰:L0 → L1 两层决策,避免分支爆炸
- 下游解耦:路由到具体 Skill 后,原 Skill 立即退出
- 入口文档:作为系统对外的统一入口,降低认知负担
4.2 强制加载型 Skill:qclaw-cron-skill
这是一个强制加载的 Skill,所有涉及定时/提醒/调度的需求都必须先读取它:
markdown
# qclaw-cron-skill/SKILL.md
---
name: qclaw-cron-skill
description: 【强制必读】凡涉及定时/提醒/闹钟/周期执行/cron/schedule/remind 等需求,以及修改/编辑/更新/暂停/恢复/删除/取消推送等已有定时任务的操作,必须读取本 Skill
---
# 定时任务 Skill(强制加载)
## 强制规则
⚠️ **【MANDATORY - MUST LOAD】**
凡涉及以下关键词的场景,**必须**先读取本 SKILL.md 禁止凭记忆猜测参数:
- 定时 / 提醒 / 闹钟
- 周期执行 / 打卡 / 签到
- cron / schedule / remind
- 修改/编辑/更新/暂停/恢复/删除/取消推送
- 改推送目标 / 改推送渠道
## 核心概念
### Job(任务)
定时任务的基本单元,包含:
- `name`:任务名称
- `schedule`:调度规则
- `payload`:任务载荷
- `sessionTarget`:执行目标
### Schedule 类型
- `at`:一次性时间点(ISO-8601)
- `every`:固定间隔(毫秒)
- `cron`:Cron 表达式(本地时区)
### Payload 类型
- `systemEvent`:注入系统事件文本
- `agentTurn`:在独立会话中执行 Agent
### Delivery 模式
- `announce`:输出到聊天频道
- `webhook`:POST 到外部 URL
- `none`:静默执行强制加载型 Skill 的设计要点:
- 醒目警告:description 中用【MANDATORY】等标记
- 覆盖场景穷举:把所有可能触发的场景都列出
- 参数不记忆:明确"禁止凭记忆猜测,必须读取文件"
- 规则优先:规则说明在示例之前
4.3 完整实战 Skill:find-skills
这是一个完整功能型 Skill,包含了触发词设计、工作流程、工具调用:
markdown
# find-skills/SKILL.md
---
name: find-skills
description: 帮助用户发现和安装 Agent 技能。当用户提出类似"我怎么做 X"、"找一个能做 X 的技能"、"有没有可以……的技能"等问题,或表达出扩展功能的需求时触发。
---
# 技能发现与安装
## 触发场景识别
以下任一场景自动触发本 Skill:
| 用户说 | 含义 |
|--------|------|
| "我怎么做 X" | 寻找能做 X 的技能 |
| "找一个能做 X 的技能" | 技能发现 |
| "有没有可以……的技能" | 技能查询 |
| "安装一个 XX 技能" | 技能安装 |
## 工作流程
### Step 1: 理解用户需求
用 `skillhub_install` 工具的 `check_env` 操作快速检查环境状态:
```bash
skillhub_install check_envStep 2: 搜索可用技能
使用 skillhub_install 工具的 install_skill 操作:
- 在线安装:直接调用
install_skill,工具自动处理依赖 - 本地 zip 安装:调用
install_skill_zip并提供 zip 路径
Step 3: 确认安装
返回安装结果和使用说明。
工具接口
| 操作 | 用途 |
|---|---|
check_env | 检查 SkillHub CLI 环境 |
install_cli | 安装 SkillHub CLI |
install_skill | 在线安装指定技能 |
install_skill_zip | 从本地 zip 安装技能 |
## 五、Skill Workshop:Skill 的生命周期管理
QClaw 的 Skill Workshop 提供了一套完整的 Skill 开发、发布、迭代机制。通过 `skill_workshop` 工具管理 Skill 的全生命周期:
### 5.1 生命周期各阶段[创建提案] → [审核中] → [安装使用] → [持续迭代] draft pending live updated
| 状态 | 含义 | 可执行的操作 |
|------|------|------------|
| `draft` | 草稿状态,正在开发 | 继续编辑 |
| `pending` | 提案提交,等待审核 | 审核 / 拒绝 |
| `live` | 已发布,可使用 | 创建更新提案 |
| `updated` | 更新版已发布 | 回滚到旧版 |
### 5.2 skill_workshop 工具接口
```javascript
// 创建新 Skill 提案
skill_workshop({
action: "create",
name: "我的新技能",
description: "简短描述,160字节以内",
proposal_content: "# Skill 内容..."
})
// 更新已有 Skill(创建更新提案)
skill_workshop({
action: "update",
skill_name: "已有技能名",
description: "更新后的描述",
proposal_content: "# 更新后的内容..."
})
// 修订提案(修改 pending 状态的提案)
skill_workshop({
action: "revise",
proposal_id: "proposal_id",
proposal_content: "# 修订后的内容..."
})
// 审核通过:应用到系统
skill_workshop({
action: "apply",
proposal_id: "proposal_id",
reason: "审核通过,同意发布"
})
// 拒绝提案
skill_workshop({
action: "reject",
proposal_id: "proposal_id",
reason: "不符合规范,拒绝发布"
})
// 列出提案
skill_workshop({ action: "list", status: "pending" })
// 检查提案详情
skill_workshop({ action: "inspect", proposal_id: "proposal_id" })5.3 完整开发流程
第1步:构思 Skill
└→ 确定:解决什么问题?触发词是什么?
第2步:创建提案
└→ skill_workshop(action: "create", proposal_content: "...")
第3步:本地开发
└→ 在 workspace/skills/ 下创建 Skill 目录
└→ 编写 SKILL.md + 捆绑资源
└→ 本地测试
第4步:提交审核
└→ skill_workshop(action: "apply", proposal_id: "...")
第5步:发布上线
└→ 审核通过后,Skill 进入 live 状态
└→ 其他用户可通过 skillhub_install 安装
第6步:持续迭代
└→ 发现问题 → 创建 update 提案
└→ 审核通过 → 发布新版本六、Skill 开发最佳实践
6.1 触发词设计原则
精准优先,避免泛化:
yaml
# ❌ 泛化导致误触发
description: "处理文件和文档相关操作"
# ✅ 精准场景覆盖
description: "当用户想要读取、编辑、转换或生成 Word 文档(.docx)时触发"关键词 + 场景组合:
yaml
# 关键词列表
description: "当用户提到以下任一关键词时触发:创建 Word、编辑 docx、生成报告、
生成备忘录、生成信函、Word 文档排版、插入图片到 Word、表格格式化"
# 场景描述
description: "当用户说'帮我写一份报告'、'做个 Word'、'生成一份文档'时触发"6.2 SKILL.md 精简原则
上下文是公共资源,每个 token 都要物有所值。
markdown
# ❌ 冗长说明
这是本 Skill 的完整使用说明。在开始之前,我们需要先理解本 Skill 的设计理念...
(本 Skill 由团队于 2024 年开发,经过多次迭代,目前版本为 2.0...)
# ✅ 精简直接
## 使用流程
1. 确认需求(用户需要哪种文档?)
2. 调用工具处理
3. 返回文件路径"挑战每一行"原则: 写完每段内容后问自己:
- 这段说明 Claude 是否已经知道?(模型内化知识无需重复)
- 10 token 的解释值不值得写在这里?
- 这段信息会在每次调用时用到,还是只在特定场景需要?(后者放 references/)
6.3 错误处理与降级
markdown
## 执行失败时的处理
### 方案A 失败 → 方案B
如果主要方法失败,自动切换到备选方案:
1. 尝试方法 A(如下)
2. 如果报错,使用方法 B
3. 如果仍然失败,返回错误信息给用户
### 常见错误处理
| 错误 | 处理方式 |
|------|---------|
| 文件不存在 | 询问用户文件路径 |
| 格式不支持 | 列出支持格式 |
| 权限不足 | 提示用户授权 |6.4 Skill 间的协作模式
模式1:链式调用
user → Skill A → Skill B → Skill C → 结果markdown
# Skill A 的 SKILL.md
## 工作流程
处理完成后,将结果传递给 `xxx-skill`:
→ 触发条件:需要 XX 处理
→ 使用 `skill_workshop` 或直接描述下一步操作模式2:路由分发
user → Skill Router → Skill A / Skill B / Skill C如前文的 email-skill,作为统一入口分发到下游。
模式3:共享资源
Skill A (references/api.md)
Skill B (references/api.md) ← 共享同一参考文档共享 references/ 目录,通过符号链接或统一资源路径实现。
七、完整实战:开发一个"技术博客文章生成"Skill
7.1 需求分析
目标:开发一个自动为博客生成技术文章的 Skill,封装工作流程和写作规范。
7.2 目录结构
blog-article-generator/
├── SKILL.md
├── scripts/
│ ├── list_articles.sh # 列出已有文章
│ └── update_nav.sh # 更新导航文件
└── references/
├── article_template.md # 文章模板
└── writing_guide.md # 写作规范7.3 SKILL.md 编写
markdown
---
name: blog-article-generator
description: 当用户要求"写一篇博客文章"、"生成技术文章"、"帮我写 XX 的深度解析"时触发。用于为个人技术博客自动生成高质量的前端/全栈技术文章。
---
# 技术博客文章生成 Skill
## 核心原则
1. **选题**:选择尚未覆盖的前端/全栈技术主题(先检查已有文章列表)
2. **深度**:包含原理分析 + 代码示例 + 实战技巧,不是浅尝辄止
3. **格式**:严格遵循模板格式
4. **署名**:末尾添加 `*本文由小虾子 🦐 撰写*`
## 工作流程
### Step 1: 检查已有文章(防止重复)
执行以下命令列出已有文章:
```bash
ls /Users/ljt/Desktop/my-app/L-blog/docs/articles/选择尚未覆盖的主题。如果已有类似主题,选择更细分或更新的角度。
Step 2: 生成文章
使用 references/article_template.md 作为模板,填充高质量内容。
文章结构:
- 标题(
# 标题:技术名 + 深度解析/完全指南) - 引言(为什么重要,解决了什么问题)
- 原理(底层机制)
- 语法/用法(带代码示例)
- 实战技巧(真实场景应用)
- 进阶主题(高级用法、性能优化等)
- 总结
- 署名
Step 3: 保存文章
bash
# 文章路径
/path/to/blog/docs/articles/文件名.md
# 文件名规范:英文小写 + 连字符
# 例如:signal-primitives-deep-dive.mdStep 4: 更新导航
读取 references/article_template.md 中的标题,追加到导航文件:
bash
# 导航文件路径
/path/to/blog/docs/articles.md
# 在对应分类的 `- [标题](/articles/文件名)` 插入Step 5: Git 发布
bash
cd /path/to/blog
git add .
git commit -m "docs: 新增文章《文章标题》"
git push origin main注意:如果 Git push 失败,记录错误但不影响任务完成。
注意事项
- 文章长度:3000~6000 字,深度优先
- 代码示例:必须实际可运行,避免伪代码
- 触发词覆盖:写文章、生成文章、技术文章、深度解析、XX 完全指南
- 发布失败时不重复生成文章(先检查 git status)
### 7.4 references/article_template.md
```markdown
# 【标题】
# 深度解析:XXX
> 【一句话说明解决的问题/核心价值】
## 简介
【为什么重要,背景介绍】
## 核心概念
【基础概念,扫清障碍】
## 工作原理
【底层机制分析,配图(文字描述)】
## 基本用法
【最简单的示例】
## 进阶用法
【复杂场景,真实案例】
## 实战技巧
【生产环境中的最佳实践】
## 常见问题
【FAQ,踩坑记录】
## 总结
【要点回顾,未来展望】
*本文由小虾子 🦐 撰写*八、总结:Skill 开发的核心心法
┌─────────────────────────────────────────────────────┐
│ Skill 开发的本质:用结构化的文档定义"专业能力" │
│ │
│ 触发词(description) → 何时激活 │
│ 工作流程(workflow) → 如何执行 │
│ 捆绑资源(bundled) → 能力扩展 │
│ Workshop(生命周期) → 持续迭代 │
└─────────────────────────────────────────────────────┘三个核心认知:
- Skill 不是代码,是协议:Skill 定义的是"做什么"和"怎么做",具体实现可以委托工具和脚本
- 描述即触发:description 的质量决定 Skill 的激活准确率,要反复打磨触发词
- 精简即效率:SKILL.md 中的每一行都应该包含模型不知道的信息,避免重复模型已有的知识
掌握 Skill 开发,就掌握了 AI 智能体能力扩展的核心杠杆。
本文由小虾子 🦐 撰写