OpenClaw 的插件体系由“插件清单 + 运行时注册 + 严格配置校验”构成。官方文档对插件发现顺序、加载路径、安全策略与缓存机制有明确规范;通道插件通过 api.registerChannel 注册消息适配器;工具插件通过 api.registerTool 注册可被代理调用的工具;集成插件则结合 HTTP 路由、生命周期钩子与服务管理实现深度集成。
graph TB
subgraph "插件目录"
VC["extensions/voice-call"]
DC["extensions/discord"]
TG["extensions/telegram"]
LB["extensions/lobster"]
LLM["extensions/llm-task"]
MC["extensions/memory-core"]
ML["extensions/memory-lancedb"]
end
subgraph "插件清单"
VC_JSON["openclaw.plugin.json"]
DC_JSON["openclaw.plugin.json"]
TG_JSON["openclaw.plugin.json"]
end
VC --> VC_JSON
DC --> DC_JSON
TG --> TG_JSON
subgraph "运行时"
API["OpenClawPluginApi"]
REG["registerChannel/registerTool/registerGatewayMethod"]
end
VC --> API
DC --> API
TG --> API
LB --> API
LLM --> API
MC --> API
ML --> API
API --> REG
核心组件
- 插件清单与 JSON Schema:所有插件必须提供 openclaw.plugin.json,并内置 configSchema 用于严格配置校验,避免执行插件代码即可完成验证。
- 插件注册接口:通过 OpenClawPluginApi 提供的 registerChannel、registerTool、registerGatewayMethod、registerCli、registerService、registerHook 等能力,将功能注入到网关与代理运行时。
- 通道插件:负责消息出站/入站适配,统一对外暴露为“频道”,支持多账号、能力声明、安全策略与状态诊断。
- 工具插件:封装系统命令或外部 API,以类型化的参数与返回值形式供代理调用,支持沙箱与可选注册。
- 集成插件:结合 HTTP 路由、生命周期钩子与服务管理,实现第三方服务的深度集成与自动化。
架构总览
下图展示了插件在 OpenClaw 网关中的位置与交互方式:客户端通过 WebSocket 连接网关,网关根据插件注册的方法与工具进行消息路由与执行;通道插件负责具体消息渠道的收发;工具插件提供可被代理调用的能力;集成插件通过 HTTP 路由与钩子扩展系统行为。
sequenceDiagram
participant Client as "客户端(WS)"
participant Gateway as "网关"
participant Plugin as "插件(通道/工具/集成)"
participant Ext as "外部服务"
Client->>Gateway : "连接/请求"
Gateway->>Plugin : "调用已注册方法/工具"
Plugin->>Ext : "HTTP/SDK/系统命令"
Ext-->>Plugin : "响应/事件"
Plugin-->>Gateway : "结果/事件"
Gateway-->>Client : "响应/事件推送"
详细组件分析
消息适配器插件示例:Telegram 与 Discord
这两个插件属于“通道插件”,通过 api.registerChannel 将外部消息平台接入 OpenClaw 的统一消息面。它们的共同特征是:
- 在 openclaw.plugin.json 中声明 channels 字段,标识该插件注册了哪些频道。
- 在 index.ts 中导入通道实现与运行时设置函数,完成注册与钩子绑定。
- 通道插件通常包含配置解析、账户解析、能力声明、出站发送等适配器。
classDiagram
class TelegramPlugin {
+id : string
+name : string
+description : string
+configSchema : object
+register(api)
}
class DiscordPlugin {
+id : string
+name : string
+description : string
+configSchema : object
+register(api)
}
class ChannelPlugin {
+id : string
+meta : object
+capabilities : object
+config : object
+outbound : object
+registerChannel()
}
TelegramPlugin --> ChannelPlugin : "注册"
DiscordPlugin --> ChannelPlugin : "注册"
工具插件示例:Lobster 与 LLM Task
工具插件通过 api.registerTool 将可被代理调用的工具注册到运行时,支持沙箱环境下的可选注册与类型化参数校验。示例包括:
- Lobster:提供可恢复审批的类型化工作流工具,支持沙箱条件下的选择性注册。
- LLM Task:提供结构化任务的 JSON-only 工具,支持默认模型、鉴权配置与超时控制。
flowchart TD
Start(["工具调用入口"]) --> CheckSandbox["检查沙箱环境"]
CheckSandbox --> |允许| CreateTool["创建工具实例"]
CheckSandbox --> |不允许| Deny["返回空(禁用)"]
CreateTool --> Register["api.registerTool(...)"]
Register --> End(["可用"])
Deny --> End
集成插件示例:Voice Call(消息适配器+工具+服务)
Voice Call 插件是“通道插件 + 工具插件 + 服务”的综合示例,展示了如何:
- 通过 openclaw.plugin.json 定义复杂的配置 Schema(含提供商、TTS/STT、隧道、流式通话等)。
- 在 index.ts 中注册多个网关方法(如 voicecall.initiate、voicecall.continue、voicecall.speak、voicecall.end、voicecall.status、voicecall.start),并通过工具接口提供统一的工具调用入口。
- 通过 api.registerService 管理生命周期(启动/停止),并在失败时记录日志。
- 通过 ensureRuntime 延迟初始化与错误重试控制,避免资源泄漏。
sequenceDiagram
participant Client as "客户端"
participant Gateway as "网关"
participant VC as "Voice Call 插件"
participant RT as "运行时/管理器"
participant Provider as "提供商(Twilio/Telnyx)"
Client->>Gateway : "voicecall.initiate"
Gateway->>VC : "调用注册方法"
VC->>RT : "ensureRuntime()"
RT-->>VC : "返回运行时"
VC->>Provider : "发起呼叫"
Provider-->>VC : "返回结果"
VC-->>Gateway : "响应{callId}"
Gateway-->>Client : "确认"
集成插件示例:Memory Core 与 Memory (LanceDB)
这两个插件属于“内存/记忆”类插件,分别代表两类集成模式:
- Memory Core:基于文件系统的轻量级搜索与 CLI 工具,通过 api.registerTool 注册 memory_search 与 memory_get,并提供 CLI 子命令。
- Memory (LanceDB):基于向量数据库的长期记忆,包含自动召回与自动捕获的生命周期钩子、CLI 命令、HTTP 路由与服务管理,同时具备提示注入防护与去重策略。
flowchart TD
A["before_agent_start"] --> B["embed(prompt)"]
B --> C["db.search(vector, limit)"]
C --> D{"命中?"}
D --> |是| E["prependContext 注入"]
D --> |否| F["跳过"]
subgraph "agent_end"
G["提取用户消息文本"] --> H["shouldCapture 过滤"]
H --> I{"可捕获?"}
I --> |是| J["embed -> store"]
I --> |否| K["跳过"]
end
依赖关系分析
- 插件发现与加载:官方文档规定了从“配置路径 → 工作区扩展 → 全局扩展 → 内置扩展”的优先级顺序,且对路径安全性与缓存策略有明确要求。
- 清单与 Schema:每个插件必须提供 openclaw.plugin.json 与 configSchema,缺失或无效将导致验证失败。
- 运行时接口:插件通过 OpenClawPluginApi 的子路径导入(如 plugin-sdk/telegram、plugin-sdk/discord 等)获得特定平台的适配器与工具。
graph LR
P["插件清单(openclaw.plugin.json)"] --> V["配置校验(JSON Schema)"]
V --> R["运行时注册(register*)"]
R --> G["网关/代理"]
性能考量
- 缓存与延迟初始化:Voice Call 插件通过 ensureRuntime 与运行时 Promise 缓存避免重复初始化;Memory (LanceDB) 插件采用惰性初始化与向量维度预计算降低冷启动成本。
- 资源释放:Voice Call 插件在服务停止时重置运行时引用,防止端口孤儿与内存泄漏。
- I/O 与网络:通道插件与集成插件应限制并发、设置超时与重试策略,避免阻塞网关主循环。
- 日志与可观测性:通过 api.logger 输出关键事件与错误,便于定位性能瓶颈。
工具插件
OpenClaw 的插件体系由“插件 SDK + 多个具体插件”构成。插件以模块形式组织在 extensions 目录下,每个插件通常包含:
- 插件入口文件(index.ts):定义插件注册逻辑、工具、命令、服务与生命周期钩子
- 配置文件(openclaw.plugin.json):声明插件 ID、类型、UI 提示与配置模式
- 可选的内部模块(如通知、配置解析等)
graph TB
subgraph "插件SDK"
SDK["src/plugin-sdk/index.ts<br/>导出插件API与类型"]
TYPES["src/plugins/types.ts<br/>插件类型与钩子定义"]
end
subgraph "内存工具插件"
MEM_CORE["extensions/memory-core/index.ts"]
MEM_LANCE["extensions/memory-lancedb/index.ts"]
CFG["extensions/memory-lancedb/config.ts"]
MEM_JSON["extensions/memory-lancedb/openclaw.plugin.json"]
end
subgraph "系统工具插件"
DEV_PAIR["extensions/device-pair/index.ts"]
DEV_NOTIFY["extensions/device-pair/notify.ts"]
PHONE_CTRL["extensions/phone-control/index.ts"]
VOICE_CALL["extensions/voice-call/index.ts"]
DEV_JSON["extensions/device-pair/openclaw.plugin.json"]
PHONE_JSON["extensions/phone-control/openclaw.plugin.json"]
VOICE_JSON["extensions/voice-call/openclaw.plugin.json"]
end
SDK --> MEM_CORE
SDK --> MEM_LANCE
SDK --> DEV_PAIR
SDK --> PHONE_CTRL
SDK --> VOICE_CALL
CFG --> MEM_LANCE
MEM_JSON --> MEM_LANCE
DEV_JSON --> DEV_PAIR
PHONE_JSON --> PHONE_CTRL
VOICE_JSON --> VOICE_CALL
核心组件
本节概述 OpenClaw 插件系统的关键能力与约定,为后续各插件实现提供统一参考。
-
插件 API(OpenClawPluginApi)
- 注册工具:registerTool
- 注册命令:registerCommand
- 注册网关方法:registerGatewayMethod
- 注册 CLI:registerCli
- 注册服务:registerService
- 生命周期钩子:on(支持 before_agent_start、agent_end、before_tool_call、after_tool_call 等)
- 路径解析:resolvePath
- 日志:logger
- 运行时访问:runtime(用于访问工具工厂、配置、状态目录等)
-
插件类型与钩子
- OpenClawPluginConfigSchema:支持 parse/safeParse/validate/uiHints/jsonSchema
- PluginHookName:定义可用的生命周期钩子名称集合
- PluginHookHandlerMap:按钩子名映射处理器签名
-
插件命令上下文(PluginCommandContext)
- 包含发送者标识、通道、授权状态、账户 ID、线程 ID 等
- 返回值为 ReplyPayload,统一消息格式
-
插件服务(OpenClawPluginService)
- 支持 start/stop 生命周期,常用于定时任务或后台守护
架构总览
OpenClaw 插件通过统一的 API 将“工具、命令、网关方法、CLI、服务与生命周期钩子”整合到运行时环境。下图展示了典型调用链路:
sequenceDiagram
participant User as "用户/渠道"
participant Cmd as "插件命令"
participant API as "OpenClawPluginApi"
participant Tools as "工具注册器"
participant Runtime as "运行时"
participant DB as "数据库/LanceDB"
User->>Cmd : 触发命令
Cmd->>API : 解析参数/鉴权
API->>Runtime : 访问工具工厂/配置
API->>Tools : registerTool(...)
Tools->>Runtime : 创建工具实例
Tools->>DB : 读写/查询
DB-->>Tools : 结果
Tools-->>API : 工具执行结果
API-->>Cmd : ReplyPayload
Cmd-->>User : 回复
详细组件分析
内存工具插件(LanceDB)
该插件提供长短期记忆的向量检索与自动捕获/召回能力,核心特性:
- 向量嵌入:使用 OpenAI Embeddings 生成文本向量
- 存储:基于 LanceDB 的向量表,支持相似度搜索与去重
- 自动捕获:在会话结束时自动提取并存储重要信息
- 自动召回:在对话前注入相关记忆上下文
- CLI 命令:ltm list/search/stats
- 工具:memory_recall/memory_store/memory_forget
classDiagram
class MemoryDB {
-db
-table
-initPromise
+store(entry)
+search(vector, limit, minScore)
+delete(id)
+count()
}
class Embeddings {
-client
+embed(text)
}
class MemoryPlugin {
+register(api)
+shouldCapture(text, options)
+detectCategory(text)
+formatRelevantMemoriesContext(memories)
}
MemoryPlugin --> MemoryDB : "使用"
MemoryPlugin --> Embeddings : "使用"
sequenceDiagram
participant Agent as "代理"
participant API as "OpenClawPluginApi"
participant Embed as "Embeddings"
participant DB as "MemoryDB"
participant Tools as "工具"
Agent->>API : before_agent_start
API->>Embed : embed(prompt)
Embed-->>API : 向量
API->>DB : search(vector, limit, minScore)
DB-->>API : 搜索结果
API-->>Agent : prependContext(记忆上下文)
Agent->>API : agent_end
API->>Tools : 提取用户消息
API->>Embed : embed(候选文本)
API->>DB : search(vector, 1, 0.95)
DB-->>API : 是否重复
API->>DB : store(新记忆)
DB-->>API : 成功
-
参数验证与配置
- 使用 memoryConfigSchema 对插件配置进行解析与校验
- 支持环境变量占位符替换(如 ${OPENAI_API_KEY})
- 默认数据库路径与模型维度映射
-
工具注册与执行
- registerTool 注册 memory_recall/memory_store/memory_forget
- 执行时进行参数校验、向量化、去重检查与结果序列化
-
CLI 与服务
- registerCli 注册 ltm 子命令
- registerService 启停日志输出
设备配对工具插件
该插件用于生成配对码、批准设备请求,并支持 Telegram 通知订阅与一次性提醒。
- 关键流程
- 生成配对码:编码网关 URL、认证方式与令牌
- 批准请求:approveDevicePairing 并返回批准结果
- 通知:Telegram 订阅与轮询推送新请求
- URL 解析:优先 publicUrl,其次 Tailscale Serve/Funnel,再回退到本地绑定
sequenceDiagram
participant User as "用户"
participant Cmd as "命令处理器"
participant Pair as "设备配对"
participant Notify as "通知服务"
participant Gate as "网关URL解析"
User->>Cmd : /pair
Cmd->>Gate : 解析网关URL
Gate-->>Cmd : URL/错误
Cmd->>Pair : 生成配对码
Pair-->>Cmd : 配对码/说明
Cmd-->>User : 发送配对码/二维码
Notify->>Pair : 轮询待批准列表
Notify-->>User : 推送新请求提醒
-
参数与鉴权解析
- 支持 token/password 两种模式,优先从环境变量与配置中解析
- URL 正规化与端口选择策略
-
命令与通知
- /pair status/pending/approve/qr/notify
- 一次性订阅与持久订阅模式
电话控制工具插件
该插件用于临时允许高风险节点命令(相机、屏幕录制、写操作),并支持自动过期与状态持久化。
- 核心能力
- 状态文件:armed.json,记录允许/拒绝命令集与过期时间
- 允许/拒绝列表更新:动态修改配置并写回
- 定时服务:定期检查过期并自动解除武装
- 命令:/phone status/arm/disarm/help
flowchart TD
Start(["进入 /phone 命令"]) --> Parse["解析动作与参数"]
Parse --> Action{"动作类型"}
Action --> |status| ReadState["读取状态文件"]
ReadState --> ReplyStatus["回复当前状态"]
Action --> |arm| UpdateAllow["计算允许/拒绝命令集"]
UpdateAllow --> WriteState["写入状态文件"]
WriteState --> WriteCfg["写回配置"]
WriteCfg --> ReplyArm["回复已临时允许的命令"]
Action --> |disarm| Disarm["恢复允许/拒绝列表"]
Disarm --> ClearState["清空状态文件"]
ClearState --> ReplyDisarm["回复已解除武装"]
Action --> |help| ReplyHelp["回复帮助信息"]
-
状态持久化与版本兼容
- 支持 v1/v2 状态文件格式,自动迁移字段
- 文件原子写入,异常时保留原状
-
自动过期
- 定时服务每 15 秒检查一次,过期后自动解除武装
语音通话工具插件
该插件提供电话呼入呼出能力,支持 Telnyx/Twilio/Plivo 等提供商,并可选实时流式 TTS/STT。
-
网关方法
- voicecall.initiate/continue/speak/end/status/start
- 统一响应格式:success/error + 附加数据
-
工具与 CLI
- registerTool 提供 voice_call 工具
- registerCli 提供 voicecall 子命令
-
配置与校验
- 支持多种提供商配置与敏感字段 UI 提示
- 提供解析与校验函数,确保必要字段存在
sequenceDiagram
participant User as "用户"
participant Tool as "voice_call 工具"
participant API as "OpenClawPluginApi"
participant RT as "VoiceCallRuntime"
participant Provider as "提供商(如 Twilio)"
User->>Tool : 调用 action
Tool->>API : ensureRuntime()
API->>RT : 创建/获取运行时
Tool->>RT : manager.initiateCall/continue/speak/end
RT->>Provider : 发起/继续/播放/结束通话
Provider-->>RT : 结果
RT-->>Tool : 结果
Tool-->>User : JSON 响应
内存核心工具插件
该插件通过运行时工具工厂创建内存搜索与获取工具,并注册 CLI。
-
工具工厂
- createMemorySearchTool / createMemoryGetTool
- 若工厂不可用则返回空
-
CLI
- registerMemoryCli 注册 memory 子命令
依赖关系分析
-
插件 SDK 与类型
- 所有插件均依赖 OpenClawPluginApi 与插件类型定义
- 生命周期钩子与工具签名在 types.ts 中集中定义
-
插件间耦合
- 内存插件依赖 LanceDB 与 OpenAI
- 设备配对插件依赖网关绑定与 Tailscale
- 电话控制插件依赖配置文件系统与定时服务
- 语音通话插件依赖提供商 SDK 与实时流式能力
graph LR
SDK["插件SDK(types.ts)"] --> MEM["内存插件(LanceDB)"]
SDK --> DEV["设备配对"]
SDK --> PHONE["电话控制"]
SDK --> CALL["语音通话"]
MEM --> LANCEDB["@lancedb/lancedb"]
MEM --> OPENAI["OpenAI Embeddings"]
DEV --> BIND["网关绑定/Tailscale"]
PHONE --> CFG["配置文件系统"]
CALL --> PROVIDER["提供商SDK/实时流"]
性能考虑
-
向量搜索与相似度转换
- LanceDB 默认使用 L2 距离,插件将其映射到 0-1 相似度范围,避免额外开销
- 限制返回数量与最小分数阈值,减少序列化与传输成本
-
异步初始化与懒加载
- MemoryDB 与 Embeddings 采用延迟初始化,首次使用时才加载模块与连接数据库
- 语音通话插件运行时采用 Promise 缓存,失败后重置以便下次重试
-
状态持久化与原子写入
- phone-control 使用原子写入与目录创建,避免部分写入导致的状态损坏
- 内存插件对向量数组进行剥离,防止无法克隆的数据结构造成序列化问题
-
定时任务与资源释放
- 设备配对通知服务与电话控制定时器在 stop 时清理,避免资源泄漏
认证插件
认证插件位于 extensions 目录下,每个插件由“入口文件 + 认证流程实现 + 插件清单 + 可选测试”组成;同时,命令层负责调用插件、写入凭据与配置补丁。
graph TB
subgraph "插件层"
GG["google-gemini-cli-auth<br/>入口与OAuth实现"]
MM["minimax-portal-auth<br/>入口与OAuth实现"]
QW["qwen-portal-auth<br/>入口与OAuth实现"]
end
subgraph "SDK与命令层"
SDK_MM["plugin-sdk/minimax-portal-auth.ts"]
SDK_QW["plugin-sdk/qwen-portal-auth.ts"]
CMD_AUTH["commands/models/auth.ts"]
APPLY["commands/auth-choice.apply.plugin-provider.ts"]
end
subgraph "文档与配置"
DOC_OAUTH["docs/concepts/oauth.md"]
DOC_AUTH["docs/gateway/authentication.md"]
DOC_MM["docs/providers/minimax.md"]
DOC_QW["docs/providers/qwen.md"]
end
GG --> CMD_AUTH
MM --> CMD_AUTH
QW --> CMD_AUTH
CMD_AUTH --> APPLY
SDK_MM --> MM
SDK_QW --> QW
CMD_AUTH --> DOC_OAUTH
CMD_AUTH --> DOC_AUTH
DOC_MM --> MM
DOC_QW --> QW
核心组件
- 插件入口:注册 Provider、声明认证方法(kind)、运行时上下文(openUrl、prompter、note、progress)。
- OAuth 实现:封装 PKCE、授权端点、令牌交换、用户信息与项目发现、轮询等待与错误处理。
- 配置补丁:动态注入默认模型、基础 URL、API 类型、成本与上下文窗口等。
- 命令集成:通过 CLI 触发插件认证,写入 auth-profiles.json 并合并 models.json。
架构总览
认证插件遵循“插件定义 → 命令触发 → SDK 调用 → OAuth 执行 → 凭据落盘”的闭环。
sequenceDiagram
participant U as "用户"
participant CLI as "命令行(models/auth)"
participant API as "插件API(ProviderAuthContext)"
participant SDK as "插件SDK(minimax/qwen)"
participant AUTH as "OAuth实现(google-gemini-cli/minimax/qwen)"
participant STORE as "凭据存储(auth-profiles.json)"
U->>CLI : 运行认证命令
CLI->>API : 解析Provider与Method
API->>SDK : 调用认证方法(run)
SDK->>AUTH : 执行OAuth流程(PKCE/轮询/回调)
AUTH-->>SDK : 返回访问令牌/刷新令牌/过期时间/项目ID
SDK-->>API : 构建ProviderAuthResult(含configPatch)
API->>STORE : 写入凭据与配置补丁
STORE-->>CLI : 完成并提示
详细组件分析
Google Gemini CLI 认证插件
- 功能要点
- 支持 PKCE + 本地回调(localhost:8085),自动或手动模式切换。
- 从环境变量或已安装的 Gemini CLI 提取 OAuth 客户端凭据。
- 令牌交换后获取邮箱与项目 ID,必要时通过多端点探测与引导完成项目发现。
- 将结果包装为 ProviderAuthResult,包含默认模型、访问/刷新令牌、过期时间与额外字段。
- 关键流程(远程/WSL2 同步场景)
- 自动打开浏览器并在本地监听回调;若端口占用则回退到手动粘贴回调 URL。
- 多端点探测 loadCodeAssist,兼容 VPC-SC 场景,必要时引导设置 GOOGLE_CLOUD_PROJECT。
- 错误处理
- 状态不匹配、超时、端口占用、缺少刷新令牌、项目发现失败等均抛出明确错误并提示。
sequenceDiagram
participant P as "插件入口(index.ts)"
participant C as "ProviderAuthContext"
participant O as "OAuth(loginGeminiCliOAuth)"
participant G as "Google OAuth端点"
participant U as "用户浏览器"
P->>C : 注册Provider与OAuth方法
C->>O : 调用run()
O->>U : 打开授权URL(PKCE)
alt 本地回调可用
U-->>O : 回调至localhost : 8085
else 端口不可用/远程
O->>C : 提示手动粘贴回调URL
C-->>O : 用户粘贴回调
end
O->>G : 交换授权码为令牌
G-->>O : 返回access/refresh/expires
O->>G : 获取用户邮箱与项目ID
O-->>P : 返回ProviderAuthResult
MiniMax 门户认证插件
- 功能要点
- 设备码登录(device_code),支持 CN 与 Global 区域端点。
- 轮询令牌状态,动态调整轮询间隔,超时/错误时给出明确提示。
- 返回 access/refresh/expires 与可选资源 URL,构建 ProviderAuthResult 并合并 models.json。
- 关键流程
- 申请设备码与用户码,打开验证页,轮询换取令牌,成功后返回并写入配置补丁。
sequenceDiagram
participant P as "插件入口(index.ts)"
participant C as "ProviderAuthContext"
participant O as "OAuth(loginMiniMaxPortalOAuth)"
participant M as "MiniMax OAuth端点"
participant U as "用户浏览器"
P->>C : 注册Provider与OAuth方法
C->>O : 调用run()
O->>M : 申请设备码(PKCE)
M-->>O : 返回user_code/verification_uri/过期时间
O->>U : 打开验证页并提示输入user_code
loop 轮询
O->>M : 以device_code换取令牌
alt pending/slow_down
O->>O : 延长轮询间隔
else success
M-->>O : 返回access/refresh/expires/resourceUrl
O-->>P : 返回ProviderAuthResult
else error
O-->>P : 抛出错误
end
end
Qwen 门户认证插件
- 功能要点
- 设备码登录(device_code),支持 PKCE。
- 轮询等待授权,支持 slow_down 情况下的指数退避。
- 返回 access/refresh/expires 与可选资源 URL,合并默认模型与别名。
- 关键流程
- 申请设备码,打开验证页,轮询换取令牌,成功后写入配置补丁。
sequenceDiagram
participant P as "插件入口(index.ts)"
participant C as "ProviderAuthContext"
participant O as "OAuth(loginQwenPortalOAuth)"
participant Q as "Qwen OAuth端点"
participant U as "用户浏览器"
P->>C : 注册Provider与OAuth方法
C->>O : 调用run()
O->>Q : 申请设备码(PKCE)
Q-->>O : 返回device_code/user_code/verification_uri/过期时间
O->>U : 打开验证页并提示输入user_code
loop 轮询
O->>Q : 以device_code换取令牌
alt authorization_pending
O->>O : 维持轮询
else slow_down
O->>O : 增大轮询间隔
else success
Q-->>O : 返回access/refresh/expires/resourceUrl
O-->>P : 返回ProviderAuthResult
else error
O-->>P : 抛出错误
end
end
插件 SDK 与命令集成
- SDK 暴露
- minimax-portal-auth:导出空配置模式、构建 OAuth 结果、PKCE 工具与表单编码工具。
- qwen-portal-auth:导出空配置模式、构建 OAuth 结果、PKCE 工具与表单编码工具。
- 命令层
- 解析 Provider 与 Method,创建 VPS/远程适配的 OAuth 处理器,执行 run 并写入凭据。
- 应用插件 Provider 的认证选择,启用插件、解析 Provider、选择方法并执行。
依赖关系分析
- 插件对 SDK 的依赖:仅使用 SDK 暴露的最小接口(空配置、PKCE、表单编码、结果构建)。
- 插件对命令层的依赖:通过 ProviderAuthContext 注入 openUrl、note、progress、prompt 等能力。
- 文档与配置:凭据存储位置、多账户路由、刷新与过期策略、API Key 旋转行为等。
graph LR
IDX_GG["google-gemini-cli-auth/index.ts"] --> OAUTH_GG["google-gemini-cli-auth/oauth.ts"]
IDX_MM["minimax-portal-auth/index.ts"] --> OAUTH_MM["minimax-portal-auth/oauth.ts"]
IDX_QW["qwen-portal-auth/index.ts"] --> OAUTH_QW["qwen-portal-auth/oauth.ts"]
SDK_MM["plugin-sdk/minimax-portal-auth.ts"] --> IDX_MM
SDK_QW["plugin-sdk/qwen-portal-auth.ts"] --> IDX_QW
CMD["commands/models/auth.ts"] --> IDX_GG
CMD --> IDX_MM
CMD --> IDX_QW
DOC_OAUTH["docs/concepts/oauth.md"] --> CMD
DOC_AUTH["docs/gateway/authentication.md"] --> CMD
性能与可靠性
- 轮询策略
- MiniMax 与 Qwen 的轮询采用指数退避与最大上限控制,避免频繁请求。
- 端点容错
- Gemini CLI 的项目发现尝试多个端点,兼容不同环境与异常情况。
- 超时与重试
- 明确的超时阈值与错误提示,便于用户快速定位问题。
- 存储与并发
- 凭据写入采用原子更新与文件锁,避免并发冲突。
消息渠道插件
OpenClaw 将每个消息渠道封装为独立的扩展目录,遵循统一的组织规范:
- 扩展根目录:extensions/{channel}
- 插件清单:openclaw.plugin.json(定义插件标识、支持的通道类型、配置模式)
- 入口文件:index.ts(负责注册插件、注入运行时、导出通道插件)
graph TB
subgraph "扩展目录"
D["extensions/discord"]
T["extensions/telegram"]
S["extensions/slack"]
W["extensions/whatsapp"]
end
D --> D_idx["index.ts"]
D --> D_cfg["openclaw.plugin.json"]
T --> T_idx["index.ts"]
T --> T_cfg["openclaw.plugin.json"]
S --> S_idx["index.ts"]
S --> S_cfg["openclaw.plugin.json"]
W --> W_idx["index.ts"]
W --> W_cfg["openclaw.plugin.json"]
核心组件
- 插件清单(openclaw.plugin.json):声明插件 id、支持的通道数组、配置模式(JSON Schema)。用于向系统注册该插件可处理的消息通道类型。
- 插件入口(index.ts):定义插件对象,包含 id、name、description、configSchema,以及 register 回调。register 中完成运行时注入与通道插件注册。
- 通道插件(由各扩展的 src/channel.js 导出):实现具体的消息收发逻辑,供插件入口通过 api.registerChannel 注册使用。
- 运行时注入(runtime):通过各扩展的 runtime 文件设置运行时环境,确保通道插件在正确的上下文中执行。
架构总览
下图展示了从插件入口到通道插件与运行时的整体交互关系:
graph LR
A["OpenClaw 核心"] --> B["插件入口 index.ts"]
B --> C["注册通道插件<br/>api.registerChannel"]
B --> D["注入运行时<br/>set*Runtime(api.runtime)"]
C --> E["通道插件<br/>src/channel.js"]
D --> E
详细组件分析
Discord 插件
- 插件清单:声明 id 为 discord,支持通道类型为 ["discord"],配置模式为空对象。
- 插件入口:注册插件后,设置 Discord 运行时,注册 Discord 通道插件,并注册子代理钩子。
- 通道插件:由扩展目录下的 src/channel.js 提供,作为 ChannelPlugin 注入到核心。
- 运行时注入:setDiscordRuntime(api.runtime) 将运行时注入到通道插件中。
sequenceDiagram
participant Core as "OpenClaw 核心"
participant Plugin as "Discord 插件入口"
participant Runtime as "Discord 运行时"
participant Channel as "Discord 通道插件"
Core->>Plugin : 调用 register(api)
Plugin->>Runtime : setDiscordRuntime(api.runtime)
Plugin->>Core : api.registerChannel({ plugin : Channel })
Plugin->>Core : registerDiscordSubagentHooks(api)
Core-->>Channel : 在运行时上下文中执行
Telegram 插件
- 插件清单:声明 id 为 telegram,支持通道类型为 ["telegram"],配置模式为空对象。
- 插件入口:注册插件后,设置 Telegram 运行时,注册 Telegram 通道插件。
- 通道插件:由扩展目录下的 src/channel.js 提供,作为 ChannelPlugin 注入到核心。
sequenceDiagram
participant Core as "OpenClaw 核心"
participant Plugin as "Telegram 插件入口"
participant Runtime as "Telegram 运行时"
participant Channel as "Telegram 通道插件"
Core->>Plugin : 调用 register(api)
Plugin->>Runtime : setTelegramRuntime(api.runtime)
Plugin->>Core : api.registerChannel({ plugin : Channel })
Core-->>Channel : 在运行时上下文中执行
Slack 插件
- 插件清单:声明 id 为 slack,支持通道类型为 ["slack"],配置模式为空对象。
- 插件入口:注册插件后,设置 Slack 运行时,注册 Slack 通道插件。
- 通道插件:由扩展目录下的 src/channel.js 提供,作为 ChannelPlugin 注入到核心。
sequenceDiagram
participant Core as "OpenClaw 核心"
participant Plugin as "Slack 插件入口"
participant Runtime as "Slack 运行时"
participant Channel as "Slack 通道插件"
Core->>Plugin : 调用 register(api)
Plugin->>Runtime : setSlackRuntime(api.runtime)
Plugin->>Core : api.registerChannel({ plugin : Channel })
Core-->>Channel : 在运行时上下文中执行
WhatsApp 插件
- 插件清单:声明 id 为 whatsapp,支持通道类型为 ["whatsapp"],配置模式为空对象。
- 插件入口:注册插件后,设置 WhatsApp 运行时,注册 WhatsApp 通道插件。
- 通道插件:由扩展目录下的 src/channel.js 提供,作为 ChannelPlugin 注入到核心。
sequenceDiagram
participant Core as "OpenClaw 核心"
participant Plugin as "WhatsApp 插件入口"
participant Runtime as "WhatsApp 运行时"
participant Channel as "WhatsApp 通道插件"
Core->>Plugin : 调用 register(api)
Plugin->>Runtime : setWhatsAppRuntime(api.runtime)
Plugin->>Core : api.registerChannel({ plugin : Channel })
Core-->>Channel : 在运行时上下文中执行
依赖关系分析
- 插件入口依赖 SDK 类型与空配置模式生成器,确保插件对象满足核心要求。
- 插件入口通过 api.registerChannel 注册通道插件,形成“入口 → 通道插件”的直接依赖。
- 插件入口通过 set*Runtime 注入运行时,形成“入口 → 运行时”的依赖链。
- 插件清单 openclaw.plugin.json 决定插件的通道能力与配置约束,是系统识别与加载的关键。
graph TB
IDX["index.ts"] --> REG["api.registerChannel"]
IDX --> RUNTIME["set*Runtime"]
REG --> CH["通道插件"]
RUNTIME --> CH
CFG["openclaw.plugin.json"] --> IDX
CFG --> REG
性能考虑
- 运行时注入:通过 set*Runtime 将运行时注入通道插件,避免重复初始化,提升启动与执行效率。
- 空配置模式:使用 emptyPluginConfigSchema 可减少不必要的配置校验开销,适合无需复杂参数的轻量插件。
- 通道注册:仅在 register 中进行一次 api.registerChannel,避免重复注册导致的资源浪费。
- 错误隔离:在通道插件内部对网络请求与第三方 API 调用进行超时与重试控制,降低失败对整体系统的冲击。
专用插件
OpenClaw 插件体系采用“扩展包”组织方式,每个插件位于独立目录下,包含:
- 扩展包根目录:如 voice-call、bluebubbles、acpx、diagnostics-otel、talk-voice 等
- 插件清单:openclaw.plugin.json,定义插件标识、UI 提示、配置模式与能力声明
- 入口与实现:index.ts(部分插件)或具体模块(如 voice-call 的多提供商适配)
- 技能目录:如 acpx/skills,用于承载与插件绑定的技能资源
- 文档与使用说明:各插件目录下的 README.md 或 SKILL.md
graph TB
subgraph "插件扩展包"
VC["语音通话插件<br/>extensions/voice-call"]
BB["BlueBubbles 插件<br/>extensions/bluebubbles"]
ACX["ACPX 插件<br/>extensions/acpx"]
DIO["诊断监控插件<br/>extensions/diagnostics-otel"]
TV["Talk 语音管理插件<br/>extensions/talk-voice"]
end
subgraph "配置与清单"
OPL1["voice-call/openclaw.plugin.json"]
OPL2["bluebubbles/openclaw.plugin.json"]
OPL3["acpx/openclaw.plugin.json"]
OPL4["diagnostics-otel/openclaw.plugin.json"]
OPL5["talk-voice/openclaw.plugin.json"]
end
VC --- OPL1
BB --- OPL2
ACX --- OPL3
DIO --- OPL4
TV --- OPL5
核心组件
- 语音通话插件:支持 Twilio、Telnyx、Plivo 多提供商,具备外呼/通知模式、媒体流、实时 STT/TTS、签名验证与去重保护、超时与清理策略等。
- BlueBubbles 插件:作为外部通道插件,负责健康检查、消息发送、反应/打字指示、附件下载、Webhook 路由与运行时桥接。
- ACPX 插件:提供 ACP 运行时后端,支持命令路径、版本策略、权限模式、非交互权限策略、队列所有权 TTL、MCP 服务器注入等。
- 诊断监控插件:基于 OTel 的诊断能力,提供可观测性与指标采集。
- Talk 语音管理插件:提供 Talk 设备语音选择与管理能力。
- 文本生成插件(技能):通过技能目录与工具链实现文本生成任务,与插件生态协同工作。
架构总览
OpenClaw 插件通过统一的插件清单与运行时桥接,将第三方服务与本地能力整合到统一的消息与工具调用管道中。语音通话与 BlueBubbles 插件分别对接外部通道与提供商,ACPX 插件提供会话与权限控制,诊断插件提供可观测性,Talk 语音插件提供设备侧语音管理。
graph TB
GW["网关/运行时"]
VC["语音通话插件"]
BB["BlueBubbles 插件"]
ACX["ACPX 插件"]
DIO["诊断监控插件"]
TV["Talk 语音管理插件"]
GW --> VC
GW --> BB
GW --> ACX
GW --> DIO
GW --> TV
VC --> |"Webhook/媒体流"| VC_EXT["提供商: Twilio/Telnyx/Plivo/Mock"]
BB --> |"REST/Webhook"| BB_EXT["BlueBubbles 服务"]
ACX --> |"会话/权限/队列"| GW
DIO --> |"OTel 指标"| GW
TV --> |"设备语音"| GW
详细组件分析
语音通话插件(Voice Call)
- 功能要点
- 多提供商适配:Twilio、Telnyx、Plivo、Mock(本地开发)
- 外呼模式:通知式(notify)与对话式(conversation)
- 媒体流与实时 STT/TTS:支持 WebSocket 流、OpenAI Realtime API、提供商原生语音
- 安全与稳定性:Webhook 签名验证、去重保护、静音/转写超时、挂断延迟、呼叫清理器
- 配置覆盖:支持深合并覆盖核心 TTS 配置
- 关键配置项(节选)
- provider、fromNumber、toNumber、inboundPolicy、allowFrom、inboundGreeting
- serve/port/path、tailscale、tunnel、webhookSecurity
- outbound/defaultMode、notifyHangupDelaySec、maxDurationSeconds、staleCallReaperSeconds
- streaming/enabled、sttProvider、openaiApiKey、sttModel、streamPath、预连接与并发限制
- tts/provider、openai/elevenlabs 参数、edge(通话场景禁用)
- store、responseModel、responseSystemPrompt、responseTimeoutMs
- 使用与工具
- CLI:openclaw voicecall call/continue/speak/end/status/tail/expose
- 工具:voice_call.initiate_call/continue_call/speak_to_user/end_call/get_status
- RPC:voicecall.initiate/continue/speak/end/status
sequenceDiagram
participant U as "用户"
participant CLI as "CLI/工具"
participant VC as "语音通话插件"
participant Prov as "提供商(如 Twilio)"
participant RT as "实时流/STT/TTS"
U->>CLI : 发起外呼/继续/播报
CLI->>VC : voice_call.initiate_call/continue_call/speak_to_user
VC->>Prov : 创建/控制通话(外呼/媒体流)
Prov-->>VC : Webhook(状态/事件)
VC->>RT : 启动/维护媒体流(可选)
RT-->>VC : 实时转写/合成音频
VC-->>CLI : 返回状态/结果
CLI-->>U : 展示/播报
BlueBubbles 集成插件(External Channel)
- 功能要点
- 外部通道插件:负责 BlueBubbles 服务的健康检查、消息发送、反应/打字指示、附件下载
- Webhook 处理:注册插件 HTTP 路由,规范化发送方/聊天 ID,跳过自发消息,路由至核心回复管线
- 运行时桥接:通过 api.runtime 与 openclaw/plugin-sdk 辅助函数集成
- 内部助手(推荐使用)
- probeBlueBubbles、sendMessageBlueBubbles、resolveChatGuidForTarget
- sendBlueBubblesReaction、sendBlueBubblesTyping/markBlueBubblesChatRead
- downloadBlueBubblesAttachment、buildBlueBubblesApiUrl/blueBubblesFetchWithTimeout
- 配置(核心)
- channels.bluebubbles.serverUrl、password、webhookPath
- 行为限制:channels.bluebubbles.actions.reactions(默认开启)
flowchart TD
Start(["收到 BlueBubbles Webhook"]) --> Normalize["规范化发送方/聊天标识"]
Normalize --> SelfCheck{"是否来自自身?"}
SelfCheck --> |是| Drop["丢弃该消息"]
SelfCheck --> |否| Attachments{"是否有附件/贴图?"}
Attachments --> |是| Placeholder["文本为空时使用<mime:...>占位符"]
Attachments --> |否| Route["路由到核心回复管线"]
Placeholder --> Route
Route --> Done(["完成"])
Drop --> Done
ACPX 协议插件(ACPX Runtime)
- 功能要点
- ACP 运行时后端,支持命令路径、版本策略、工作目录、权限模式(approve-all/read-only/deny-all)
- 非交互权限策略(deny/fail),严格 Windows cmd 包装器开关
- 提示超时与队列拥有者 TTL,MCP 服务器注入(command/args/env)
- 关键配置项(节选)
- command、expectedVersion、cwd、permissionMode、nonInteractivePermissions
- strictWindowsCmdWrapper、timeoutSeconds、queueOwnerTtlSeconds
- mcpServers(命名 MCP 服务器定义)
classDiagram
class ACPXPlugin {
+命令路径
+期望版本
+工作目录
+权限模式
+非交互权限策略
+严格Windows包装器
+提示超时
+队列拥有者TTL
+MCP服务器列表
}
class MCP_Server {
+命令
+参数数组
+环境变量
}
ACPXPlugin --> MCP_Server : "注入"
诊断监控插件(Diagnostics OTel)
- 功能要点
- 基于 OpenTelemetry 的诊断能力,提供可观测性与指标采集
- 插件清单最小化,便于在不同环境中启用/停用
- 配置
- 当前无额外配置项,保持开箱即用
Talk 语音管理插件(Talk Voice)
- 功能要点
- 管理 Talk 设备的语音选择与设置
- 插件清单简洁,提供列出/设置能力
- 配置
- 当前无额外配置项
文本生成插件(以技能形式体现)
- 功能要点
- 通过技能目录与工具链实现文本生成任务
- 与插件生态协同,提供可复用的生成能力
- 说明
- 本节为概念性说明,不直接分析具体源码文件
依赖关系分析
- 语音通话插件对提供商的依赖:Twilio/Telnyx/Plivo/Mock;对实时流服务(如 OpenAI Realtime)的依赖
- BlueBubbles 插件对 BlueBubbles 服务的 REST/Webhook 依赖
- ACPX 插件对本地命令与 MCP 服务器的依赖
- 诊断插件对 OTel 生态的依赖
- Talk 语音插件对设备侧语音能力的依赖
graph LR
VC["语音通话插件"] --> TW["Twilio"]
VC --> TL["Telnyx"]
VC --> PV["Plivo"]
VC --> MK["Mock"]
VC --> OR["OpenAI Realtime"]
BB["BlueBubbles 插件"] --> BB_API["BlueBubbles 服务"]
ACX["ACPX 插件"] --> CMD["本地命令/脚本"]
ACX --> MCP["MCP 服务器"]
DIO["诊断监控插件"] --> OT["OTel 生态"]
TV["Talk 语音管理插件"] --> DEV["设备语音"]
性能考量
- 语音通话
- 媒体流并发与预连接上限需结合硬件与网络带宽设定,避免拥塞与抖动
- 实时 STT/TTS 的超时与静音阈值应平衡响应速度与准确性
- 呼叫清理器时间窗应高于最大通话时长,防止误杀正常通话
- BlueBubbles
- Webhook 路由与附件下载应异步化,避免阻塞主消息管线
- 健康检查与重试策略需考虑服务可用性与速率限制
- ACPX
- 队列拥有者 TTL 应尽量短,减少轮询与延迟
- 权限模式与非交互策略影响执行效率与安全性
- 诊断与监控
- 指标采样频率与上报间隔需权衡精度与资源占用
- Talk 语音
- 设备语音切换应避免阻塞主线程,必要时采用后台线程