0

OpenClaw 技能开发完全指南:从零编写你的第一个Skill

2026.05.20 | youres | 13次围观

为什么大部分OpenClaw用户永远在用别人的技能,而你可以通过本文学会自己写

我接触OpenClaw快半年了,观察到一个有趣现象:90%的用户只会安装和使用别人写好的技能(Skill),遇到特殊需求就到处求人。剩下9%的人会改改现成技能的参数,只有不到1%的人真正从零写过自己的Skill。这个比例跟Python生态很像——大多数人用现成库,少数人写自己的工具包。

但OpenClaw的技能开发比你想的简单得多。我第一次写Skill是因为需要一个"每天自动备份特定文件夹到网盘"的功能,翻遍SkillHub都没找到合适的。花了2小时看完官方文档,又花了3小时写出第一个能用的版本,中间踩了十几个坑。这篇文章就是把那十几个坑全部列出来,让你少走弯路。

OpenClaw技能的本质:一个带SKILL.md的文件夹

很多人被"开发"这个词吓到了。其实OpenClaw的技能本质上就是一个文件夹 + 一个SKILL.md描述文件 + 若干脚本。跟我来拆解一个最基础的技能结构:

my-first-skill/                    ← 技能文件夹(名字随便取)
├── SKILL.md                       ← 必须有的描述文件(OpenClaw靠这个识别技能)
├── scripts/
│   └── main.cjs                   ← 核心执行脚本(.cjs扩展名,CommonJS格式)
├── config.json                    ← 可选:配置文件
└── README.md                     ← 可选:给人看的使用说明

就这么简单。不需要编译,不需要打包,不需要学新的DSL(领域特定语言)。skillhub install的时候,OpenClaw就是把这个文件夹复制到~/.qclaw/skills/目录下,然后读取SKILL.md里的元数据。

SKILL.md:OpenClaw识别技能的唯一入口

SKILL.md有严格的格式要求,这是我最开始踩的第一个坑。它必须有frontmatter(开头的---分隔符之间的部分),OpenClaw靠这个判断"这是不是一个合法技能"。一个最小化的SKILL.md是这样的:

---
name: backup-folder
description: "自动备份指定文件夹到网盘"
metadata:
  openclaw:
    emoji: "📦"
---

# 文件夹自动备份技能

## 功能说明
自动将指定文件夹压缩并上传到配置好的网盘。

## 使用方法
在OpenClaw中说:"帮我备份D:\\Projects文件夹"

## 依赖要求
- 需要安装7-Zip或WinRAR
- 需要配置网盘API Token

这里有三个关键点:

  • name字段:只能包含小写字母、数字、连字符,不能含空格或中文。这是技能的唯一ID,skillhub install时用的就是它。
  • description字段:OpenClaw的Agent会读这个,用来判断"用户的需求是否应该触发这个技能"。写得好不好直接影响触发准确率。我建议用"动词+名词"结构,比如"自动备份指定文件夹到网盘",而不是名词短语"文件夹备份工具"。
  • metadata.openclaw.emoji:纯装饰,但用户选技能时会看到,建议选个有意义的emoji。

第一个实战:写一个"每日科技新闻摘要"技能

光讲理论太虚,跟我一步步写一个真正能用的技能。需求是:每天早上8点,自动搜索昨天的科技新闻,生成200字摘要,发送到我的邮箱

第一步:创建技能文件夹和SKILL.md

// ~/.qclaw/skills/daily-tech-news/SKILL.md
---
name: daily-tech-news
description: "每日自动搜索并摘要科技新闻,支持邮件发送"
metadata:
  openclaw:
    emoji: "📰"
---

# 每日科技新闻摘要技能

## 触发方式
用户说:"订阅科技新闻" 或 "每天8点给我发科技新闻摘要"

## 工作流程
1. 调用online-search技能搜索"最新科技新闻"(freshness=24h)
2. 提取前5条新闻标题和摘要
3. 用大模型生成200字左右的综合摘要
4. 通过邮件发送(或输出到聊天窗口)

## 配置
在config.json中配置收件邮箱地址。

第二步:写核心执行脚本scripts/fetch-news.cjs

这是最关键的的部分。OpenClaw的技能脚本必须用.cjs扩展名(CommonJS格式),不能用.mjs(ES Module)。我第一次写的时候用了import语法,调试了半小时才发现问题。

// ~/.qclaw/skills/daily-tech-news/scripts/fetch-news.cjs
const { execSync } = require('child_process');
const fs = require('fs');
const path = require('path');

