Skip to content

OpenClaw 技能开发指南

本章节详细介绍如何开发自定义技能(Skills),扩展 OpenClaw 智能体能力。 前置知识:了解 OpenClaw 基本概念、工具系统和 JSON 格式。 技能加载优先级:工作区技能 > 本地技能 > 捆绑默认技能。


1. 技能系统概述

1.1 什么是技能

技能(Skills)是扩展 OpenClaw 智能体功能的模块化组件:

  • 自定义工具定义
  • 复杂工作流封装
  • 外部服务集成
  • 智能体行为指令

1.2 技能结构

1.3 技能目录结构

~/.openclaw/workspace/skills/
└── <skill-name>/
    ├── SKILL.md          # 技能定义(必需)
    ├── tools/             # 工具实现目录
    │   ├── index.ts      # 工具入口
    │   └── *.ts          # 其他工具文件
    ├── references/        # 参考资料
    │   └── *.md
    └── assets/           # 静态资源
        └── *

2. SKILL.md 格式详解

2.1 完整结构

markdown
# <技能名称>

<技能描述,说明这个技能做什么。>

## Tools

```json
[
  {
    "name": "tool_name",
    "description": "工具描述",
    "parameters": {
      "type": "object",
      "properties": {
        "param1": {
          "type": "string",
          "description": "参数描述"
        }
      },
      "required": ["param1"]
    },
    "function": "async (params) => { ... }"
  }
]

Usage

<使用说明和示例。>

Examples

<更多使用示例。>


### 2.2 工具定义详解

```json
{
  "name": "get_weather",           // 工具唯一名称
  "description": "获取指定城市的天气",  // AI 看到描述决定是否调用
  "parameters": {                   // JSON Schema 参数定义
    "type": "object",
    "properties": {
      "city": {
        "type": "string",
        "description": "城市名称(支持中英文)"
      },
      "format": {
        "type": "string",
        "description": "返回格式:celsius(默认)或 fahrenheit",
        "enum": ["celsius", "fahrenheit"]
      }
    },
    "required": ["city"]
  },
  "function": "async ({ city, format = 'celsius' }) => { ... }"
}

2.3 工具函数签名

工具函数支持两种签名风格:

javascript
// 风格 1:解构参数(推荐)
async ({ param1, param2 }) => {
  // 函数体
  return result;
}

// 风格 2:完整参数对象
async (params) => {
  const { param1, param2 } = params;
  // 函数体
  return result;
}

3. 技能开发示例

3.1 简单天气技能

创建 ~/.openclaw/workspace/skills/weather/SKILL.md

markdown
# Weather 天气查询技能

获取指定城市的当前天气信息和天气预报。

## Tools

```json
[
  {
    "name": "get_current_weather",
    "description": "获取指定城市的当前天气,包括温度、湿度、风速等",
    "parameters": {
      "type": "object",
      "properties": {
        "city": {
          "type": "string",
          "description": "城市名称(中文或英文)"
        },
        "country": {
          "type": "string",
          "description": "国家代码,如 CN、US"
        }
      },
      "required": ["city"]
    },
    "function": "async ({ city, country = 'CN' }) => {\n  const response = await fetch(`https://api.weather.com/v3/wx/conditions/current?city=${encodeURIComponent(city)}&country=${country}&apikey=${process.env.WEATHER_API_KEY}`);\n  const data = await response.json();\n  return {\n    city: data.location,\n    temperature: data.temp,\n    humidity: data.humidity,\n    description: data.weather\n  };\n}"
  },
  {
    "name": "get_forecast",
    "description": "获取指定城市未来几天的天气预报",
    "parameters": {
      "type": "object",
      "properties": {
        "city": {
          "type": "string",
          "description": "城市名称"
        },
        "days": {
          "type": "number",
          "description": "预报天数(1-7)",
          "minimum": 1,
          "maximum": 7
        }
      },
      "required": ["city", "days"]
    },
    "function": "async ({ city, days }) => {\n  const response = await fetch(`https://api.weather.com/v3/wx/forecast/daily?city=${encodeURIComponent(city)}&days=${days}&apikey=${process.env.WEATHER_API_KEY}`);\n  const data = await response.json();\n  return {\n    city: data.location,\n    forecasts: data.forecast.map(f => ({\n      date: f.date,\n      high: f.highTemp,\n      low: f.lowTemp,\n      condition: f.condition\n    }))\n  };\n}"
  }
]

Usage

用户:今天北京天气怎么样?
助手:调用 get_current_weather({ city: "北京" })

Environment Variables

需要设置以下环境变量:

  • WEATHER_API_KEY:Weather API 密钥

### 3.2 Git 操作技能

创建 `~/.openclaw/workspace/skills/git-operations/SKILL.md`:

