共计 2047 个字符,预计需要花费 6 分钟才能阅读完成。
核心概念:Skill 在 OpenClaw 中的角色
OpenClaw 平台的 Skill 类似于智能手机上的应用,它们是实现特定功能的模块。当用户发出指令时,平台会根据指令内容路由到对应的 Skill 进行处理。这种架构有两大特点:

- 事件驱动:Skill 通过监听特定类型的事件(如语音指令、API 调用)来触发执行
- 技能编排:多个 Skill 可以协同工作,前一个 Skill 的输出可以作为下一个 Skill 的输入
举个实际例子:当用户说 ” 查下北京天气然后提醒我带伞 ”,天气查询 Skill 和提醒 Skill 就会依次被触发。
环境准备:从安装到初始化
1. 安装 CLI 工具
打开终端执行以下命令(需要 Node.js 16+ 环境):
npm install -g @openclaw/cli
2. 创建项目
用 CLI 初始化项目骨架:
oclaw init weather-skill --template=typescript
cd weather-skill
3. 配置本地调试
创建 .env 文件配置凭证:
# .env 示例
API_KEY=your_openclaw_key
WEATHER_API=your_weather_provider_key
启动开发服务器:
oclaw dev
实战开发:天气查询 Skill
项目结构说明
典型 Skill 包含这些关键文件:
├── src
│ ├── handlers/ # 事件处理器
│ ├── models/ # 数据模型
│ ├── services/ # 第三方服务封装
│ └── index.ts # 入口文件
├── skill.json # 技能元数据
└── package.json
核心代码实现
在 src/handlers/weather.ts 中编写业务逻辑:
// 天气查询处理器
import {WeatherService} from '../services/weather';
import {CardBuilder} from '@openclaw/card-templates';
export const weatherHandler = async (event) => {
// 1. 从事件中提取城市参数
const city = event.slotValues.city;
// 2. 调用天气 API
const weather = await WeatherService.getForecast(city);
// 3. 构建响应卡片
return new CardBuilder()
.setTitle(`${city}天气预报 `)
.addText(` 当前温度:${weather.temp}℃`)
.addImage(weather.icon)
.build();};
记得在 src/services/weather.ts 中封装 API 调用:
// 天气服务封装
import axios from 'axios';
export class WeatherService {static async getForecast(city: string) {
const res = await axios.get(`https://api.weatherapi.com/v1/current.json`, {
params: {
key: process.env.WEATHER_API,
q: city
}
});
return {
temp: res.data.current.temp_c,
icon: res.data.current.condition.icon
};
}
}
调试与部署
本地测试方法
使用 CLI 模拟用户输入:
oclaw test --event weather --slots city= 北京
生产部署
打包前注意:
- 在
skill.json中完善元信息 - 执行构建命令:
oclaw build
- 通过 CLI 发布:
oclaw deploy --prod
常见问题避坑指南
-
权限遗漏 :在
skill.json中必须声明需要的 API 权限{"permissions": ["weather_api"] } -
冷启动超时:
- 保持 Skill 最小依赖
-
使用
oclaw warmup预热函数 -
异步处理错误:
- 所有异步操作必须用 try/catch 包裹
- 使用
async/await替代回调
性能优化建议
-
缓存热点数据:
// 使用内存缓存 import NodeCache from 'node-cache'; const cache = new NodeCache({stdTTL: 600}); async function getWeather(city) {const cached = cache.get(city); if (cached) return cached; const data = await fetchWeather(city); cache.set(city, data); return data; } -
并发控制:
- 使用
Promise.all并行独立请求 - 限制最大并发数(如
p-limit库)
思考延伸
本文实现的天气查询是单轮对话的简单 Skill。如果要实现多轮对话(比如先问城市再问日期),需要考虑:
– 如何维护对话状态?
– 如何处理用户中途切换话题?
– 怎样设计上下文传递机制?
欢迎在评论区分享你的设计思路!
正文完
发表至: 技术开发
近一天内
