万字解析 OpenClaw 源码架构-插件开发示例

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
导出插件API与类型"] TYPES["src/plugins/types.ts
插件类型与钩子定义"] 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
入口与OAuth实现"] MM["minimax-portal-auth
入口与OAuth实现"] QW["qwen-portal-auth
入口与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["注册通道插件
api.registerChannel"] B --> D["注入运行时
set*Runtime(api.runtime)"] C --> E["通道插件
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.mdSKILL.md
graph TB subgraph "插件扩展包" VC["语音通话插件
extensions/voice-call"] BB["BlueBubbles 插件
extensions/bluebubbles"] ACX["ACPX 插件
extensions/acpx"] DIO["诊断监控插件
extensions/diagnostics-otel"] TV["Talk 语音管理插件
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["文本为空时使用占位符"] 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 语音
    • 设备语音切换应避免阻塞主线程,必要时采用后台线程
相关推荐
毛骗导演2 小时前
万字解析 OpenClaw 源码架构-插件开发指南
前端·架构
Mintopia2 小时前
如何看待大模型发展瓶颈:从算力、数据到对齐与系统工程的再评估
前端·人工智能
Mintopia2 小时前
Gemini-Essay-Writer 技术解析:基于 Gemini 的长文写作生成与质量控制实践
前端
蜡台2 小时前
Node Vue 项目开发常见问题解决
前端·javascript·vue.js·git·node
嘉琪0012 小时前
Day1 完整学习包(var/let/const + 作用域)——2026 0310
前端·javascript·学习
Moment2 小时前
2026 年 Next.js 站点的 SEO 优化指南
前端·javascript·面试
We་ct2 小时前
LeetCode 46. 全排列:深度解析+代码拆解
前端·数据结构·算法·leetcode·typescript·深度优先·回溯
problc2 小时前
前端预览pdf有哪些方案
前端·pdf
小小仙。2 小时前
IT自学第三十二天
服务器·前端·javascript