```markdown
# Git Operations Git 操作技能

封装常用 Git 操作,简化代码管理。

## Tools

```json
[
  {
    "name": "git_status",
    "description": "查看 Git 仓库状态,显示已修改、已暂存、待提交的文件",
    "parameters": {
      "type": "object",
      "properties": {
        "path": {
          "type": "string",
          "description": "仓库路径,默认当前目录"
        }
      }
    },
    "function": "async ({ path = '.' }) => {\n  const { stdout } = await exec(`git -C ${path} status --short`);\n  return stdout || '工作区干净';\n}"
  },
  {
    "name": "git_commit",
    "description": "提交所有更改到 Git 仓库",
    "parameters": {
      "type": "object",
      "properties": {
        "message": {
          "type": "string",
          "description": "提交信息"
        },
        "path": {
          "type": "string",
          "description": "仓库路径"
        }
      },
      "required": ["message"]
    },
    "function": "async ({ message, path = '.' }) => {\n  await exec(`git -C ${path} add .`);\n  const { stdout } = await exec(`git -C ${path} commit -m ${JSON.stringify(message)}`);\n  return stdout;\n}"
  },
  {
    "name": "git_log",
    "description": "查看 Git 提交历史",
    "parameters": {
      "type": "object",
      "properties": {
        "path": {
          "type": "string",
          "description": "仓库路径"
        },
        "limit": {
          "type": "number",
          "description": "显示最近 N 条记录",
          "default": 10
        }
      }
    },
    "function": "async ({ path = '.', limit = 10 }) => {\n  const { stdout } = await exec(`git -C ${path} log --oneline -n ${limit}`);\n  return stdout;\n}"
  }
]

Usage

用户:查看当前仓库状态
助手:调用 git_status()

用户:提交所有更改
助手:调用 git_commit({ message: "feat: 添加新功能" })

3.3 数据库查询技能

markdown
# Database Query 数据库查询技能

执行只读数据库查询,返回格式化结果。

## Tools

```json
[
  {
    "name": "db_query",
    "description": "执行 SELECT 查询(仅支持查询,禁止修改数据)",
    "parameters": {
      "type": "object",
      "properties": {
        "sql": {
          "type": "string",
          "description": "SQL SELECT 语句"
        },
        "limit": {
          "type": "number",
          "description": "最大返回行数",
          "default": 100
        }
      },
      "required": ["sql"]
    },
    "function": "async ({ sql, limit = 100 }) => {\n  // 安全检查:只允许 SELECT\n  const normalized = sql.trim().toUpperCase();\n  if (!normalized.startsWith('SELECT')) {\n    throw new Error('只允许执行 SELECT 查询');\n  }\n  \n  // 参数化查询防止注入\n  const { stdout } = await exec(`psql -t -c ${JSON.stringify(sql + ' LIMIT ' + limit)}`);\n  return stdout;\n}"
  }
]

4. 高级技能开发

4.1 带状态管理的技能

对于需要维护状态的技能,可以使用文件系统存储状态:

markdown
# Todo List 待办事项技能

管理待办事项列表。

## Tools

```json
[
  {
    "name": "todo_add",
    "description": "添加待办事项",
    "parameters": {
      "type": "object",
      "properties": {
        "task": {
          "type": "string",
          "description": "待办事项内容"
        },
        "priority": {
          "type": "string",
          "description": "优先级",
          "enum": ["low", "medium", "high"]
        }
      },
      "required": ["task"]
    },
    "function": "async ({ task, priority = 'medium' }) => {\n  const fs = require('fs');\n  const path = process.env.OPENCLAW_STATE_DIR + '/todo.json';\n  let todos = [];\n  if (fs.existsSync(path)) {\n    todos = JSON.parse(fs.readFileSync(path, 'utf8'));\n  }\n  const newTodo = {\n    id: Date.now(),\n    task,\n    priority,\n    done: false,\n    created: new Date().toISOString()\n  };\n  todos.push(newTodo);\n  fs.writeFileSync(path, JSON.stringify(todos, null, 2));\n  return newTodo;\n}"
  },
  {
    "name": "todo_list",
    "description": "列出所有待办事项",
    "parameters": {
      "type": "object",
      "properties": {}
    },
    "function": "async () => {\n  const fs = require('fs');\n  const path = process.env.OPENCLAW_STATE_DIR + '/todo.json';\n  if (!fs.existsSync(path)) return [];\n  const todos = JSON.parse(fs.readFileSync(path, 'utf8'));\n  return todos.filter(t => !t.done);\n}"
  },
  {
    "name": "todo_done",
    "description": "标记待办事项为已完成",
    "parameters": {
      "type": "object",
      "properties": {
        "id": {
          "type": "number",
          "description": "待办事项 ID"
        }
      },
      "required": ["id"]
    },
    "function": "async ({ id }) => {\n  const fs = require('fs');\n  const path = process.env.OPENCLAW_STATE_DIR + '/todo.json';\n  let todos = JSON.parse(fs.readFileSync(path, 'utf8'));\n  const todo = todos.find(t => t.id === id);\n  if (!todo) throw new Error('待办事项不存在');\n  todo.done = true;\n  todo.completed = new Date().toISOString();\n  fs.writeFileSync(path, JSON.stringify(todos, null, 2));\n  return todo;\n}"
  }
]

4.2 异步任务技能

对于长时间运行的任务,使用任务队列模式:

markdown
# Long Task 长任务技能

处理需要后台执行的长时间任务。

## Tools

