OpenClaw v2026.5.4代码规范详解:插件SDK重构与中间件适配
明确几点:如果你仍幻想在OpenClaw v2026.5.4上直接套用旧插件,大概率会碰壁。基于openclaw/extension-api构建的老方案已全面失效——控制台抛出“register is not a function”,甚至npm install后插件毫无反应。原因很简单:v2026.5.4彻底废弃旧版API,强制迁移至全新SDK体系。所有插件必须重写,且需严格适配中间件生命周期钩子。
验证运行环境与SDK版本
第一步,确认当前环境是否达标。终端执行openclaw --version,输出必须为v2026.5.4或更高;若低于此版本,立即升级:openclaw update --force。
接着核查Node.js和npm版本。node -v需≥22.12.0,npm -v需≥10.9.0。两者缺一不可,否则插件编译会因ESM模块解析失败而直接终止,不会给出明确提示。
最后运行openclaw plugin sdk info,确认返回的currentSdk字段是否为@openclaw/plugin-sdk@2026.5.4。这一步至关重要——这是唯一兼容v2026.5.4的SDK版本,其他任何版本均无法通过加载校验。
重写插件入口:从export default到createSkill
旧插件常用module.exports = { register };,但在v2026.5.4中此路不通。新规范要求改用SDK导出的createSkill工厂函数。
具体操作:新建skill.ts(或skill.js),文件顶部引入:import { createSkill } from '@openclaw/plugin-sdk';。将原来的register(api)逻辑替换为:
export default createSkill({ id: 'my-formatter', name: '代码格式化助手', version: '1.0.0' });
注意细节——id必须全局唯一,且仅允许小写字母、数字和短横线。
更关键的是,旧版中直接调用api.registerTool的位置,现在必须包裹在onLoad钩子内:onLoad: (ctx) => { ctx.registerTool(...); }。若不按此处理,插件启动时工具不会注册,命令自然不可见。
适配中间件生命周期:四阶段钩子不可省略
v2026.5.4将插件加载拆分为四个严格顺序的中间件阶段,每个阶段对应一个可选钩子函数。官方称“可选”,但实际中——缺失任一阶段的声明,插件都会被静默跳过,不产生任何报错。
第一步:声明onDiscover。该钩子用于返回插件元数据,必须同步返回{ id, name, description, icon }对象。注意:此处禁止使用Promise或异步操作,否则插件会被判定为“发现失败”并终止加载。
第二步:实现onLoad。插件正式载入内存后的初始化入口。在此注册工具、监听事件、建立数据库连接——所有副作用操作(如fs.readFile、fetch)必须在此阶段完成。【onDiscover中禁止IO操作,此为硬性规定】。
第三步:定义onExecute。用户触发插件时的核心执行逻辑,接收input参数,返回Promise。该函数内可调用ctx.runtime.exec执行系统命令,但绝对禁止process.exit()——否则会杀死整个Gateway进程,后果严重。
第四步:补充onUnload。插件卸载前的清理工作,例如关闭HTTP服务器、释放文件句柄。若未定义,OpenClaw在热重载时会残留资源,连续三次重载后会触发EMFILE错误,相当棘手。
迁移配置文件:openclaw.plugin.json强制校验
旧版package.json中的openclaw字段可以删除。现在需新建openclaw.plugin.json——注意文件名必须与此一致,不能改为.yaml或.ts。
基础结构简单,必填项为:
{"id":"my-formatter","name":"代码格式化助手","version":"1.0.0","main":"dist/skill.js"}
其中main路径必须指向编译后的产物,且为相对于插件根目录的路径。若指向src/skill.ts,加载时会直接报ERR_MODULE_NOT_FOUND。
若希望插件更可靠,建议添加能力声明:
"capabilities": ["tool", "http"]
这明确告知OpenClaw——该插件需要注册工具,并可能暴露HTTP路由。如果实际注册了HTTP路由但未声明http能力,ctx.http.registerRoute的调用会静默失败,难以排查。
另一个易被忽略的点:安全上下文声明。
添加"permissions": ["fs:read", "network:outbound"],否则在v2026.5.4默认沙箱下,插件无法读取本地文件或发起网络请求。【不声明即无权,没有例外】。