/**
 * 调用online-search技能搜索最新科技新闻
 * 返回搜索结果的message字段(已格式化的文本)
 */
function searchTechNews() {
  const scriptPath = path.join(
    process.env.APP_PATH || 'C:\\Program Files\\QClaw\\resources\\openclaw\\config\\skills',
    'online-search',
    'scripts',
    'prosearch.cjs'
  );
  
  // 调用搜索脚本,freshness=24h表示搜索最近24小时
  // 使用字符串拼接,避免使用模板字符串
  const cmd = 'node "' + scriptPath + '" --keyword=最新科技新闻 --freshness=24h';
  const result = execSync(cmd, { encoding: 'utf-8', timeout: 30000 });
  
  return JSON.parse(result);
}

/**
 * 主函数
 */
function main() {
  try {
    console.log('🔍 开始搜索最新科技新闻...');
    const searchResult = searchTechNews();
    
    if (!searchResult.success) {
      console.error('❌ 搜索失败:', searchResult.message);
      process.exit(1);
    }
    
    console.log('✅ 搜索成功,结果:');
    console.log(searchResult.message); // 直接输出格式化的搜索结果
    
    // 实际部署时,这里会调用邮件发送逻辑
    // 参考email-skill或public-skill的写法
    
  } catch (error) {
    console.error('❌ 执行出错:', error.message);
    process.exit(1);
  }
}

main();

这段代码有几个值得注意的细节:

  • 脚本路径问题:online-search技能的脚本路径是硬编码的(C:\\Program Files\\...),这是第二个坑。正确做法是用process.env.APP_PATH动态获取,但Windows下这个环境变量不一定有。我最后的方案是在config.json里让用户手动配置路径。
  • execSync的timeout:搜索脚本可能因为网络问题卡住,必须设timeout。我设的30秒,实际发现大部分情况下5秒内就能返回。
  • 输出格式:脚本的输出会被Agent捕获,所以直接用console.log输出格式化的文本即可,不需要返回JSON(除非你要在脚本间传递结构化数据)。
  • 避免模板字符串:在技能脚本中,尽量使用字符串拼接('string' + variable + 'string')而不是模板字符串(`string ${variable} string`),可以避免很多转义问题。在SKILL.md的代码示例中展示时,也建议用字符串拼接的写法。

第三步:配置Cron定时任务

技能写好了,怎么让它每天8点自动执行?答案是配合OpenClaw的Cron系统。在SKILL.md里加上这段:

## 定时任务配置

用户说"订阅科技新闻"时,Agent应该执行以下操作:

1. 调用 `openclaw cron add` 创建定时任务
2. 任务配置:
   - 名称:每日科技新闻摘要
   - 时间:每天 08:00(Asia/Shanghai时区)
   - 执行命令:`node ~/.qclaw/skills/daily-tech-news/scripts/fetch-news.cjs`
   - 输出渠道:邮件(从config.json读取邮箱地址)

3. 示例cron表达式:`0 8 * * *`

我实际测试时发现,技能本身不应该直接操作Cron,应该由Agent根据用户指令来创建Cron任务。技能的职责是"提供执行脚本",而不是"自己把自己注册成定时任务"。这个职责分离很重要,否则技能之间会互相冲突。

调试技能的5个实用技巧

写技能最痛苦的不是写代码,是调试。以下是我踩坑3周后总结的调试技巧:

技巧1:用openclaw skill test命令快速测试

# 测试技能是否被OpenClaw正确识别
openclaw skill list | findstr daily-tech-news

# 手动执行技能脚本,看输出是否正确
node ~/.qclaw/skills/daily-tech-news/scripts/fetch-news.cjs

# 查看OpenClaw的技能加载日志
openclaw gateway logs --tail 50

技巧2:在SKILL.md里写清楚的"触发词"

Agent靠SKILL.md的description字段判断"用户这句话应该触发哪个技能"。如果你发现技能总是不触发,90%是因为description写得太模糊。对比一下:

不好的description好的description
"新闻摘要工具""每日自动搜索并摘要科技新闻,支持邮件发送"
"备份工具""自动备份指定文件夹到网盘,支持7-Zip压缩"
"聊天记录导出""导出OpenClaw会话记录为Markdown或PDF格式"

技巧3:用process.env读取配置,不要硬编码

我第一个技能把邮箱地址、API Key都硬编码在脚本里,结果换个电脑就跑不起来了。正确做法是在技能目录下创建config.json:

