0

OpenClaw Skills 开发完全指南:从零构建你的第一个技能包

2026.06.04 | youres | 29次围观

为什么需要自定义Skills

OpenClaw 的核心竞争力不在于它"能聊天",而在于它"能执行"。这种执行能力就是通过 Skills(技能包)实现的。很多用户停留在"问问问题"阶段,却不知道只需编写一个 SKILL.md 文件,就能让 AI 自动完成文件整理、数据分析、定时任务、API调用等复杂操作。

我第一次意识到 Skills 威力是在一个真实场景中:每天需要从5个Excel文件提取数据、合并、生成报表邮件。手动操作需40分钟,编写 Skill 后,AI 自动完成仅需90秒。这就是 Skills 的价值——把重复流程转化为一句话指令

Skill 的本质:三层渐进式加载机制

第一层:技能发现(始终加载)

OpenClaw 启动时会扫描 skills/ 文件夹,读取每个子文件夹中的 SKILL.md 元数据(name 和 description)。这些信息始终在系统提示中,用于判断用户意图是否匹配该技能。

// 示例:SKILL.md 元数据部分(必须放在文件头部)
---
name: excel-data-processor
description: "处理Excel数据合并与报表生成。当用户提到'合并Excel'、'生成报表'、'数据处理'时触发"
---

第二层:核心指令加载(按需加载)

当 AI 判断需要使用某个 Skill 时,会读取 SKILL.md 的正文内容(元数据之后的所有内容)。这部分包含:

  • 工作流程:分步骤说明如何完成任务
  • 命令示例:具体的命令行操作或API调用
  • 注意事项:常见错误、权限要求、环境依赖

第三层:资源文件加载(深度按需)

如果任务需要执行脚本、读取配置模板、或参考示例文件,AI 会在真正需要时才读取这些文件。这避免了系统提示过长导致模型性能下降。

层级 加载时机 内容示例 Token消耗
第一层(元数据) OpenClaw 启动时 name + description ~50 tokens/Skill
第二层(核心指令) 任务匹配时 SKILL.md 正文 500-2000 tokens
第三层(资源文件) 执行具体步骤时 scripts/ 下的 .js/.py 文件 按实际读取量计算

实战:构建一个"文件自动分类"Skill

场景描述

你的下载文件夹是否经常混乱?图片、文档、压缩包混在一起。我们要构建一个 Skill,让 AI 理解"整理下载文件夹"这句话,并自动执行分类。

第一步:创建 Skill 文件夹结构

skills/
└── file-auto-sorter/
    ├── SKILL.md          # 核心指令文件(必须)
    ├── scripts/
    │   └── sort.js      # 执行脚本
    └── config/
        └── rules.json   # 分类规则配置

第二步:编写 SKILL.md(核心文件)

这是 Skill 的"大脑",决定 AI 如何理解任务、调用哪些工具、按什么顺序执行。

---
name: file-auto-sorter
description: "自动整理文件,按类型分类到子文件夹。触发词:整理文件、文件分类、清理下载文件夹"
---

# 文件自动分类 Skill

## 适用场景
- 下载文件夹混乱,需要按文件类型归类
- 批量重命名文件(按日期/类型前缀)
- 清理重复文件(基于MD5校验)

## 执行流程

### 1. 读取配置
读取 `config/rules.json` 获取分类规则。
如果用户未提供配置文件,使用默认规则(见下方"默认规则"部分)。

### 2. 扫描目标文件夹
使用 Node.js `fs` 模块读取目标文件夹(默认:`~/Downloads`)。
生成文件列表,包含:文件名、扩展名、大小、修改时间、MD5哈希。

### 3. 分类决策
根据 `rules.json` 中的 `extensions` 映射,将每个文件分配到对应类别。
类别包括:Images(图片)、Documents(文档)、Archives(压缩包)、Videos(视频)、Others(其他)。

### 4. 执行移动
对每个文件,执行以下操作:
- 如果目标子文件夹不存在,先创建(使用 `fs.mkdirSync`)
- 使用 `fs.renameSync` 移动文件
- 如果目标位置已存在同名文件,自动重命名(添加 _1, _2 后缀)

### 5. 生成报告
输出Markdown格式的报告,包含:
- 总文件数、已分类文件数、跳过文件数
- 每个类别的文件数量
- 重复文件列表(如果有)

## 默认规则

```json
{
  "Images": {"extensions": [".jpg", ".png", ".gif", ".webp"]},
  "Documents": {"extensions": [".pdf", ".docx", ".txt", ".md"]},
  "Archives": {"extensions": [".zip", ".rar", ".7z"]},
  "Videos": {"extensions": [".mp4", ".avi", ".mov"]}
}
```

## 命令行调用示例

```bash
# 整理下载文件夹(使用默认规则)
node scripts/sort.js --target=~/Downloads

# 整理指定文件夹(自定义规则)
node scripts/sort.js --target=D:/ProjectFiles --config=config/custom-rules.json

# 仅扫描不移动(预览模式)
node scripts/sort.js --target=~/Downloads --dry-run
```

## 注意事项
1. **权限问题**:如果目标文件夹需要管理员权限,脚本会抛出 EPERM 错误。解决方案:右键 OpenClaw →"以管理员身份运行"。
2. **文件占用**:如果文件已被其他程序打开(如Excel文件正在编辑),移动会失败。脚本会自动跳过并记录。
3. **跨磁盘移动**:如果源文件夹和目标文件夹在不同磁盘,`renameSync` 会失败。需使用 `copyFileSync` + `unlinkSync` 组合。
4. **中文文件名**:确保脚本文件使用 UTF-8 编码保存,避免乱码。

## 错误处理
- 如果 `rules.json` 不存在或格式错误,Skill 会自动创建默认配置
- 如果目标文件夹不存在,提示用户并提供创建选项
- 如果移动失败超过3个文件,暂停执行并询问用户是否继续

第三步:编写执行脚本(scripts/sort.js)

SKILL.md 提供了"做什么",脚本解决"具体怎么做"。以下是核心代码框架:

const fs = require('fs');
const path = require('path');
const crypto = require('crypto');

// 读取配置
function loadConfig(configPath) {
  if (!fs.existsSync(configPath)) {
    return getDefaultConfig();
  }
  return JSON.parse(fs.readFileSync(configPath, 'utf-8'));
}

// 计算文件MD5(用于检测重复)
function getFileMD5(filePath) {
  const content = fs.readFileSync(filePath);
  return crypto.createHash('md5').update(content).digest('hex');
}

// 主函数
function sortFiles(targetDir, config) {
  const files = fs.readdirSync(targetDir);
  const report = { total: 0, sorted: 0, skipped: 0, duplicates: [] };
  
  files.forEach(file => {
    const filePath = path.join(targetDir, file);
    if (!fs.statSync(filePath).isFile()) return; // 跳过文件夹
    
    report.total++;
    const ext = path.extname(file).toLowerCase();
    const category = findCategory(ext, config);
    
    if (!category) {
      report.skipped++;
      return;
    }
    
    // 检查重复
    const md5 = getFileMD5(filePath);
    if (report.duplicates.includes(md5)) {
      console.log(`跳过重复文件:${file}`);
      report.skipped++;
      return;
    }
    report.duplicates.push(md5);
    
    // 移动文件
    const targetFolder = path.join(targetDir, category);
    if (!fs.existsSync(targetFolder)) {
      fs.mkdirSync(targetFolder, { recursive: true });
    }
    
    let targetPath = path.join(targetFolder, file);
    if (fs.existsSync(targetPath)) {
      // 重命名逻辑
      let counter = 1;
      while (fs.existsSync(targetPath)) {
        const name = path.parse(file).name;
        const ext = path.parse(file).ext;
        targetPath = path.join(targetFolder, `${name}_${counter}${ext}`);
        counter++;
      }
    }
    
    fs.renameSync(filePath, targetPath);
    report.sorted++;
  });
  
  return report;
}

// 命令行参数解析
const args = process.argv.slice(2).reduce((acc, arg) => {
  const [key, value] = arg.replace('--', '').split('=');
  acc[key] = value;
  return acc;
}, {});

const config = loadConfig(args.config || 'config/rules.json');
const report = sortFiles(args.target || process.env.HOME + '/Downloads', config);

console.log('分类报告:', report);

第四步:测试 Skill

在 OpenClaw 对话框中输入:"帮我整理下载文件夹"

AI 应该会:

  1. 识别到触发词"整理"(匹配 file-auto-sorter 的 description)
  2. 读取 SKILL.md 正文,理解执行流程
  3. 执行 node scripts/sort.js --target=~/Downloads
  4. 返回分类报告

进阶:让 Skill 支持参数化调用

问题场景

上面的 Skill 硬编码了目标文件夹(~/Downloads)。实际使用中,用户可能想说:"整理 D:/ProjectFiles 里的文件"。我们需要让 Skill 支持动态参数提取

解决方案:在 SKILL.md 中添加"参数提取规则"

## 参数提取规则

当用户说"整理 [路径] 里的文件"时,提取路径部分作为 `--target` 参数。

示例:
- 用户输入:"整理 D:/ProjectFiles"
  → 执行:`node scripts/sort.js --target=D:/ProjectFiles`
  
- 用户输入:"整理下载文件夹,按我的规则来"
  → 执行:`node scripts/sort.js --target=~/Downloads --config=config/my-rules.json`

实现原理

OpenClaw 使用 LLM 提取结构化参数。关键在于 SKILL.md 中提供的示例要足够清晰。LLM 会学习示例中的模式,应用到新输入中。

用户输入示例 提取的参数 执行的命令
"整理下载文件夹" target=~/Downloads(默认) node scripts/sort.js --target=~/Downloads
"整理 D:/Photos 里的文件" target=D:/Photos node scripts/sort.js --target=D:/Photos
"整理文件,用我自己的规则" config=config/custom-rules.json node scripts/sort.js --config=config/custom-rules.json

真实案例:我如何为团队构建"日报自动生成"Skill

背景