```json
[
  {
    "name": "task_submit",
    "description": "提交长时间任务到队列",
    "parameters": {
      "type": "object",
      "properties": {
        "taskType": {
          "type": "string",
          "description": "任务类型"
        },
        "params": {
          "type": "object",
          "description": "任务参数"
        }
      },
      "required": ["taskType"]
    },
    "function": "async ({ taskType, params }) => {\n  const fs = require('fs');\n  const path = process.env.OPENCLAW_STATE_DIR + '/tasks';\n  if (!fs.existsSync(path)) fs.mkdirSync(path, { recursive: true });\n  \n  const task = {\n    id: Date.now().toString(36) + Math.random().toString(36).substr(2),\n    taskType,\n    params,\n    status: 'pending',\n    created: new Date().toISOString()\n  };\n  \n  fs.writeFileSync(\\`\\${path}/\\${task.id}.json\\`, JSON.stringify(task));\n  return { taskId: task.id, status: 'queued' };\n}"
  },
  {
    "name": "task_status",
    "description": "查询任务状态",
    "parameters": {
      "type": "object",
      "properties": {
        "taskId": {
          "type": "string",
          "description": "任务 ID"
        }
      },
      "required": ["taskId"]
    },
    "function": "async ({ taskId }) => {\n  const fs = require('fs');\n  const path = \\`\\${process.env.OPENCLAW_STATE_DIR}/tasks/\\${taskId}.json\\`;\n  if (!fs.existsSync(path)) throw new Error('任务不存在');\n  return JSON.parse(fs.readFileSync(path, 'utf8'));\n}"
  }
]

5. 技能发布与分享

5.1 打包技能

技能目录结构:

my-skill/
├── SKILL.md
├── README.md           # 使用说明
├── package.json       # 依赖定义(如有)
└── references/        # 参考文档
    └── api.md

5.2 技能市场 (ClaWHub)

bash
# 发布技能到 ClaWHub
openclaw skills publish ./my-skill

# 从 ClaWHub 安装
openclaw skills install <skill-name>

# 搜索技能
openclaw skills search <keyword>

5.3 技能审核清单

发布前检查:

  • [ ] SKILL.md 格式正确
  • [ ] 工具描述清晰
  • [ ] 参数定义完整
  • [ ] 示例足够
  • [ ] 无硬编码敏感信息
  • [ ] 依赖已声明
  • [ ] README 完整

6. 技能调试

6.1 本地测试

bash
# 测试工具
openclaw tools test exec --command "echo 'test'"

# 查看技能加载日志
openclaw gateway --verbose | Select-String "skill"

6.2 模拟调用

javascript
// 在 Node.js 中模拟工具调用
const skill = require('./skills/weather/SKILL.md');
const fn = eval('(' + skill.tools[0].function + ')');
const result = await fn({ city: '北京' });
console.log(result);

7. 技能最佳实践

7.1 设计原则

原则说明
单一职责每个技能只做一件事
清晰命名工具名要清晰表达功能
完整文档描述、参数、示例都要有
错误处理正确处理并返回错误信息
幂等设计重复调用不会产生副作用

7.2 安全建议

markdown
## Security

此技能需要的权限:
- 网络访问(调用外部 API)
- 文件系统读取(缓存)
- 文件系统写入(状态存储)

此技能**不**需要的权限:
- exec 命令执行
- 系统配置修改

7.3 性能考虑

  • 避免在工具函数中执行长时间操作
  • 使用流式处理大文件
  • 实施超时机制
  • 缓存常用结果

8. 技能模板

8.1 最小模板

markdown
# My Skill

这是一个示例技能。

## Tools

```json
[
  {
    "name": "hello_world",
    "description": "返回问候语",
    "parameters": {
      "type": "object",
      "properties": {}
    },
    "function": "async () => 'Hello, World!'"
  }
]

Usage

用户:打招呼
助手:调用 hello_world()

### 8.2 完整模板

```markdown
# <Skill Name>

<详细描述这个技能做什么,什么时候应该使用。>

## Prerequisites

- 环境变量:`API_KEY` - API 密钥
- 依赖:无需额外依赖

## Tools

```json
[
  {
    "name": "tool_name",
    "description": "<清晰描述工具功能>",
    "parameters": {
      "type": "object",
      "properties": {
        "param1": {
          "type": "<string|number|boolean|object|array>",
          "description": "<参数描述>"
        }
      },
      "required": ["param1"]
    },
    "function": "async ({ param1 }) => {\n  // 实现代码\n}"
  }
]

Usage Examples

Example 1

用户:<场景描述>
助手:调用 tool_name({ param1: 'value' })

Example 2

用户:<场景描述>
助手:调用 tool_name({ param1: 'value' })

Error Handling

错误原因处理方式
API 错误外部 API 调用失败返回错误信息,提示重试
参数错误参数格式不正确返回参数要求说明
权限错误缺少必要权限提示配置环境变量

See Also


---

## 延伸阅读

- [官方技能示例](https://github.com/VoltAgent/awesome-openclaw-skills)
- [技能参考](../index)
- [工具系统](../index)

为前端工程师打造 · 基于 VitePress 构建