Plugins (Extensions)
快速开始(插件新手?)
插件只是一个小型代码模块,用于通过额外功能扩展 openclaw (命令、工具和网关 RPC)。
大多数情况下,当您想要一个尚未内置到核心 openclaw 中的功能时 (或者您希望将可选功能排除在主安装之外),您会使用插件。
快速路径:
- 查看已加载的内容:
openclaw plugins list- 安装官方插件(示例:语音通话):
openclaw plugins install @openclaw/voice-call- 重启网关,然后在
plugins.entries.<id>.config下进行配置。
有关具体示例插件,请参阅 语音通话。
可用插件(官方)
- Microsoft Teams 自 2026.1.15 起仅作为插件提供;如果您使用 Teams,请安装
@openclaw/msteams。 - 内存(核心)— 捆绑的内存搜索插件(默认通过
plugins.slots.memory启用) - 内存(LanceDB)— 捆绑的长期内存插件(自动回忆/捕获;设置
plugins.slots.memory = "memory-lancedb") - 语音通话 —
@openclaw/voice-call - Zalo 个人版 —
@openclaw/zalouser - Matrix —
@openclaw/matrix - Nostr —
@openclaw/nostr - Zalo —
@openclaw/zalo - Microsoft Teams —
@openclaw/msteams - Google Antigravity OAuth(提供商认证)— 捆绑为
google-antigravity-auth(默认禁用) - Gemini CLI OAuth(提供商认证)— 捆绑为
google-gemini-cli-auth(默认禁用) - Qwen OAuth(提供商认证)— 捆绑为
qwen-portal-auth(默认禁用) - Copilot 代理(提供商认证)— 本地 VS Code Copilot 代理桥接;与内置的
github-copilot设备登录不同(捆绑,默认禁用)
openclaw 插件是通过 jiti 在运行时加载的 TypeScript 模块。配置 验证不执行插件代码;而是使用插件清单和 JSON Schema。 请参阅 插件清单。
插件可以注册:
- 网关 RPC 方法
- 网关 HTTP 处理器
- 智能体工具
- CLI 命令
- 后台服务
- 可选的配置验证
- 技能(通过在插件清单中列出
skills目录) - 自动回复命令(无需调用 AI 智能体即可执行)
插件与网关同进程运行,因此请将它们视为受信任的代码。 工具编写指南:插件智能体工具。
运行时助手
插件可以通过 api.runtime 访问选定的核心助手。对于电话 TTS:
const result = await api.runtime.tts.textToSpeechTelephony({
text: "Hello from openclaw",
cfg: api.config,
});注意事项:
- 使用核心
messages.tts配置(OpenAI 或 ElevenLabs)。 - 返回 PCM 音频缓冲区 + 采样率。插件必须为提供商重新采样/编码。
- Edge TTS 不支持电话。
发现与优先级
openclaw 按顺序扫描:
- 配置路径
plugins.load.paths(文件或目录)
- 工作空间扩展
<workspace>/.clawdbot/extensions/*.ts<workspace>/.clawdbot/extensions/*/index.ts
- 全局扩展
~/.clawdbot/extensions/*.ts~/.clawdbot/extensions/*/index.ts
- 捆绑扩展(随 openclaw 提供,默认禁用)
<openclaw>/extensions/*
捆绑插件必须通过 plugins.entries.<id>.enabled 或 openclaw plugins enable <id> 显式启用。 安装的插件默认启用,但可以通过相同方式禁用。
每个插件必须在根目录中包含一个 openclaw.plugin.json 文件。如果路径 指向一个文件,插件根目录是该文件所在的目录,并且必须包含清单。
如果多个插件解析为相同的 ID,则按上述顺序第一个匹配的插件胜出, 优先级较低的副本将被忽略。
包包
插件目录可以包含带有 openclaw.extensions 的 package.json:
{
"name": "my-pack",
"openclaw": {
"extensions": ["./src/safety.ts", "./src/tools.ts"]
}
}每个条目都成为一个插件。如果包列出多个扩展,插件 ID 变为 name/<fileBase>。
如果您的插件导入 npm 依赖项,请在该目录中安装它们,以便 node_modules 可用(npm install / pnpm install)。
频道目录元数据
频道插件可以通过 openclaw.channel 宣传入门元数据,并通过 openclaw.install 提供安装提示。这使核心目录保持无数据。
示例:
{
"name": "@openclaw/nextcloud-talk",
"openclaw": {
"extensions": ["./index.ts"],
"channel": {
"id": "nextcloud-talk",
"label": "Nextcloud Talk",
"selectionLabel": "Nextcloud Talk(自托管)",
"docsPath": "/channels/nextcloud-talk",
"docsLabel": "nextcloud-talk",
"blurb": "通过 Nextcloud Talk webhook 机器人进行自托管聊天。",
"order": 65,
"aliases": ["nc-talk", "nc"]
},
"install": {
"npmSpec": "@openclaw/nextcloud-talk",
"localPath": "extensions/nextcloud-talk",
"defaultChoice": "npm"
}
}
}openclaw 还可以合并外部频道目录(例如,MPM 注册表导出)。将 JSON 文件放在以下位置之一:
~/.clawdbot/mpm/plugins.json~/.clawdbot/mpm/catalog.json~/.clawdbot/plugins/catalog.json
或者将 CLAWDBOT_PLUGIN_CATALOG_PATHS(或 CLAWDBOT_MPM_CATALOG_PATHS)指向 一个或多个 JSON 文件(逗号/分号/PATH 分隔)。每个文件应 包含 { "entries": [ { "name": "@scope/pkg", "openclaw": { "channel": {...}, "install": {...} } } ] }。
插件 ID
默认插件 ID:
- 包包:
package.jsonname - 独立文件:文件基本名称(
~/.../voice-call.ts→voice-call)
如果插件导出 id,openclaw 会使用它,但当它与配置的 ID 不匹配时会发出警告。
配置
{
plugins: {
enabled: true,
allow: ["voice-call"],
deny: ["untrusted-plugin"],
load: { paths: ["~/Projects/oss/voice-call-extension"] },
entries: {
"voice-call": { enabled: true, config: { provider: "twilio" } }
}
}
}字段:
enabled:主开关(默认:true)allow:允许列表(可选)deny:拒绝列表(可选;拒绝优先)load.paths:额外的插件文件/目录entries.<id>:每个插件的开关 + 配置
配置更改需要重启网关。
验证规则(严格):
entries、allow、deny或slots中的未知插件 ID 是错误。channels.<id>中的未知键是错误,除非插件清单声明了该频道 ID。- 插件配置使用嵌入在
openclaw.plugin.json中的 JSON Schema(configSchema)进行验证。 - 如果插件被禁用,其配置将被保留并发出警告。
插件插槽(独占类别)
某些插件类别是独占的(一次只能激活一个)。使用 plugins.slots 来选择哪个插件拥有该插槽:
{
plugins: {
slots: {
memory: "memory-core" // 或 "none" 以禁用内存插件
}
}
}如果多个插件声明 kind: "memory",则只加载选定的插件。其他 插件将被禁用并显示诊断信息。
控制界面(架构 + 标签)
控制界面使用 config.schema(JSON Schema + uiHints)来渲染更好的表单。
openclaw 根据发现的插件在运行时增强 uiHints:
- 为
plugins.entries.<id>/.enabled/.config添加每个插件的标签 - 合并插件提供的可选配置字段提示到:
plugins.entries.<id>.config.<field>
如果您希望插件配置字段显示良好的标签/占位符(并将机密标记为敏感), 请在插件清单中与 JSON Schema 一起提供 uiHints。
示例:
{
"id": "my-plugin",
"configSchema": {
"type": "object",
"additionalProperties": false,
"properties": {
"apiKey": { "type": "string" },
"region": { "type": "string" }
}
},
"uiHints": {
"apiKey": { "label": "API 密钥", "sensitive": true },
"region": { "label": "区域", "placeholder": "us-east-1" }
}
}CLI
openclaw plugins list
openclaw plugins info <id>
openclaw plugins install <path> # 将本地文件/目录复制到 ~/.clawdbot/extensions/<id>
openclaw plugins install ./extensions/voice-call # 相对路径可用
openclaw plugins install ./plugin.tgz # 从本地 tarball 安装
openclaw plugins install ./plugin.zip # 从本地 zip 安装
openclaw plugins install -l ./extensions/voice-call # 链接(不复制)用于开发
openclaw plugins install @openclaw/voice-call # 从 npm 安装
openclaw plugins update <id>
openclaw plugins update --all
openclaw plugins enable <id>
openclaw plugins disable <id>
openclaw plugins doctorplugins update 仅适用于在 plugins.installs 下跟踪的 npm 安装。
插件也可以注册自己的顶级命令(例如:openclaw voicecall)。
插件 API(概述)
插件可以导出以下两种形式之一:
- 函数:
(api) => { ... } - 对象:
{ id, name, configSchema, register(api) { ... } }
插件钩子
插件可以打包钩子并在运行时注册它们。这使得插件可以捆绑 事件驱动的自动化,而无需单独安装钩子包。
示例
import { registerPluginHooksFromDir } from "openclaw/plugin-sdk";
export default function register(api) {
registerPluginHooksFromDir(api, "./hooks");
}注意事项:
- 钩子目录遵循正常的钩子结构(
HOOK.md+handler.ts)。 - 钩子资格规则仍然适用(操作系统/二进制文件/环境/配置要求)。
- 插件管理的钩子会出现在
openclaw hooks list中,带有plugin:<id>前缀。 - 您不能通过
openclaw hooks启用/禁用插件管理的钩子;而是启用/禁用插件本身。
提供商插件(模型认证)
插件可以注册模型提供商认证流程,以便用户可以在 openclaw 内部运行 OAuth 或 API 密钥设置(无需外部脚本)。
通过 api.registerProvider(...) 注册提供商。每个提供商公开一个 或多个认证方法(OAuth、API 密钥、设备代码等)。这些方法支持:
openclaw models auth login --provider <id> [--method <id>]
示例:
api.registerProvider({
id: "acme",
label: "AcmeAI",
auth: [
{
id: "oauth",
label: "OAuth",
kind: "oauth",
run: async (ctx) => {
// 运行 OAuth 流程并返回认证配置文件。
return {
profiles: [
{
profileId: "acme:default",
credential: {
type: "oauth",
provider: "acme",
access: "...",
refresh: "...",
expires: Date.now() + 3600 * 1000,
},
},
],
defaultModel: "acme/opus-1",
};
},
},
],
});注意事项:
run接收一个ProviderAuthContext,包含prompter、runtime、openUrl和oauth.createVpsAwareHandlers助手。- 当您需要添加默认模型或提供商配置时,返回
configPatch。 - 返回
defaultModel,以便--set-default可以更新智能体默认值。
注册消息频道
插件可以注册频道插件,其行为类似于内置频道 (WhatsApp、Telegram 等)。频道配置位于 channels.<id> 下,并由 您的频道插件代码验证。
const myChannel = {
id: "acmechat",
meta: {
id: "acmechat",
label: "AcmeChat",
selectionLabel: "AcmeChat (API)",
docsPath: "/channels/acmechat",
blurb: "演示频道插件。",
aliases: ["acme"],
},
capabilities: { chatTypes: ["direct"] },
config: {
listAccountIds: (cfg) => Object.keys(cfg.channels?.acmechat?.accounts ?? {}),
resolveAccount: (cfg, accountId) =>
(cfg.channels?.acmechat?.accounts?.[accountId ?? "default"] ?? { accountId }),
},
outbound: {
deliveryMode: "direct",
sendText: async () => ({ ok: true }),
},
};
export default function (api) {
api.registerChannel({ plugin: myChannel });
}注意事项:
- 将配置放在
channels.<id>下(而不是plugins.entries)。 meta.label用于 CLI/UI 列表中的标签。meta.aliasesadds alternate ids for normalization and CLI inputs.meta.preferOverlists channel ids to skip auto-enable when both are configured.meta.detailLabelandmeta.systemImagelet UIs show richer channel labels/icons.
编写新的消息频道(逐步指南)
当您想要一个新的聊天界面(一个"消息频道"),而不是模型提供商时,请使用此方法。 模型提供商的文档位于 /providers/*。
- 选择一个 ID + 配置结构
- 所有频道配置都位于
channels.<id>下。 - 对于多账户设置,优先使用
channels.<id>.accounts.<accountId>。
- 定义频道元数据
meta.label、meta.selectionLabel、meta.docsPath、meta.blurb控制 CLI/UI 列表。meta.docsPath应指向类似/channels/<id>的文档页面。meta.preferOver允许插件替换另一个频道(自动启用时优先选择)。meta.detailLabel和meta.systemImage被 UI 用于详细文本/图标。
- 实现必需的适配器
config.listAccountIds+config.resolveAccountcapabilities(聊天类型、媒体、线程等)outbound.deliveryMode+outbound.sendText(用于基本发送)
- 根据需要添加可选适配器
setup(向导)、security(私信策略)、status(健康/诊断)gateway(启动/停止/登录)、mentions、threading、streamingactions(消息操作)、commands(原生命令行为)
- 在插件中注册频道
api.registerChannel({ plugin })
最小配置示例:
{
channels: {
acmechat: {
accounts: {
default: { token: "ACME_TOKEN", enabled: true }
}
}
}
}最小频道插件(仅出站):
const plugin = {
id: "acmechat",
meta: {
id: "acmechat",
label: "AcmeChat",
selectionLabel: "AcmeChat (API)",
docsPath: "/channels/acmechat",
blurb: "AcmeChat 消息频道。",
aliases: ["acme"],
},
capabilities: { chatTypes: ["direct"] },
config: {
listAccountIds: (cfg) => Object.keys(cfg.channels?.acmechat?.accounts ?? {}),
resolveAccount: (cfg, accountId) =>
(cfg.channels?.acmechat?.accounts?.[accountId ?? "default"] ?? { accountId }),
},
outbound: {
deliveryMode: "direct",
sendText: async ({ text }) => {
// 在此处将 `text` 传递到您的频道
return { ok: true };
},
},
};
export default function (api) {
api.registerChannel({ plugin });
}加载插件(扩展目录或 plugins.load.paths),重启网关, 然后在配置中配置 channels.<id>。
智能体工具
请参阅专用指南:插件智能体工具。
注册网关 RPC 方法
export default function (api) {
api.registerGatewayMethod("myplugin.status", ({ respond }) => {
respond(true, { ok: true });
});
}注册 CLI 命令
export default function (api) {
api.registerCli(({ program }) => {
program.command("mycmd").action(() => {
console.log("Hello");
});
}, { commands: ["mycmd"] });
}注册自动回复命令
插件可以注册自定义斜杠命令,这些命令执行时无需调用 AI 智能体。这对于切换命令、状态检查或不需要 LLM 处理的快速操作非常有用。
export default function (api) {
api.registerCommand({
name: "mystatus",
description: "显示插件状态",
handler: (ctx) => ({
text: `插件正在运行!频道:${ctx.channel}`,
}),
});
}命令处理程序上下文:
senderId:发送者的 ID(如果可用)channel:发送命令的频道isAuthorizedSender:发送者是否为授权用户args:命令后传递的参数(如果acceptsArgs: true)commandBody:完整的命令文本config:当前的 openclaw 配置
命令选项:
name:命令名称(不带前导/)description:在命令列表中显示的帮助文本acceptsArgs:命令是否接受参数(默认:false)。如果为 false 且提供了参数,命令将不匹配,消息将传递给其他处理程序requireAuth:是否需要授权发送者(默认:true)handler:返回{ text: string }的函数(可以是异步的)
带授权和参数的示例:
api.registerCommand({
name: "setmode",
description: "设置插件模式",
acceptsArgs: true,
requireAuth: true,
handler: async (ctx) => {
const mode = ctx.args?.trim() || "default";
await saveMode(mode);
return { text: `模式设置为:${mode}` };
},
});注意事项:
- 插件命令在内置命令和 AI 智能体之前处理
- 命令全局注册,可在所有频道使用
- 命令名称不区分大小写(
/MyStatus匹配/mystatus) - 命令名称必须以字母开头,只能包含字母、数字、连字符和下划线
- 保留命令名称(如
help、status、reset等)不能被插件覆盖 - 跨插件重复注册命令将失败并显示诊断错误
注册后台服务
export default function (api) {
api.registerService({
id: "my-service",
start: () => api.logger.info("准备就绪"),
stop: () => api.logger.info("再见"),
});
}命名约定
- 网关方法:
pluginId.action(示例:voicecall.status) - 工具:
snake_case(示例:voice_call) - CLI 命令:kebab 或 camel,但避免与核心命令冲突
技能
插件可以在仓库中附带一个技能(skills/<name>/SKILL.md)。 通过 plugins.entries.<id>.enabled(或其他配置门控)启用它,并确保 它存在于您的工作空间/托管技能位置中。
分发(npm)
推荐的打包方式:
- 主包:
openclaw(此仓库) - 插件:单独的 npm 包,位于
@openclaw/*下(示例:@openclaw/voice-call)
发布约定:
- 插件的
package.json必须包含openclaw.extensions,其中包含一个或多个入口文件。 - 入口文件可以是
.js或.ts(jiti 在运行时加载 TS)。 openclaw plugins install <npm-spec>使用npm pack,提取到~/.clawdbot/extensions/<id>/中,并在配置中启用它。- 配置键稳定性:作用域包被规范化为 无作用域 的 ID,用于
plugins.entries.*。
示例插件:语音通话
此仓库包含一个语音通话插件(Twilio 或日志回退):
- 源代码:
extensions/voice-call - 技能:
skills/voice-call - CLI:
openclaw voicecall start|status - 工具:
voice_call - RPC:
voicecall.start、voicecall.status - 配置(twilio):
provider: "twilio"+twilio.accountSid/authToken/from(可选statusCallbackUrl、twimlUrl) - 配置(开发):
provider: "log"(无网络)
有关设置和用法,请参阅 语音通话 和 extensions/voice-call/README.md。
安全注意事项
插件与网关在同一进程中运行。将它们视为受信任的代码:
- 仅安装您信任的插件。
- 优先使用
plugins.allow允许列表。 - 更改后重新启动网关。
测试插件
插件可以(并且应该)附带测试:
- 仓库内的插件可以将 Vitest 测试放在
src/**下(示例:src/plugins/voice-call.plugin.test.ts)。 - 单独发布的插件应该运行自己的 CI(lint/build/test)并验证
openclaw.extensions指向构建的入口点(dist/index.js)。