团队要求每天下班前提交日报(工作内容+明日计划+遇到的问题)。但大家经常忘记,或者写得很敷衍。我构建了一个 Skill,让 AI 自动:

  1. 读取今天的所有 Git 提交记录
  2. 读取 Slack/飞书中的今日消息(关键词匹配工作相关)
  3. 生成结构化日报草稿
  4. 询问用户补充"遇到的问题"(这部分 AI 无法自动获取)
  5. 写入到团队共享的 Markdown 文件

核心代码片段(SKILL.md 摘要)

## 执行步骤

1. **读取 Git 日志**:
   执行 `git log --since="today 00:00" --pretty=format:"%h - %s (%an)"`
   如果没有提交,记录为"今日无代码提交"

2. **读取聊天记录**:
   调用 Slack API(需提前配置 OAuth Token)
   搜索今日消息,过滤掉"你好"、"吃饭了吗"等非工作内容

3. **生成日报草稿**:
   使用以下模板:
   ```
   ## 今日工作
   - [从Git日志提取]
   - [从聊天记录提取的关键讨论]
   
   ## 明日计划
   - [基于今日未完成工作,AI推测]
   
   ## 遇到的问题
   - [等待用户补充]
   ```

4. **询问用户补充**:
   问:"今日工作是否有遇到阻碍或问题?有的话请补充,没有请回复'无'"

5. **写入文件**:
   写入到 `~/team-daily-reports/YYYY-MM-DD-md5(user).md`

效果

  • 提交率:从60%提升到95%(AI自动提醒+生成草稿)
  • 质量:日报内容更具体(有Git提交哈希、有讨论要点)
  • 时间成本:从手动写10分钟,降到复核2分钟

发布与共享你的 Skill

为什么应该共享?

OpenClaw 社区还处在早期阶段,优质 Skills 非常稀缺。如果你构建了一个好用的 Skill,可以通过这些渠道共享:

  • GitHub:创建开源仓库,附上详细 README 和使用示例
  • OpenClaw 社区论坛:发布 Skill 介绍帖,附截图和视频演示
  • 技术博客:写一篇文章详细介绍设计思路(就像本文这样)

打包规范

如果你希望其他人能直接安装你的 Skill,建议遵循以下目录结构:

my-skill/
├── SKILL.md          # 核心文件(必须)
├── package.json      # 如果依赖npm包
├── requirements.txt  # 如果依赖Python包
├── scripts/          # 执行脚本
├── config/           # 配置文件模板
├── examples/         # 使用示例(截图/视频)
└── README.md         # 安装和使用说明

内链资源推荐

常见问题与解决方案

Q1:Skill 没有被触发(AI 忽略了我的 SKILL.md)

原因:description 字段写得不清晰,导致 AI 无法将用户意图与 Skill 匹配。

解决

  • 在 description 中加入同义词和变体表达,如:"整理文件、文件分类、文件归档、清理文件夹"
  • 使用动词+名词结构,避免抽象描述
  • 测试:在对话框输入不同的触发语,观察 AI 是否加载该 Skill(查看系统提示中是否包含该 Skill 的内容)

Q2:脚本执行失败,但手动运行正常

原因:OpenClaw 运行环境与你手动运行脚本的环境可能不同(不同的 Node.js 版本、不同的 PATH、不同的当前工作目录)。

解决

  1. 在 SKILL.md 中添加"环境要求"部分,明确说明需要的 Node.js 版本、依赖包
  2. 在脚本开头添加环境检测代码:
    // 检测 Node.js 版本
    if (process.version < 'v18.0.0') {
      console.error('需要 Node.js v18+ 才能运行此脚本');
      process.exit(1);
    }
    
    // 检测依赖包
    try {
      require('some-package');
    } catch (e) {
      console.error('缺少依赖包,请运行:npm install some-package');
      process.exit(1);
    }
    
  3. 使用绝对路径,避免相对路径导致的文件找不到错误

Q3:如何让 Skill 支持多语言?

方案:在 SKILL.md 的 description 中加入多语言触发词。例如:

description: "文件分类工具。触发词(中文):整理文件、文件分类。触发词(英文):sort files, organize files, clean up folder"

AI 会根据用户使用的语言,自动匹配对应的描述部分。

总结与下一步

OpenClaw Skills 开发的核心思想是渐进式披露:元数据始终加载(轻量),核心指令按需加载(中量),资源文件深度按需(重量)。遵循这个原则,你就能构建出既强大又高效的 Skill。

下一步建议:

  1. 从简单 Skill 开始:先做一个"定时提醒"Skill(调用系统通知API)
  2. 参考优秀案例:阅读 OpenClaw 官方 Skills 仓库中的代码
  3. 加入社区:在 Discord/论坛上分享你的 Skill,获取反馈

记住:好的 Skill 不是"功能多",而是"意图匹配准"。描述清楚你的 Skill 能做什么、什么时候用,比堆砌功能清单更重要。

版权声明

本文仅代表个人观点。
本文系AI辅助作者原创,未经许可,转载请保留原文链接。

发表评论