1. OpenClaw技能系统入门:核心概念解析
OpenClaw技能系统是一个基于Node.js和TypeScript构建的插件化架构,允许开发者通过定义工具插件来扩展AI代理的能力。与传统的插件系统不同,OpenClaw采用了一种独特的"技能即工具"的设计理念,每个技能本质上都是一个可被AI代理调用的工具函数。
在OpenClaw中,一个完整的技能通常由三个核心文件构成:
package.json:定义项目元数据、依赖关系和构建脚本openclaw.plugin.json:描述插件元数据和工具契约src/index.ts:实现具体的工具逻辑
这种三文件结构的设计体现了OpenClaw对模块化和声明式编程的重视。通过分离元数据和实现逻辑,系统可以在不加载运行时代码的情况下发现和验证工具,这在大型插件生态系统中尤为重要。
提示:OpenClaw要求使用Node.js 22.19+、23.11+或24+版本,并且必须使用TypeScript的ESM模块输出格式。在开始开发前,请确保你的开发环境满足这些要求。
2. 三文件结构深度剖析
2.1 package.json:项目基石
OpenClaw技能项目的package.json除了包含常规Node.js项目的配置外,还有几个关键的特殊字段:
{ "type": "module", "files": ["dist", "openclaw.plugin.json", "README.md"], "dependencies": { "typebox": "^1.1.38" }, "peerDependencies": { "openclaw": ">=2026.5.17" }, "openclaw": { "extensions": ["./dist/index.js"] } }其中typebox必须作为运行时依赖而非开发依赖,因为生成的插件会在运行时引用它。peerDependencies确保插件与兼容的OpenClaw版本一起使用,而openclaw.extensions则指明了插件的入口文件。
2.2 openclaw.plugin.json:元数据契约
这个文件由openclaw plugins build命令自动生成,包含了插件的静态元数据:
{ "id": "stock-quotes", "name": "Stock Quotes", "description": "Fetch stock quote snapshots.", "version": "0.1.0", "configSchema": { "type": "object", "additionalProperties": false, "properties": {} }, "activation": { "onStartup": true }, "contracts": { "tools": ["stock_quote"] } }contracts.tools字段特别重要,它声明了插件提供的所有工具名称,使OpenClaw能在不加载插件代码的情况下发现可用工具。如果手动修改这个文件,必须重新运行构建命令以确保元数据与代码实现一致。
2.3 src/index.ts:技能实现
这是技能的核心实现文件,使用defineToolPlugin函数定义:
export default defineToolPlugin({ id: "stock-quotes", name: "Stock Quotes", description: "Fetch stock quote snapshots.", configSchema: Type.Object({ apiKey: Type.Optional(Type.String({ description: "Quote API key." })), baseUrl: Type.Optional(Type.String({ description: "Quote API base URL." })), }), tools: (tool) => [ tool({ name: "stock_quote", label: "Stock Quote", description: "Fetch a stock quote snapshot.", parameters: Type.Object({ symbol: Type.String({ description: "Ticker symbol, for example OPEN." }), }), async execute({ symbol }, config, context) { context.signal?.throwIfAborted(); return { symbol: symbol.toUpperCase(), configured: Boolean(config.apiKey), baseUrl: config.baseUrl ?? "https://api.example.com", }; }, }), ], });defineToolPlugin接收插件标识、配置模式(可选)和工具列表,每个工具都定义了名称、描述、参数模式和execute函数。OpenClaw会自动将普通返回值包装成工具结果格式。
3. 技能开发全流程指南
3.1 初始化项目
使用OpenClaw CLI初始化一个新插件项目:
openclaw plugins init stock-quotes --name "Stock Quotes" cd stock-quotes npm install这个命令会创建包含以下文件的脚手架:
src/index.ts:带有示例echo工具的基本插件src/index.test.ts:元数据测试tsconfig.json:配置为输出到dist目录vitest.config.ts:测试配置package.json:包含构建和验证脚本openclaw.plugin.json:初始工具元数据
3.2 开发与构建
开发过程中主要使用以下命令:
npm run build # 编译TypeScript到dist目录 npm run plugin:build # 构建并生成元数据 npm run plugin:validate # 验证插件完整性 npm test # 运行测试plugin:build实际上是npm run build后跟openclaw plugins build --entry ./dist/index.js的组合,它会:
- 编译TypeScript代码
- 从代码中提取元数据
- 生成/更新openclaw.plugin.json
- 确保package.json配置正确
3.3 本地测试与调试
要在本地OpenClaw实例中测试插件:
openclaw plugins install ./stock-quotes openclaw plugins inspect stock-quotes --runtime如果工具没有按预期出现,检查步骤:
- 确认插件已正确安装(
openclaw plugins list) - 验证元数据是否最新(
npm run plugin:validate) - 检查Gateway是否已重启
- 使用
--runtime --json标志查看详细运行时信息
3.4 发布到ClawHub
准备发布时,首先创建发布包:
npm pack然后使用ClawHub CLI发布:
clawhub package publish ./stock-quotes --dry-run # 试运行 clawhub package publish ./stock-quotes # 实际发布发布后,用户可以通过以下方式安装你的技能:
openclaw plugins install clawhub:your-org/stock-quotes4. 高级技能开发技巧
4.1 可选工具与工厂模式
对于需要用户显式许可的工具,可以标记为可选:
tool({ name: "workflow_run", description: "Run an external workflow.", parameters: Type.Object({ goal: Type.String() }), optional: true, execute: ({ goal }) => ({ queued: true, goal }), });对于需要运行时决定是否提供的工具,可以使用工厂模式:
tool({ name: "local_workflow", description: "Run a local workflow outside sandboxed sessions.", parameters: Type.Object({ goal: Type.String() }), optional: true, factory({ api, toolContext }) { if (toolContext.sandboxed) { return null; } return createLocalWorkflowTool(api); }, });4.2 返回值处理
OpenClaw会自动包装返回值,但你可以控制包装方式:
- 返回字符串:AI代理直接看到该文本
- 返回JSON兼容值:AI看到格式化JSON,OpenClaw保留原始值
// AI看到纯文本 tool({ name: "echo_text", execute: ({ input }) => input, }); // AI看到格式化JSON tool({ name: "echo_json", execute: ({ input }) => ({ input, length: input.length }), });4.3 配置管理
技能可以定义配置模式,配置通过Gateway提供:
const configSchema = Type.Object({ apiKey: Type.String(), }); export default defineToolPlugin({ configSchema, tools: (tool) => [ tool({ name: "configured_ping", execute: (_params, config) => ({ hasKey: config.apiKey.length > 0 }), }), ], });重要:永远不要在代码中硬编码敏感信息,始终使用配置系统或环境变量。
5. 常见问题与解决方案
5.1 工具未出现在可用列表中
检查顺序:
- 运行
openclaw plugins inspect <plugin-id> --runtime确认工具已注册 - 验证
openclaw.plugin.json中的contracts.tools包含正确工具名 - 检查
package.json的openclaw.extensions指向正确的入口文件 - 确认Gateway已重启加载新插件
5.2 元数据过时错误
当看到"openclaw.plugin.json generated metadata is stale"错误时,执行:
npm run build openclaw plugins build --entry ./dist/index.js然后提交openclaw.plugin.json和package.json的变更。
5.3 类型包缺失错误
"Cannot find package 'typebox'"错误通常是因为typebox被错误地放在了devDependencies中。解决:
npm install typebox --save npm run build openclaw plugins build --entry ./dist/index.js5.4 入口文件问题
如果遇到"plugin entry not found"或"does not expose defineToolPlugin metadata"错误:
- 确认
--entry参数指向正确的文件 - 检查入口文件是否默认导出了
defineToolPlugin的结果 - 确保已经运行过构建命令
6. 实战:构建股票报价技能
让我们通过一个完整的股票报价技能示例,串联所有概念:
6.1 初始化项目
openclaw plugins init stock-quotes --name "Stock Quotes" cd stock-quotes npm install axios --save # 添加HTTP客户端6.2 实现核心逻辑
修改src/index.ts:
import axios from 'axios'; import { defineToolPlugin, Type } from 'openclaw/plugin-sdk/tool-plugin'; export default defineToolPlugin({ id: "stock-quotes", name: "Stock Quotes", description: "Fetch real-time stock quotes.", configSchema: Type.Object({ apiKey: Type.String({ description: "Alpha Vantage API key" }), timeout: Type.Optional(Type.Number({ default: 5000 })), }), tools: (tool) => [ tool({ name: "get_quote", label: "Get Stock Quote", description: "Fetch current price and volume for a stock symbol.", parameters: Type.Object({ symbol: Type.String({ description: "Stock ticker symbol" }), }), async execute({ symbol }, config, context) { context.signal?.throwIfAborted(); const url = `https://www.alphavantage.co/query?function=GLOBAL_QUOTE&symbol=${symbol}&apikey=${config.apiKey}`; try { const { data } = await axios.get(url, { timeout: config.timeout, signal: context.signal }); if (data['Global Quote']) { return { symbol: data['Global Quote']['01. symbol'], price: data['Global Quote']['05. price'], volume: data['Global Quote']['06. volume'], lastUpdated: new Date().toISOString() }; } throw new Error('Invalid response format'); } catch (error) { if (axios.isAxiosError(error)) { throw new Error(`API request failed: ${error.message}`); } throw error; } }, }), ], });6.3 构建与验证
npm run plugin:build npm run plugin:validate6.4 本地测试
npm pack openclaw plugins install ./openclaw-plugin-stock-quotes-0.1.0.tgz然后在Gateway配置中添加API密钥,重启服务后即可通过AI代理测试:
@agent get me the current price of AAPL6.5 生产注意事项
- 添加适当的错误处理和限流
- 实现缓存机制避免频繁调用API
- 添加输入验证防止注入攻击
- 考虑添加批处理功能同时查询多个股票
- 编写完整的单元测试和集成测试
通过这个实战示例,我们可以看到OpenClaw技能系统如何将简单的工具函数转化为AI代理可以理解和使用的强大能力。三文件结构保持了项目的整洁,同时提供了足够的灵活性来处理各种复杂场景。