OpenClaw 进阶:打造专属技能生态系统
·
基础部署只是开始,真正的威力在于自定义技能。本文教你如何为 OpenClaw 开发专属技能,打造属于自己的 AI 助手生态。
🎯 你将学到什么
- OpenClaw 技能系统架构
- 如何开发自定义技能
- 技能市场和分享
- 实战案例:开发 5 个实用技能
- 技能调试和测试
- 发布到 Clawhub 技能市场
前置知识: 需要先阅读 OpenClaw 基础教程
一、OpenClaw 技能系统架构
1.1 什么是技能?
技能 = 工具 + 文档 + 配置
skill/
├── SKILL.md # 技能文档(必需)
├── tools.py # 工具实现(Python)
├── tools.js # 工具实现(JavaScript)
├── config.yaml # 配置文件(可选)
├── assets/ # 资源文件(可选)
└── examples/ # 示例代码(可选)
1.2 技能生命周期
┌─────────────────────────────────────┐
│ 开发技能 │
│ (编写 SKILL.md + tools) │
└──────────────┬──────────────────────┘
│
▼
┌─────────────────────────────────────┐
│ 测试技能 │
│ (本地测试 + 调试) │
└──────────────┬──────────────────────┘
│
▼
┌─────────────────────────────────────┐
│ 发布技能 │
│ (上传到 Clawhub) │
└──────────────┬──────────────────────┘
│
▼
┌─────────────────────────────────────┐
│ 使用技能 │
│ (openclaw skills install) │
└─────────────────────────────────────┘
二、开发第一个技能
2.1 需求分析
目标: 开发一个天气查询技能
功能:
- 查询指定城市的天气
- 支持多日天气预报
- 自动识别用户位置
2.2 创建技能目录
# 创建技能目录
mkdir -p ~/.openclaw/workspace/skills/weather-pro
cd ~/.openclaw/workspace/skills/weather-pro
2.3 编写 SKILL.md
---
name: weather-pro
description: 专业天气查询技能,支持全球城市和多日预报
version: 1.0.0
author: 你的名字
tags: [weather, forecast, location]
---
# Weather Pro - 专业天气查询
专业的天气查询技能,支持全球城市和多日天气预报。
## 功能特性
- ✅ 查询当前天气
- ✅ 7 天天气预报
- ✅ 自动识别用户位置
- ✅ 支持全球主要城市
- ✅ 温度、湿度、风速等详细信息
## 工具列表
### get_current_weather
查询指定城市的当前天气。
**参数:**
- `city` (string, 必需): 城市名称(中文或英文)
- `unit` (string, 可选): 温度单位(celsius/fahrenheit),默认 celsius
**返回:**
```json
{
"city": "北京",
"temperature": 15,
"unit": "celsius",
"condition": "晴",
"humidity": 45,
"wind_speed": 12
}
示例:
用户: 北京今天天气怎么样?
助手: [调用 get_current_weather(city="北京")]
输出: 北京今天晴,温度 15°C,湿度 45%,风速 12 km/h
get_forecast
查询指定城市的多日天气预报。
参数:
city(string, 必需): 城市名称days(int, 可选): 预报天数(1-7),默认 3
返回:
{
"city": "北京",
"forecast": [
{
"date": "2026-02-23",
"temperature_high": 18,
"temperature_low": 8,
"condition": "多云"
]
}
示例:
用户: 北京未来三天天气
助手: [调用 get_forecast(city="北京", days=3)]
输出: 北京未来三天天气预报...
配置
API 密钥
本技能使用 OpenWeatherMap API,需要配置 API 密钥:
openclaw skills config weather-pro --api-key YOUR_API_KEY
获取 API 密钥:https://openweathermap.org/api
默认城市
可以设置默认城市,当用户未指定城市时使用:
openclaw skills config weather-pro --default-city 北京
使用示例
查询当前天气:
你: 今天天气怎么样?
AI: 北京今天晴,温度 15°C,适合出行。
查询其他城市:
你: 上海天气如何?
AI: 上海今天多云,温度 20°C,湿度较高。
查询天气预报:
你: 未来三天天气
AI: 北京未来三天天气预报:
- 明天:晴,8-18°C
- 后天:多云,10-20°C
- 大后天:小雨,12-16°C
依赖
- Python 3.8+
- requests 库
安装
openclaw skills install weather-pro
许可证
MIT License
### 2.4 实现工具(tools.py)
```python
# tools.py
from langchain.tools import tool
from typing import Optional, Dict, List
import requests
import os
# 从环境变量或配置文件读取 API 密钥
API_KEY = os.getenv("OPENWEATHER_API_KEY", "")
BASE_URL = "https://api.openweathermap.org/data/2.5"
@tool
def get_current_weather(city: str, unit: str = "celsius") -> Dict:
"""
查询指定城市的当前天气
Args:
city: 城市名称(中文或英文)
unit: 温度单位(celsius/fahrenheit)
Returns:
天气信息字典
"""
try:
# 转换单位
units = "metric" if unit == "celsius" else "imperial"
# 调用 API
url = f"{BASE_URL}/weather"
params = {
"q": city,
"appid": API_KEY,
"units": units,
"lang": "zh_cn"
}
response = requests.get(url, params=params, timeout=10)
response.raise_for_status()
data = response.json()
# 解析数据
result = {
"city": city,
"temperature": round(data["main"]["temp"]),
"unit": unit,
"condition": data["weather"][0]["description"],
"humidity": data["main"]["humidity"],
"wind_speed": round(data["wind"]["speed"] * 3.6) # m/s 转 km/h
}
return result
except requests.exceptions.RequestException as e:
return {
"error": f"查询天气失败: {str(e)}",
"city": city
}
except KeyError as e:
return {
"error": f"解析天气数据失败: {str(e)}",
"city": city
}
@tool
def get_forecast(city: str, days: int = 3) -> Dict:
"""
查询指定城市的多日天气预报
Args:
city: 城市名称
days: 预报天数(1-7)
Returns:
天气预报列表
"""
try:
# 限制天数
days = max(1, min(days, 7))
# 调用 API
url = f"{BASE_URL}/forecast"
params = {
"q": city,
"appid": API_KEY,
"units": "metric",
"lang": "zh_cn",
"cnt": days * 8 # 每天 8 个时间点
}
response = requests.get(url, params=params, timeout=10)
response.raise_for_status()
data = response.json()
# 按天分组
forecast_by_day = {}
for item in data["list"]:
date = item["dt_txt"].split()[0]
if date not in forecast_by_day:
forecast_by_day[date] = {
"date": date,
"temperatures": [],
"conditions": []
}
forecast_by_day[date]["temperatures"].atem["main"]["temp"])
forecast_by_day[date]["conditions"].append(item["weather"][0]["description"])
# 计算每天的最高/最低温度和主要天气
forecast = []
for date, day_data in list(forecast_by_day.items())[:days]:
temps = day_data["temperatures"]
forecast.append({
"date": date,
"temperature_high": round(max(temps)),
"temperature_low": round(min(temps)),
"condition": max(set(day_data["conditions"]), key=day_data["conditions"].count)
})
return {
"city": city,
"forecast": forecast
}
except requests.exceptions.RequestException as e:
return {
"error": f"查询天气预报失败: {str(e)}",
"city": city
}
except (KeyError, IndexError) as e:
return {
"error": f"解析天气预报数据失败: {str(e)}",
"city": city
}
# 导出工具列表
tools = [get_current_weather, get_forecast]
2.5 创建配置文件(config.yaml)
# config.yaml
# 技能元数据
metadata:
name: weather-pro
version: 1.0.0
aut description: 专业天气查询技能
# 配置项
config:
api_key:
type: string
required: true
description: OpenWeatherMap API 密钥
env: OPENWEATHER_API_KEY
default_city:
type: string
required: false
default: 北京
description: 默认城市
# 依赖
dependencies:
python:
- requests>=2.28.0
# 权限
permissions:
- network # 需要网络访问权限
三、测试技能
3.1 本地测试
# 进入技能目录
cd ~/.openclaw/workspace/skills/weather-pro
# 测试工具
python3 -c "
from tools import get_current_weather, get_forecast
# 测试当前天气
print(get_current_weather.invoke({'city': '北京'}))
# 测试天气预报
print(get_forecast.invoke({'city': '北京', 'days': 3}))
"
n
### 3.2 集成测试
```bash
# 重启 Gateway
openclaw gateway restart
# 在聊天中测试
你: 北京今天天气怎么样?
AI: [调用 weather-pro 技能]
北京今天晴,温度 15°C,湿度 45%,风速 12 km/h
3.3 调试技巧
启用详细日志:
# 编辑 config.yaml
logging:
level: debug # info → debug
# 重启 Gateway
openclaw gateway restart
# 查看日志
tail -f ~/.openclaw/logs/openclaw.log
使用 Python 调试器:
# 在 tools.py 中添加断点
import pdb
@tool
def get_current_weather(city: str, unit: str = "celsius") -> Dict:
pdb.set_trace() # 断点
# ... 代码
四、更多实战案例
4.1 案例 1:GitHub 集成技能
功能:
- 创建 issue
- 查看 PR
- 合并代码
SKILL.md 片段:
### create_issue
创建 GitHub issue
**参数:**
- `repo` (string): 仓库名称(格式:owner/repo)
- `title` (string): Issue 标题
- `body` (string): Issue 内容
**示例:**
用户: 在 myrepo 创建一个 issue,标题是"修复登录 bug"
助手: [调用 create_issue(repo=“username/myrepo”, title=“修复登录 bug”, body=“…”)]
tools.py 片段:
from github import Github
import os
GITHUB_TOKEN = os.getenv("GITHUB_TOKEN", "")
g = Github(GITHUB_TOKEN)
@tool
def create_issue(repo: str, title: str, body: str = "") -> Dict:
"""创建 GitHub issue"""
try:
repository = g.get_repo(repo)
issue = repository.create_issue(title=title, body=body)
return {
"status": "success",
"issue_number": issue.number,
"url": issue.html_url
}
except Exception as e:
return {
"status": "error",
"message": str(e)
}
tools = [create_issue]
4.2 案例 2:数据库查询技能
功能:
- 执行 SQL 查询
- 导出数据
- 数据统计
tools.py 片段:
import psycopg2
import os
DATABASE_URL = ov("DATABASE_URL", "")
@tool
def query_database(sql: str, limit: int = 100) -> Dict:
"""
执行 SQL 查询
Args:
sql: SQL 查询语句
limit: 返回结果数量限制
Returns:
查询结果
"""
try:
conn = psycopg2.connect(DATABASE_URL)
cursor = conn.cursor()
# 添加 LIMIT
if "LIMIT" not in sql.upper():
sql += f" LIMIT {limit}"
cursor.execute(sql)
results = cursor.fetchall()
columns = [desc[0] for desc in cursor.description]
cursor.close()
conn.close()
return {
"status": "success",
"columns": columns,
"rows": results,
"count": len(results)
}
except Exception as e:
return {
"status": "error",
"message": str(e)
}
tools = [query_database]
4.3 案例 3:文件处理技能
功能:
- 读取文件
- 搜索文件
- 批量重命名
tools.py 片段:
import os
import glob
from pathlib import Path
@tool
def search_files(pattern: str, directory: str = ".") -> List[str]:
"""
搜索文件
Args:
pattern: 文件名模式(支持通配符)
directory: 搜索目录
Returns:
列表
"""
try:
search_path = os.path.join(directory, "**", pattern)
files = glob.glob(search_path, recursive=True)
return {
"status": "success",
"files": files,
"count": len(files)
}
except Exception as e:
return {
"status": "error",
"message": str(e)
}
@tool
def batch_rename(directory: str, old_pattern: str, new_pattern: str) -> Dict:
"""
批量重命名文件
Args:
directory: 目录路径
old_pattern: 旧文件名模式
new_pattern: 新文件名模式
Returns:
重命名结果
"""
try:
renamed = []
for file_path in Path(directory).glob(old_pattern):
new_name = file_path.name.replace(old_pattern.replace("*", ""), new_pattern)
new_path = file_path.parent / new_name
file_path.rename(new_path)
renamed.append({
"old": str(file_path),
"new": str(new_path)
})
return {
"status": "success",
"renamed": renamed,
"count": len(renamed)
}
except Exception as e:
return {
"status": "error",
"message": str(e)
}
tools = [search_files, batch_rename]
4.4 案例 4:邮件自动化技能
功能:
- 发送邮件
- 搜索邮件
- 自动分类
tools.py 片段:
import smtplib
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
import os
SMTP_SERVER = os.getenv("SMTP_SERVER", "smtp.gmail.com")
SMTP_PORT = int(os.getenv("SMTP_PORT", "587"))
SMTP_USER = os.getenv("SMTP_USER", "")
SMTP_PASSWORD = etenv("SMTP_PASSWORD", "")
@tool
def send_email(to: str, subject: str, body: str, cc: str = "") -> Dict:
"""
发送邮件
Args:
to: 收件人邮箱
subject: 邮件主题
body: 邮件正文
cc: 抄送(可选)
Returns:
发送结果
"""
try:
msg = MIMEMultipart()
msg['From'] = SMTP_USER
msg['To'] = to
msg['Subject'] = subject
if cc:
msg['Cc'] = cc
msg.attach(MIMEText(body, 'plain'))
server = smtplib.SMTP(SMTP_SERVER, SMTP_PORT)
server.starttls()
server.login(SMTP_USER, SMTP_PASSWORD)
recipients = [to]
if cc:
recipients.extend(cc.split(','))
server.send_message(msg)
server.quit()
return {
"status": "success",
"to": to,
"subject": subject
}
except Exception as e:
return {
"status": "error",
"message": str(e)
}
tools = [send_email]
4.5 案例 5:定时提醒技能
功能:
- 创建提醒
- 查看提醒
- 删除提醒
tools.py 片段:
import json
import os
from datetime import datetime
from typing import List, Dict
REMINDERS_FILE = os.path.expanduser("~/.openclaw/reminders.json")
def load_reminders() -> List[Dict]:
"""加载提醒列表"""
if os.path.exists(REMINDERS_FILE):
with open(REMINDERS_FILE, 'r') as f:
return json.load(f)
return []
def save_reminders(reminders: List[Dict]):
"""保存提醒列表"""
os.makedirs(os.path.dirname(REMINDERS_FILE), exist_ok=True)
with open(REMINDERS_FILE, 'w') as f:
json.dump(reminders, f, indent=2, ensure_ascii=False)
@tool
def create_reminder(title: str, time: str, description: str = "") -> Dict:
"""
创建提醒
Args:
title: 提醒标题
time: 提醒时间(格式:YYYY-MM-DD HH:MM)
description: 提醒描述(可选)
Returns:
创建结果
"""
try:
# 验证时间格式
datetime.strptime(time, "%Y-%m-%d %H:%M")
reminders = load_reminders()
reminder = {
"id": len(reminders) + 1,
"title": title,
"time": time,
"description": description,
"created_at": datetime.now().isoformat(),
"status": "pending"
}
reminders.append(reminder)
save_reminders(reminders)
return {
"status": "success",
"reminder": reminder
}
except ValueError as e:
return {
"status": "error",
"message": f"时间格式错误: {str(e)}"
}
except Exception as e:
return {
"status": "error",
"message": str(e)
}
@tool
def list_reminders(status: str = "all") -> Dict:
"""
查看提醒列表
Args:
status: 状态筛选(all/pending/completed)
Returns:
提醒列表
try:
reminders = load_reminders()
if status != "all":
reminders = [r for r in reminders if r["status"] == status]
return {
"status": "success",
"reminders": reminders,
"count": len(reminders)
}
except Exception as e:
return {
"status": "error",
"message": str(e)
}
tools = [create_reminder, list_reminders]
五、发布到 Clawhub
5.1 准备发布
检查清单:
- SKILL.md 文档完整
- 工具实现正确
- 本地测试通过
- 添加示例代码
- 编写 README
- 添加许可证
5.2 发布命令
# 登录 Clawhub
openclaw login
# 发布技能
openclaw skills publish weather-pro
# 输出:
# ✅ 技能已发布到 Clawhub
# 📦 技能名称:weather-pro
# 🔗 链接:https://clawhub.com/skills/weather-pro
5.3 更新技能
# 修改版本号(config.yaml)
version: 1.1.0
# 发布更新
openclaw skills publish weather-pro --version 1.1.0
六、技能最佳实践
6.1 文档规范
DO ✅:
- 详细的功能说明
- 清晰的参数说明
- 丰富的使用示例
- 配置说明
- 依赖列表
DON’T ❌:
- 文档过于简单
- 缺少示例
- 参数说明不清
- 没有配置说明
6.2 代码规范
DO ✅:
- 使用类型注解
- 添加详细注释
- 错误处理完善
- 返回结构化数据
- 遵循 PEP 8
DON’T ❌:
- 没有错误处理
- 返回非结构化文本
- 代码混乱
- 缺少注释
6.3 安全规范
DO ✅:
- API 密钥使用环境变量
- 输入验证
- 权限检查
- 敏感信息加密
DON’T ❌:
- 硬编码密钥
- 不验证输入
- 忽略权限
- 明文存储密码
七、常见问题
Q1: 技能开发用 Python 还是 JavaScript?
A: 都可以!
- Python:适合数据处理、API 调用、机器学习
- JavaScript:适合前端交互、Node.js 生态
Q2: 如何调试技能?
A: 三种方法:
- 单元测试(推荐)
- 启用 debug 日志
- 使用 Python/Node.js 调试器
Q3: 技能可以访问文件系统吗?
A: 可以,但需要:
- 在 config.yaml 声明权限
- 用户确认授权
- 限制访问范围
Q4: 如何分享技能?
A: 两种方式:
- 发布到 Clawhub(推荐)
- 分享 GitHub 仓库
八、总结
8.1 关键要点
- 技能 = 工具 + 文档 + 配置
- SKILL.md 是技能的核心
- 工具实现要健壮
- 测试很重要
- 发布到 Clawhub 让更多人受益
8.2 技能开发流程
需求分析 → 创建目录 → 编写文档 → 实现工具 → 测试 → 发布
8.3 下一步
- 🛠️ 开发更多实用技能
- 📦 发布到 Clawhub
- 🌟 获得社区反馈
- 🔄 持续迭代优化
九、资源链接
官方资源:
- Clawhub:https://clawhub.com
- 技能开发文档:https://docs.openclaw.ai/skills
- 示例技能:https://github.com/openclaw/skills
社区:
- Discord:https://discord.gg/openclaw
- GitHub Discussions:https://github.com/openclaw/openclaw/discussions
🎉 结语
OpenClaw 的威力在于它的可扩展性。
通过开发自定义技能,你可以让 AI 助手做任何事情。
现在就开始,打造属于你的技能生态吧! 🚀
关注我,获取更多 OpenClaw 开发干货! 💪
如果觉得有帮助,欢迎点赞、收藏、转发! ❤️
有问题欢迎在评论区交流!
更多推荐

所有评论(0)