安装和使用插件
用于添加、启用和排查插件的终端用户指南。
构建插件
使用最小可运行 manifest 的第一个插件教程。
频道插件
构建一个消息频道插件。
提供者插件
构建一个模型提供者插件。
SDK 概览
导入映射和注册 API 参考。
公共能力模型
能力是 OpenClaw 内部公开的原生插件模型。每个原生 OpenClaw 插件都会针对一种或多种能力类型进行注册:一个只注册零个能力、但提供 hooks、tools、discovery services 或后台服务的插件,是一个仅 hook 的旧式插件。该模式仍然完全受支持。
外部兼容性立场
能力模型已经进入核心,并且今天已被捆绑/原生插件使用,但外部插件兼容性仍需要比“它被导出了,因此它是冻结的”更严格的标准。
能力注册是预期方向。在迁移期间,旧式 hooks 仍是外部插件最安全的不破坏路径。已导出的辅助子路径并不都等价——应优先选择狭窄、文档化的契约,而不是偶然导出的辅助函数。
插件形态
OpenClaw 会根据插件实际的注册行为(而不仅仅是静态元数据)将每个已加载插件归类为某种形态:纯能力
纯能力
注册恰好一种能力类型(例如一个仅提供者插件,如
arcee 或 chutes)。混合能力
混合能力
注册多种能力类型(例如
openai 同时拥有文本推理、语音、媒体理解和图像生成)。仅 hooks
仅 hooks
只注册 hooks(类型化或自定义),不注册能力、工具、命令或服务。
非能力型
非能力型
注册工具、命令、服务或路由,但不注册能力。
openclaw plugins inspect <id> 查看插件的形态和能力拆分。详情请参见 CLI 参考。
兼容性信号
openclaw doctor、openclaw plugins inspect <id>、openclaw status --all 和 openclaw plugins doctor 会显示这些兼容性提示:
这些建议/警告信号今天不会破坏你的插件。这些信号也会出现在
openclaw status --all 和 openclaw plugins doctor 中。
架构概览
OpenClaw 的插件系统有四层:1
清单 + 发现
OpenClaw 会从配置路径、workspace 根目录、全局插件根目录以及捆绑插件中查找候选插件。发现流程会优先读取原生
openclaw.plugin.json 清单以及受支持的 bundle 清单。2
启用 + 验证
核心会决定发现的插件是启用、禁用、阻止,还是被选中用于某个独占槽位,例如 memory。
3
运行时加载
原生 OpenClaw 插件以内进程方式加载,并将能力注册到中央注册表中。打包后的 JavaScript 通过原生
require 加载;第三方本地源码 TypeScript 则使用紧急的 Jiti 回退。兼容的 bundle 会被规范化为注册表记录,而不会导入运行时代码。4
表面消费
OpenClaw 的其余部分读取注册表,以暴露工具、频道、提供者设置、hooks、HTTP 路由、CLI 命令和服务。
- 解析时元数据来自
registerCli(..., { descriptors: [...] }) - 真正的插件 CLI 模块可以保持懒加载,并在首次调用时注册
- manifest/配置验证应当仅依赖manifest/schema 元数据,而不执行插件代码
- 原生能力发现可能会加载受信任的插件入口代码,以构建一个不激活的注册表快照
- 原生运行时行为来自插件模块的
register(api)路径,并且api.registrationMode === "full"
插件元数据快照和查找表
Gateway 启动会为当前配置快照构建一个PluginMetadataSnapshot。该快照仅包含元数据:它存储已安装插件索引、manifest 注册表、manifest 诊断、所有者映射、插件 id 规范化器以及 manifest 记录。它不包含已加载的插件模块、提供者 SDK、包内容或运行时导出。
插件感知的配置验证、启动时自动启用以及 Gateway 插件引导都会使用该快照,而不是独立重建 manifest/索引元数据。PluginLookUpTable 基于同一个快照派生,并为当前运行时配置添加启动插件计划。
启动后,Gateway 会将当前元数据快照作为可替换的运行时产物保留。重复的运行时提供者发现可以借用该快照,而无需在每次 provider-catalog 遍历时重建已安装索引和 manifest 注册表。当没有兼容的当前快照时,调用方会退回到冷路径的 manifest/索引流程。兼容性检查必须包含诸如 plugins.load.paths 和默认 agent workspace 之类的插件发现根目录,因为 workspace 插件属于元数据作用域的一部分。
该快照和查找表让重复的启动决策保持在快速路径上:
- 频道所有权
- 启动插件规划
- 启动插件 id
- 提供者和 CLI 后端所有权
- 设置提供者、命令别名、模型目录提供者以及 manifest 契约所有权
- 插件配置 schema 和频道配置 schema 验证
- 启动时自动启用决策
PluginLookUpTable。该路径现在会按需重建注册表;如果调用方已经拥有当前查找表或显式 manifest 注册表,优先在运行时流程中传递它们。
激活规划
激活规划属于控制平面。调用方可以在加载更广泛的运行时注册表之前,询问哪些插件与某个具体命令、提供者、频道、路由、agent harness 或能力相关。 规划器保持当前 manifest 行为兼容:activation.*字段是显式的规划器提示providers、channels、commandAliases、setup.providers、contracts.tools和 hooks 仍然是 manifest 所有权回退- 仅 ids 的规划器 API 对现有调用方保持可用
- plan API 会报告原因标签,以便诊断能够区分显式提示和所有权回退
频道插件和共享消息工具
频道插件在正常聊天操作中不需要注册单独的发送/编辑/反应工具。OpenClaw 在核心中保留了一个共享的message 工具,而频道插件在其后面负责频道特定的发现和执行。
当前边界是:
- 核心拥有共享的
message工具宿主、提示词绑定、会话/线程记账以及执行分发 - 频道插件拥有作用域内的动作发现、能力发现以及任何频道特定的 schema 片段
- 频道插件拥有提供者特定的会话对话语法,例如对话 ids 如何编码线程 ids,或如何从父对话继承
- 频道插件通过其动作适配器执行最终动作
ChannelMessageActionAdapter.describeMessageTool(...)。这个统一的发现调用让插件能够将其可见动作、能力和 schema 贡献一起返回,从而避免这些部分彼此偏离。
消息动作名称使用一种有意设计为封闭且由核心拥有的词汇,以便每种传输方式都能呈现每个动作。插件只能通过核心 PR 添加动作名称;运行时注册是明确不受支持的。
当频道特定的消息工具参数携带媒体源(例如本地路径或远程媒体 URL)时,插件还应从 describeMessageTool(...) 返回 mediaSourceParams。核心会使用这个显式列表来应用沙箱路径规范化和出站媒体访问提示,而不会硬编码插件拥有的参数名称。这里应优先使用按动作划分的映射,而不是整个频道共用的扁平列表,这样仅用于配置文件的媒体参数就不会被规范化到 send 等无关动作上。
核心会在该发现步骤中传入运行时作用域。重要字段包括:
accountIdcurrentChannelIdcurrentThreadTscurrentMessageIdsessionKeysessionIdagentId- 可信的入站
requesterSenderId
message 工具中硬编码频道特定分支。
这也是为什么嵌入式运行器的路由变更仍然属于插件工作:运行器负责将当前聊天/会话身份传递到插件发现边界,以便共享的 message 工具为当前轮次暴露正确的频道拥有表面。
对于频道拥有的执行辅助工具,频道插件应将执行运行时保留在其自身的插件模块中。核心不再在 src/agents/tools 下拥有 Discord、Slack、Telegram 或 WhatsApp 的消息动作运行时。我们不会发布单独的 plugin-sdk/*-action-runtime 子路径,这些插件应直接从其自有模块中导入本地运行时代码。
同样的边界也普遍适用于按提供者命名的 SDK 断点:核心不应导入 Discord、Signal、Slack、WhatsApp 或类似插件的频道专用便捷导出桶。如果核心需要某种行为,要么消费捆绑插件自己的 api.ts / runtime-api.ts 导出桶,要么将需求提升为共享 SDK 中一个狭窄的通用能力。
捆绑插件遵循相同规则。捆绑插件的 runtime-api.ts 不应重新导出其自己的品牌化 openclaw/plugin-sdk/<plugin-id> facade。这些品牌化 facade 仍然是面向外部插件和旧消费者的兼容性 shim,但捆绑插件应使用本地导出,以及诸如 openclaw/plugin-sdk/channel-policy、openclaw/plugin-sdk/runtime-store 或 openclaw/plugin-sdk/webhook-ingress 之类狭窄的通用 SDK 子路径。除非现有外部生态的兼容边界确有要求,否则新代码不应添加插件 id 特定的 SDK facade。
针对 poll,存在两条执行路径:
outbound.sendPoll是适用于符合通用 poll 模型的频道的共享基线actions.handleAction("poll")是适用于频道特定 poll 语义或额外 poll 参数的首选路径
能力所有权模型
OpenClaw 将原生插件视为 公司 或 功能 的所有权边界,而不是把各种互不相关的集成杂糅在一起的“杂物袋”。 这意味着:- 公司插件通常应拥有该公司所有面向 OpenClaw 的表面
- 功能插件通常应拥有其引入的完整功能表面
- 通道应消费共享的核心能力,而不是临时性地重新实现提供方行为
厂商多能力
厂商多能力
google 拥有文本推理、CLI 后端、嵌入、语音、实时语音、媒体理解、图像/音乐/视频生成以及网页搜索。openai 拥有文本推理、嵌入、语音、实时转录、实时语音、媒体理解、图像/视频生成。minimax 拥有文本推理以及媒体理解、语音、图像/音乐/视频生成和网页搜索。厂商单能力
厂商单能力
arcee 和 chutes 仅拥有文本推理;microsoft 仅拥有语音。厂商插件可以一直保持这种窄范围,直到它需要覆盖该厂商更多的表面。功能插件
功能插件
voice-call 拥有通话传输、工具、CLI、路由以及 Twilio 媒体流桥接,但它消费共享的语音、实时转录和实时语音能力,而不是直接导入厂商插件。- 一个厂商的 OpenClaw 面向表面位于一个插件中,即使它跨越文本模型、语音、图像和视频
- 其他厂商也可以为它们自己的表面区域采用同样的方式
- 通道不关心哪个厂商插件拥有提供方;它们消费 core 暴露的共享能力契约
- plugin = 所有权边界
- capability = 可由多个插件实现或消费的核心契约
1
定义能力
在 core 中定义缺失的能力。
2
通过 SDK 暴露
以类型安全的方式通过插件 API/runtime 暴露它。
3
连接消费者
让通道/功能围绕该能力进行连接。
4
厂商实现
让厂商插件注册实现。
能力分层
在决定代码应该放在哪里时,可以使用这个心智模型:- 核心能力层
- 厂商插件层
- 通道/功能插件层
共享编排、策略、回退、配置合并规则、交付语义以及类型化契约。
- core 拥有回复时 TTS 策略、回退顺序、偏好设置和通道交付
elevenlabs、google、microsoft和openai拥有合成实现voice-call消费电信 TTS 运行时辅助工具
多能力公司插件示例
从外部看,公司插件应该是内聚的。如果 OpenClaw 对模型、语音、实时转录、实时语音、媒体理解、图像生成、视频生成、网页抓取和网页搜索拥有共享契约,那么某个厂商可以在一个地方拥有它的全部表面:- 一个插件拥有厂商表面
- core 仍然拥有能力契约
- 提供方请求转换和 HTTP 辅助工具保留在厂商插件中
- 通道和功能插件消费
api.runtime.*辅助工具,而不是厂商代码 - 契约测试可以断言插件注册了它声称拥有的能力
能力示例:视频理解
OpenClaw 已经将图像/音频/视频理解视为一个共享能力。相同的所有权模型也适用于这里:1
Core 定义契约
core 定义媒体理解契约。
2
厂商插件注册
厂商插件按需注册
describeImage、transcribeAudio 和 describeVideo。3
消费者使用共享行为
通道和功能插件消费共享的 core 行为,而不是直接连接到厂商代码。
api.registerVideoGenerationProvider(...) 实现。
需要一个具体的落地清单吗?请参见 能力食谱。
契约与约束
插件 API 表面被有意设计为类型化并集中在OpenClawPluginApi 中。该契约定义了插件可用的注册点,以及插件可以依赖的运行时辅助工具。
这之所以重要,是因为:
- 插件作者获得了一个稳定的内部标准
- core 可以拒绝重复所有权,例如两个插件注册相同的 provider id
- 启动时可以针对格式错误的注册提供可执行的诊断信息
- 契约测试可以强制执行打包插件的所有权并防止悄然漂移
运行时注册约束
运行时注册约束
插件注册表会在插件加载时校验注册。示例:重复的 provider id、重复的 speech provider id 以及格式错误的注册会生成插件诊断,而不是未定义行为。
契约测试
契约测试
在测试运行期间,会将打包插件捕获到契约注册表中,以便 OpenClaw 能明确断言所有权。当前这用于模型提供方、语音提供方、网页搜索提供方以及打包注册所有权。
契约中应该包含什么
- 好的契约
- 坏的契约
- 类型化
- 小而精
- 面向特定能力
- 由 core 拥有
- 可被多个插件复用
- 通道/功能可消费且无需了解厂商细节
执行模型
原生 OpenClaw 插件和网关在同一进程内运行。它们未进行沙箱隔离。已加载的原生插件与核心代码共享相同的进程级信任边界。 默认情况下,兼容的 bundle 更安全,因为 OpenClaw 目前将它们视为元数据/内容包。在当前版本中,这主要指捆绑的技能。 对于非捆绑插件,请使用允许列表以及明确的安装/加载路径。将工作区插件视为开发时代码,而不是生产环境默认配置。 对于捆绑的工作区包名称,请将插件 id 与 npm 名称绑定:默认使用@openclaw/<id>,或者在包有意暴露更窄的插件角色时,使用经批准的类型后缀,例如 -provider、-plugin、-speech、-sandbox 或 -media-understanding。
信任说明:
plugins.allow 信任的是插件 id,而不是来源。与捆绑插件具有相同 id 的工作区插件,在启用/加入允许列表后,会有意覆盖捆绑版本。这是正常且有用的行为,适用于本地开发、补丁测试和热修复。捆绑插件的信任来源是源代码快照——即加载时磁盘上的清单和代码——而不是安装元数据。损坏或被替换的安装记录不会悄悄扩大捆绑插件的信任范围,使其超出实际源代码所声明的内容。导出边界
OpenClaw 导出的是能力,而不是实现便利性。 保持能力注册为公开。裁剪非契约型的辅助导出:- 打包插件特定的辅助子路径
- 不打算作为公共 API 的运行时管道子路径
- 供应商特定的便利辅助工具
- 作为实现细节的设置/引导辅助工具
plugin-sdk/gateway-runtime、plugin-sdk/security-runtime 以及注入的插件 API 能力。