// ~/.qclaw/skills/daily-tech-news/config.json
{
  "email": "your@email.com",
  "news_sources": ["科技新闻", "AI新闻", "半导体新闻"],
  "max_news_count": 5,
  "summary_length": 200
}

然后在脚本里读取:

const config = JSON.parse(fs.readFileSync(path.join(__dirname, '../config.json'), 'utf-8'));
console.log('📧 收件邮箱:' + config.email);

技巧4:处理Windows路径的坑

OpenClaw同时支持Windows和macOS,但路径分隔符不一样。我建议在脚本里用path.join()而不是字符串拼接:

// ❌ 错误:Windows下会出错
const scriptPath = __dirname + '/../scripts/main.cjs';

// ✅ 正确:跨平台兼容
const scriptPath = path.join(__dirname, '..', 'scripts', 'main.cjs');

技巧5:输出要有"视觉层次"

Agent会把脚本的console.log输出展示给用户。如果你的输出是一大坨纯文本,用户会觉得你的技能很low。学会用emoji和分段:

// ❌ 不好的输出
console.log('开始搜索');
console.log('搜索完成,找到10条结果');
console.log('生成摘要...');
console.log('摘要:AI领域今日发生重大突破...');

// ✅ 好的输出
console.log('🔍 正在搜索最新科技新闻...');
console.log('✅ 搜索完成,找到 10 条结果\n');
console.log('📝 正在生成摘要...\n');
console.log('📰 今日科技新闻摘要:');
console.log('─'.repeat(50));
console.log('AI领域今日发生重大突破...');
console.log('─'.repeat(50));

发布和分享你的技能

技能写好了,怎么分享给社区?OpenClaw的技能分发通过SkillHub完成。打包命令:

# 在技能目录下执行
cd ~/.qclaw/skills/daily-tech-news
npm pack .  # 生成 daily-tech-news-1.0.0.tgz

# 或者手动打包成zip
# 确保SKILL.md在压缩包的根目录,而不是在子文件夹里

上传到SkillHub后,别人就可以通过skillhub install daily-tech-news安装你的技能了。我建议在上架前检查以下几项:

  • SKILL.md的description是否清晰?
  • 是否提供了使用示例(最好带截图)?
  • 是否列出了依赖要求(比如需要安装7-Zip)?
  • 是否处理了常见错误(比如网络超时、文件路径不存在)?

进阶:技能之间的组合和编排

OpenClaw最强大的地方在于技能可以互相调用。比如我写了一个"科技新闻摘要"技能,又写了一个"微信消息推送"技能,然后在Cron任务里把两者串起来:

// 每天8点,先抓取新闻,再推送到微信
// Cron任务的执行脚本
const { execSync } = require('child_process');

// 第一步:抓取新闻
const news = execSync('node ~/.qclaw/skills/daily-tech-news/scripts/fetch-news.cjs', { encoding: 'utf-8' });

// 第二步:推送到微信(调用另一个技能)
// 注意:传递给命令行参数时,需要转义双引号
const escapedNews = news.replace(/"/g, '\\"');
const pushCmd = 'node ~/.qclaw/skills/wechat-pusher/scripts/push.cjs --message "' + escapedNews + '"';
execSync(pushCmd, { encoding: 'utf-8' });

console.log('✅ 新闻已推送到微信');

这种"技能编排"的思路,让你可以用简单的技能组合出复杂的工作流。这也是OpenClaw跟其他AI助手最大的区别:它不只是聊天,它是真正可编排的自动化平台

写在最后:从用户到开发者的跨越

学会写OpenClaw技能,本质上是在学"怎么让AI帮你干活"。你不再是一个被动的工具使用者,而是一个主动的工作流设计者。我现在的日常是:早上让OpenClaw自动抓取行业新闻、生成摘要、推送到我的Notion;中午让OpenClaw自动整理上午的聊天记录、提取待办事项、更新到TAPD;晚上让OpenClaw自动备份当天的工作文件到网盘。

这些自动化流程,每一个都是一个小技能。它们单个看起来很简单,但组合起来,每天帮我节省至少2小时。这2小时,我可以用来学习新东西、陪伴家人、或者单纯发呆——反正比手动做那些重复劳动有意义得多。

如果你已经看到这里,说明你对OpenClaw技能开发是真的感兴趣。不妨现在就打开PowerShell,输入mkdir ~/.qclaw/skills/my-first-skill,然后按照本文的步骤,写出你的第一个技能。记住:完成比完美重要,先跑起来,再慢慢优化

版权声明

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

发表评论
883文章数 0评论数
作者其它文章