快速开始
构建插件
插件通过新能力扩展 OpenClaw:渠道、模型提供商、语音、实时转写、实时语音、媒体理解、图像生成、视频生成、Web 抓取、Web 搜索、智能体工具,或任意组合。
你不需要把你的插件添加到 OpenClaw 仓库。发布到
ClawHub,用户可以用
openclaw plugins install clawhub:<package-name> 安装。在发布切换期间,裸包规格仍会从 npm 安装。
前置条件
- Node >= 22 和一个包管理器(npm 或 pnpm)
- 熟悉 TypeScript(ESM)
- 对于仓库内插件:已克隆仓库并完成
pnpm install。源码检出插件开发仅支持 pnpm,因为 OpenClaw 会从extensions/*工作区包加载内置插件。
哪种插件?
将 OpenClaw 连接到消息平台(Discord、IRC 等)
添加一个模型提供商(LLM、代理或自定义端点)
将本地 AI CLI 映射到 OpenClaw 的文本兜底运行器
注册智能体工具、事件钩子或服务 - 继续阅读下文
对于不能保证在新手引导/设置运行时已安装的渠道插件,请使用
openclaw/plugin-sdk/channel-setup 中的 createOptionalChannelSetupSurface(...)。
它会生成一对设置适配器 + 向导,用于声明安装要求,并且在插件安装之前对真实配置写入采取失败关闭策略。
快速开始:工具插件
本演练会创建一个注册智能体工具的最小插件。渠道插件和提供商插件有上方链接的专门指南。
创建包和清单
{"name": "@myorg/openclaw-my-plugin","version": "1.0.0","type": "module","openclaw": { "extensions": ["./index.ts"], "compat": { "pluginApi": ">=2026.3.24-beta.2", "minGatewayVersion": "2026.3.24-beta.2" }, "build": { "openclawVersion": "2026.3.24-beta.2", "pluginSdkVersion": "2026.3.24-beta.2" }}}{"id": "my-plugin","name": "My Plugin","description": "Adds a custom tool to OpenClaw","contracts": { "tools": ["my_tool"]},"activation": { "onStartup": true},"configSchema": { "type": "object", "additionalProperties": false}}每个插件都需要清单,即使没有配置也是如此。运行时注册的工具必须列在 contracts.tools 中,这样 OpenClaw 才能在不加载每个插件运行时的情况下发现所属插件。插件还应有意声明 activation.onStartup。此示例将其设为 true。完整 schema 请参阅
插件清单。规范的 ClawHub 发布片段位于 docs/snippets/plugin-publish/。
编写入口点
// index.tsimport { definePluginEntry } from "openclaw/plugin-sdk/plugin-entry";import { Type } from "@sinclair/typebox"; export default definePluginEntry({ id: "my-plugin", name: "My Plugin", description: "Adds a custom tool to OpenClaw", register(api) { api.registerTool({ name: "my_tool", description: "Do a thing", parameters: Type.Object({ input: Type.String() }), async execute(_id, params) { return { content: [{ type: "text", text: `Got: ${params.input}` }] }; }, }); },});definePluginEntry 用于非渠道插件。对于渠道,请使用
defineChannelPluginEntry - 请参阅 渠道插件。
完整入口点选项请参阅 入口点。
测试并发布
**外部插件:**使用 ClawHub 验证并发布,然后安装:
clawhub package publish your-org/your-plugin --dry-runclawhub package publish your-org/your-pluginopenclaw plugins install clawhub:@myorg/openclaw-my-plugin在发布切换期间,像 @myorg/openclaw-my-plugin 这样的裸包规格会从 npm 安装。需要 ClawHub 解析时,请使用 clawhub:。
**仓库内插件:**放在内置插件工作区树下 - 会自动发现。
pnpm test -- <bundled-plugin-root>/my-plugin/插件能力
单个插件可以通过 api 对象注册任意数量的能力:
| 能力 | 注册方法 | 详细指南 |
|---|---|---|
| 文本推理(LLM) | api.registerProvider(...) |
提供商插件 |
| CLI 推理后端 | api.registerCliBackend(...) |
CLI 后端插件 |
| 渠道 / 消息 | api.registerChannel(...) |
渠道插件 |
| 语音(TTS/STT) | api.registerSpeechProvider(...) |
提供商插件 |
| 实时转写 | api.registerRealtimeTranscriptionProvider(...) |
提供商插件 |
| 实时语音 | api.registerRealtimeVoiceProvider(...) |
提供商插件 |
| 媒体理解 | api.registerMediaUnderstandingProvider(...) |
提供商插件 |
| 图像生成 | api.registerImageGenerationProvider(...) |
提供商插件 |
| 音乐生成 | api.registerMusicGenerationProvider(...) |
提供商插件 |
| 视频生成 | api.registerVideoGenerationProvider(...) |
提供商插件 |
| Web 抓取 | api.registerWebFetchProvider(...) |
提供商插件 |
| Web 搜索 | api.registerWebSearchProvider(...) |
提供商插件 |
| 工具结果中间件 | api.registerAgentToolResultMiddleware(...) |
SDK 概览 |
| 智能体工具 | api.registerTool(...) |
下文 |
| 自定义命令 | api.registerCommand(...) |
入口点 |
| 插件钩子 | api.on(...) |
插件钩子 |
| 内部事件钩子 | api.registerHook(...) |
入口点 |
| HTTP 路由 | api.registerHttpRoute(...) |
内部机制 |
| CLI 子命令 | api.registerCli(...) |
入口点 |
完整注册 API 请参阅 SDK 概览。
当内置插件需要在模型看到输出之前异步重写工具结果时,可以使用
api.registerAgentToolResultMiddleware(...)。请在 contracts.agentToolResultMiddleware 中声明目标运行时,例如
["pi", "codex"]。这是一个受信任的内置插件接口;外部插件应优先使用常规 OpenClaw 插件钩子,除非 OpenClaw 为此能力发展出明确的信任策略。
如果你的插件注册了自定义 Gateway 网关 RPC 方法,请将它们放在插件专属前缀下。核心管理员命名空间(config.*、exec.approvals.*、wizard.*、update.*)保持保留,并始终解析到
operator.admin,即使插件请求更窄的作用域也是如此。
需要牢记的钩子保护语义:
before_tool_call:{ block: true }是终止性决定,并会停止较低优先级的处理程序。before_tool_call:{ block: false }会被视为未作决定。before_tool_call:{ requireApproval: true }会暂停智能体执行,并通过 exec 审批浮层、Telegram 按钮、Discord 交互,或任意渠道上的/approve命令提示用户审批。before_install:{ block: true }是终止性决定,并会停止较低优先级的处理程序。before_install:{ block: false }会被视为未作决定。message_sending:{ cancel: true }是终止性决定,并会停止较低优先级的处理程序。message_sending:{ cancel: false }会被视为未作决定。message_received:当你需要入站线程/话题路由时,优先使用类型化的threadId字段。将metadata保留给渠道专属的额外信息。message_sending:优先使用类型化的replyToId/threadId路由字段,而不是渠道专属的元数据键。
/approve 命令会通过有界兜底同时处理 exec 和插件审批:当找不到某个 exec 审批 ID 时,OpenClaw 会通过插件审批重试同一个 ID。插件审批转发可以通过配置中的 approvals.plugin 独立配置。
如果自定义审批管道需要检测同一个有界兜底场景,请优先使用
openclaw/plugin-sdk/error-runtime 中的 isApprovalNotFoundError,而不是手动匹配审批过期字符串。
示例和钩子参考请参阅 插件钩子。
注册智能体工具
工具是 LLM 可以调用的类型化函数。它们可以是必需的(始终可用),也可以是可选的(用户选择启用):
register(api) { // Required tool - always available api.registerTool({ name: "my_tool", description: "Do a thing", parameters: Type.Object({ input: Type.String() }), async execute(_id, params) { return { content: [{ type: "text", text: params.input }] }; }, }); // Optional tool - user must add to allowlist api.registerTool( { name: "workflow_tool", description: "Run a workflow", parameters: Type.Object({ pipeline: Type.String() }), async execute(_id, params) { return { content: [{ type: "text", text: params.pipeline }] }; }, }, { optional: true }, );}工具工厂会接收一个由运行时提供的上下文对象。当工具需要记录、显示或适配当前轮次的活动模型时,请使用
ctx.activeModel。该对象可以包含 provider、modelId 和
modelRef。将其视为信息性的运行时元数据,而不是用于防范本地操作者、已安装插件代码或被修改过的
OpenClaw 运行时的安全边界。对于敏感的本地工具,请保留显式的插件或操作者选择启用,并在活动模型元数据缺失或不合适时默认拒绝。
每个通过 api.registerTool(...) 注册的工具也必须在插件清单中声明:
{ "contracts": { "tools": ["my_tool", "workflow_tool"] }, "toolMetadata": { "workflow_tool": { "optional": true } }}OpenClaw 会捕获并缓存已注册工具中经过验证的描述符,因此插件无需在清单中重复 description 或 schema 数据。清单契约只声明所有权和设备发现;执行时仍会调用实时注册的工具实现。
对于通过 api.registerTool(..., { optional: true }) 注册的工具,请设置
toolMetadata.<tool>.optional: true,这样 OpenClaw 可以在该工具被显式加入允许列表之前避免加载该插件运行时。
用户在配置中启用可选工具:
{ tools: { allow: ["workflow_tool"] },}- 工具名称不得与核心工具冲突(冲突项会被跳过)
- 注册对象格式错误的工具会被跳过并在插件诊断中报告,而不是中断智能体运行,包括缺少
parameters的情况 - 对有副作用或额外二进制依赖的工具使用
optional: true - 用户可以通过将插件 id 添加到
tools.allow来启用某个插件的所有工具
注册 CLI 命令
插件可以使用 api.registerCli 添加根级 openclaw 命令组。为每个顶层命令根提供
descriptors,这样 OpenClaw 无需预先加载每个插件运行时即可显示和路由该命令。
register(api) { api.registerCli( ({ program }) => { const demo = program .command("demo-plugin") .description("Run demo plugin commands"); demo .command("ping") .description("Check that the plugin CLI is executable") .action(() => { console.log("demo-plugin:pong"); }); }, { descriptors: [ { name: "demo-plugin", description: "Run demo plugin commands", hasSubcommands: true, }, ], }, );}安装后,验证运行时注册并执行命令:
openclaw plugins inspect demo-plugin --runtime --jsonopenclaw demo-plugin ping导入约定
始终从聚焦的 openclaw/plugin-sdk/<subpath> 路径导入:
// Wrong: monolithic root (deprecated, will be removed) 完整子路径参考见 SDK 概览。
在你的插件内部,请使用本地 barrel 文件(api.ts、runtime-api.ts)进行内部导入,绝不要通过自己的 SDK 路径导入自己的插件。
对于提供商插件,请将提供商专用 helper 保留在这些包根级 barrel 中,除非该接缝确实是通用的。当前内置示例:
- Anthropic:Claude 流包装器以及
service_tier/ beta helper - OpenAI:提供商构建器、默认模型 helper、实时提供商
- OpenRouter:提供商构建器以及新手引导/配置 helper
如果某个 helper 只在一个内置提供商包内部有用,请将它保留在该包根级接缝上,而不是提升到 openclaw/plugin-sdk/* 中。
一些生成的 openclaw/plugin-sdk/<bundled-id> helper 接缝仍然存在,用于在有已跟踪所有者使用场景时维护内置插件。请将它们视为保留表面,而不是新第三方插件的默认模式。
提交前检查清单
OPENCLAW_DOCS_MARKER:calloutOpen:Q2hlY2s
package.json 具有正确的 openclaw 元数据
OPENCLAW_DOCS_MARKER:calloutClose:
OPENCLAW_DOCS_MARKER:calloutOpen:Q2hlY2s openclaw.plugin.json 清单存在且有效 OPENCLAW_DOCS_MARKER:calloutClose:
OPENCLAW_DOCS_MARKER:calloutOpen:Q2hlY2s
入口点使用 defineChannelPluginEntry 或 definePluginEntry
OPENCLAW_DOCS_MARKER:calloutClose:
OPENCLAW_DOCS_MARKER:calloutOpen:Q2hlY2s
所有导入都使用聚焦的 plugin-sdk/<subpath> 路径
OPENCLAW_DOCS_MARKER:calloutClose: