OpenClaw 的插件系统允许在 gateway 进程中挂载自定义逻辑,与 AI agent 共享运行时。插件可以做很多事情:监听 agent 事件、提供自定义 tool、定时任务,或者像我们这次一样——跑一个独立的同步守护进程。
这篇记录从零创建一个插件、验证、发布到 ClawHub,再到远程节点安装的全过程。
背景 链接到标题
OpenClaw 插件和 Skill 的区别:Skill 是一组 instructions 文件,通过注入到 agent prompt 来改变行为;插件则是编译后的 JavaScript 代码,运行在 gateway 进程内,能调用 SDK 提供的 API(config、storage、http 等)。两者互补,技能负责"教 agent 怎么做",插件负责"替 agent 做"。
环境要求 链接到标题
- Node.js ≥ 22.19(OpenClaw 的要求)
- TypeScript + ESM 模块
- clawhub CLI — 用于验证和发布
- 一个 GitHub 仓库(公开或私有均可)
安装 clawhub CLI:
npm install -g @openclaw/clawhub
创建插件项目 链接到标题
推荐项目结构:
my-plugin/
├── src/
│ ├── index.ts # 插件入口
│ └── lib.ts # 核心逻辑
├── openclaw.plugin.json # 插件清单
├── tsconfig.json
└── package.json
包元数据 链接到标题
package.json 中的 openclaw 块定义了入口文件、兼容性和构建信息,是 gateway 加载和 ClawHub 发布的依据:
{
"name": "@myorg/openclaw-my-plugin",
"version": "1.0.0",
"type": "module",
"openclaw": {
"extensions": ["./dist/index.js"],
"compat": {
"pluginApi": ">=2026.6.5",
"minGatewayVersion": ">=2026.6.5"
},
"build": {
"openclawVersion": "2026.6.5",
"pluginSdkVersion": "2026.6.5"
}
},
"dependencies": {
"typebox": "^1.1.38"
}
}
| 字段 | 说明 |
|---|---|
openclaw.extensions |
编译后的 JS 入口文件路径 |
openclaw.compat |
兼容性声明,ClawHub 据此判断插件适用的 gateway 版本 |
openclaw.build |
构建时使用的 SDK 版本,用于发布元数据 |
入口文件必须指向编译后的 JS(如 ./dist/index.js),而非 TS 源码。ClawHub 发布的插件需要 compat 和 build 字段。
插件清单 链接到标题
openclaw.plugin.json 是 gateway 在加载插件代码前读取的元数据,用于配置验证和能力发现:
{
"id": "my-plugin",
"name": "My Plugin",
"description": "示例插件",
"version": "0.1.0",
"activation": {
"onStartup": true
},
"contracts": {
"tools": ["my_tool"]
},
"configSchema": {
"type": "object",
"additionalProperties": false,
"properties": {
"serverUrl": { "type": "string", "description": "服务地址" },
"userName": { "type": "string", "description": "用户名" },
"password": { "type": "string", "description": "密码" }
}
}
}
字段说明:
| 字段 | 说明 |
|---|---|
id |
插件唯一标识,安装时使用 |
activation.onStartup |
是否在 gateway 启动时自动加载 |
contracts.tools |
插件提供的 tool 列表,供 agent 调用 |
configSchema |
必需,JSON Schema 格式的配置校验规则,即使无配置也要写空对象 |
注意:入口文件路径不放在 openclaw.plugin.json 中,而是放在 package.json#openclaw.extensions。configSchema 是必需字段,缺少会导致 gateway 拒绝加载。
TypeScript 配置 链接到标题
ESM 模块编译配置,tsconfig.json:
{
"compilerOptions": {
"target": "ES2022",
"module": "NodeNext",
"moduleResolution": "NodeNext",
"outDir": "dist",
"rootDir": "src",
"strict": true,
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true,
"skipLibCheck": true
},
"include": ["src"]
}
SDK 入口与最小示例 链接到标题
插件入口使用 definePluginEntry 辅助函数:
import { definePluginEntry } from "openclaw/plugin-sdk/plugin-entry";
export default definePluginEntry({
id: "my-plugin",
name: "My Plugin",
description: "示例插件",
register(api) {
console.log("[my-plugin] Plugin started");
// 读取插件自身配置(来自 openclaw.json plugins.entries.<id>.config)
const cfg = api.pluginConfig;
console.log("[my-plugin] Config:", JSON.stringify(cfg));
// 你的逻辑...
},
});
register(api) 是插件运行时入口,gateway 启动时调用。api 对象提供了访问 OpenClaw 配置、存储、HTTP 客户端等能力。
插件自身的配置通过 api.pluginConfig 直接获取,无需从 api.config 中手动取路径。
注册自定义 Tool 链接到标题
通过 api.registerTool 注册可供 agent 调用的 tool:
import { Type } from "typebox";
import { definePluginEntry } from "openclaw/plugin-sdk/plugin-entry";
export default definePluginEntry({
id: "my-plugin",
name: "My Plugin",
description: "示例插件",
register(api) {
api.registerTool({
name: "my_tool",
description: "agent 可以调用的自定义功能",
parameters: Type.Object({
input: Type.String({ description: "输入参数" }),
}),
async execute(_id, params) {
return {
content: [{ type: "text", text: `处理成功: ${params.input}` }],
};
},
});
},
});
参数类型使用 typebox 定义,execute 返回 AgentToolResult 格式。Tool 名必须在 openclaw.plugin.json#contracts.tools 中声明。
插件配置 链接到标题
插件的配置通过 openclaw.json 注入,安装插件后在配置文件中添加:
{
"plugins": {
"allow": ["my-plugin"],
"entries": {
"my-plugin": {
"enabled": true,
"config": {
"serverUrl": "http://内网地址:端口",
"userName": "user",
"password": "***"
}
}
}
}
}
代码中通过 api.pluginConfig 读取。
本地验证 链接到标题
编译项目后,使用 clawhub CLI 做完整性检查:
npx tsc
clawhub package validate .
成功输出:
Plugin Inspector: PASS
Breakages: 0
Warnings: 0
Findings: none
Inspector 会检查:清单字段完整性、入口文件存在性、依赖冲突、Node 版本兼容性等。验证报告会写入 reports/ 目录。
发布到 ClawHub 链接到标题
发布需要关联一个 GitHub 仓库(公开或私有均可):
clawhub package publish <scope>/<name> \
--source-repo <github-user>/<repo-name> \
--source-commit $(git rev-parse HEAD)
<scope>:你的 GitHub 用户名<name>:包名,与插件id无关,独立定义- ClawHub 不限制仓库必须是公开的,私有仓库也能发布
- 每次发布建议更新版本号
发布后查看:
clawhub package info <scope>/<name>
版本管理 链接到标题
建议使用 semver,每次修改后更新 openclaw.plugin.json 中的 version,再重新发布。Agent 安装时若不指定版本,默认拉取最新版。
远程节点安装 链接到标题
在有 OpenClaw gateway 运行的节点上安装:
openclaw plugins install clawhub:<scope>/<name>
安装后,编辑 openclaw.json 添加配置(可选),然后重启 gateway:
# Docker 部署场景
docker restart openclaw-openclaw-gateway-1
验证插件是否加载成功:
docker logs openclaw-openclaw-gateway-1 2>&1 | grep "plugin"
日志中应看到插件名称出现在加载列表中:
http server listening (N plugins: ... my-plugin ...)
关闭并卸载 链接到标题
在 openclaw.json 中可以:
- 从
plugins.allow中移除(彻底卸载) - 或设置
plugins.entries.<id>.enabled: false(临时禁用)
日志与调试 链接到标题
插件内的标准输出会被 OpenClaw 日志系统捕获:
console.log("[my-plugin] [INFO] 信息");
console.warn("[my-plugin] [WARN] 警告");
console.error("[my-plugin] [ERROR] 错误");
建议日志格式保持 [插件名] [级别] 消息,便于 grep 过滤。
对于需要持久化的状态(如上一次处理的 seq、token 等),有两种方式:
- 写入文件(插件进程内持久)
- 通过
api.storageSDK 接口(推荐,配置管理等场景)
小结 链接到标题
OpenClaw 插件机制的几个要点:
- TypeScript ESM + Node ≥22 是硬性要求
- 插件清单定义了元数据和能力,
configSchema是必需字段 - 入口文件在
package.json#openclaw.extensions中声明,不在 manifest 中 - 发布不要求公开仓库,私有仓库完全可用
- 远程安装一行命令,配置通过
openclaw.json注入 - 日志通过 console 输出,与 gateway 日志汇总
插件的应用场景不止于此:可以挂载 HTTP handler、定时任务、集成外部服务。对于需要在 AI agent 侧执行的计算密集型或持久化任务,插件是比 Skill 更合适的选择。