Skip to content

本页是 OpenClaw 插件系统的深度架构参考。覆盖能力注册模型(文本推理、语音、媒体理解、图像/视频生成等)、插件所有权边界、合约执行机制、加载管道(发现→启用→加载→注册→消费)、以及 Provider 运行时 Hook 完整顺序表。

OpenClaw 插件内部架构

这是深度架构参考。实践指南请见:插件安装与使用 · 插件开发入门 · Channel 插件 · Provider 插件

公共能力模型

每个原生 OpenClaw 插件针对一种或多种能力类型注册:

能力注册方法示例插件
文本推理api.registerProvider(...)openai, anthropic
语音api.registerSpeechProvider(...)elevenlabs, microsoft
实时转录api.registerRealtimeTranscriptionProvider(...)openai
实时语音api.registerRealtimeVoiceProvider(...)openai
媒体理解api.registerMediaUnderstandingProvider(...)openai, google
图像生成api.registerImageGenerationProvider(...)openai, google, fal, minimax
音乐生成api.registerMusicGenerationProvider(...)google, minimax
视频生成api.registerVideoGenerationProvider(...)qwen
网页抓取api.registerWebFetchProvider(...)firecrawl
网页搜索api.registerWebSearchProvider(...)google
渠道/消息api.registerChannel(...)msteams, matrix

插件形态

OpenClaw 根据实际注册行为(非静态元数据)将插件分为四种形态:

  • plain-capability — 注册恰好一种能力类型(如仅 Provider 的 mistral
  • hybrid-capability — 注册多种能力类型(如 openai 拥有文本推理、语音、媒体理解和图像生成)
  • hook-only — 只注册 Hook,无能力/工具/命令/服务
  • non-capability — 注册工具、命令、服务或路由,但无能力

运行 openclaw plugins inspect <id> 查看插件形态和能力分解。

兼容性信号

运行 openclaw doctoropenclaw plugins inspect <id> 可能看到:

信号含义
config valid配置解析正常,插件解析成功
compatibility advisory插件使用了受支持但较旧的模式(如 hook-only
legacy warning插件使用了已废弃的 before_agent_start
hard error配置无效或插件加载失败

架构概览

OpenClaw 插件系统分四层:

  1. Manifest + 发现层 — 从配置路径、工作区根、全局扩展根和内置扩展中发现候选插件;先读取原生 openclaw.plugin.json 和支持的 bundle manifest
  2. 启用 + 验证层 — 决定已发现插件的状态(启用/禁用/阻断/独占槽位如 memory)
  3. 运行时加载层 — 原生插件通过 jiti 进程内加载,向中央注册表注册能力;兼容 bundle 标准化为注册记录,不导入运行时代码
  4. 面向消费层 — 其余 OpenClaw 代码从注册表读取,暴露工具、渠道、Provider、Hook、HTTP 路由、CLI 命令和服务

Channel 插件与共享消息工具

Channel 插件无需为普通聊天动作注册单独的发送/编辑/反应工具。OpenClaw 在 core 中维护一个共享的 message 工具,Channel 插件拥有其背后的渠道特定发现和执行。

核心边界:

  • core 拥有:共享 message 工具宿主、提示词接线、会话/线程管理、执行调度
  • Channel 插件拥有:范围内的动作发现、能力发现和渠道特定 schema 片段

能力所有权模型

OpenClaw 将原生插件视为公司功能的所有权边界,而非不相关集成的大杂烩。

核心区分:

  • plugin = 所有权边界
  • capability = 可由多个插件实现或消费的 core 合约

推荐的分层模型:

  • core 能力层:共享编排、策略、回退、config 合并规则、交付语义和类型合约
  • 厂商插件层:厂商特定 API、认证、模型目录、语音合成、图像生成等
  • 渠道/功能插件层:消费 core 能力并在特定平台上呈现的集成

合约与执行

插件 API 面向有意设计为类型化、集中化。这意味着:

  • 插件作者有统一的内部标准
  • core 可以拒绝重复所有权(如两个插件注册同一 provider id)
  • 启动时可给出可操作的诊断信息
  • 合约测试可以明确执行已绑定插件的所有权

两层执行机制:

  1. 运行时注册执行 — 注册表在插件加载时验证注册,重复 ID、格式错误的注册产生插件诊断而非未定义行为
  2. 合约测试 — 绑定插件在测试运行时被捕获到合约注册表,断言所有权

执行模型

原生 OpenClaw 插件进程内运行于网关。它们不被沙箱化。已加载的原生插件与 core 代码具有相同的进程级信任边界。

含义:

  • 原生插件可注册工具、网络处理器、Hook 和服务
  • 原生插件 bug 可能导致网关崩溃或不稳定
  • 恶意原生插件等同于 OpenClaw 进程内的任意代码执行

兼容 bundle 默认更安全——OpenClaw 目前将其视为元数据/内容包。

使用白名单和明确的安装/加载路径管理非内置插件。将工作区插件视为开发时代码,而非生产默认值。

加载管道

启动时,OpenClaw 大致执行:

  1. 发现候选插件根目录
  2. 读取原生或兼容 bundle 的 manifest 和包元数据
  3. 拒绝不安全候选
  4. 规范化插件配置(plugins.enabledallowdenyentriesslotsload.paths
  5. 决定每个候选的启用状态
  6. 通过 jiti 加载已启用的原生模块
  7. 调用原生 register(api) 并将注册收集到插件注册表
  8. 向命令/运行时面暴露注册表

安全门控在运行时执行之前发生。当入口逃逸插件根目录、路径全局可写或路径所有权可疑时,候选被阻断。

activateregister 的旧版别名。加载器解析 def.register ?? def.activate 并在同一时间点调用。所有内置插件使用 register,新插件请用 register

注册表模型

已加载插件向中央插件注册表注册,注册表跟踪:

  • 插件记录(标识、来源、状态、诊断)
  • 工具
  • 旧版/类型化 Hook
  • 渠道
  • Provider
  • 网关 RPC 处理器
  • HTTP 路由
  • CLI 注册器
  • 后台服务
  • 插件拥有的命令

Core 功能从注册表读取,而非直接与插件模块通信。这保持了加载的单向性:插件模块 → 注册表注册;core 运行时 → 注册表消费。

Provider 运行时 Hook

Provider 插件有两层:

  • manifest 元数据providerAuthEnvVars(cheap 的 env 认证查询)和 providerAuthChoices(cheap 的引导/认证选择标签)
  • 运行时 Hook:完整列表见 Plugin Internals 原文

Hook 执行顺序(简表):

#Hook用途
1catalog发布 Provider 配置到 models.providers
2applyConfigDefaults应用 Provider 拥有的全局配置默认值
3normalizeModelId规范化旧版或预览模型 ID 别名
4-6normalizeTransport/Config/...规范化传输和配置
7-9resolveConfigApiKey/SyntheticAuth/...解析认证凭证
10-13resolveDynamicModel/...解析动态模型 ID
14-18capabilities/normalizeToolSchemas/...工具 schema 和能力元数据
19-20createStreamFn/wrapStreamFn自定义或包装流式传输
36prepareRuntimeAuth推理前的 token 交换
37-38resolveUsageAuth/fetchUsageSnapshot用量/配额端点
40-42buildReplayPolicy/sanitizeReplayHistory/...回放策略和历史清理

运行时辅助 API

Provider 插件可通过 api.runtime 访问 core 辅助方法:

TTS(文字转语音):

ts
const clip = await api.runtime.tts.textToSpeech({ text: "Hello", cfg: api.config });

媒体理解:

ts
const image = await api.runtime.mediaUnderstanding.describeImageFile({
  filePath: "/tmp/photo.jpg",
  cfg: api.config,
  agentDir: "/tmp/agent",
});

音频转录:

ts
const { text } = await api.runtime.mediaUnderstanding.transcribeAudioFile({
  filePath: "/tmp/audio.ogg",
  cfg: api.config,
});

子 Agent 运行:

ts
const result = await api.runtime.subagent.run({
  sessionKey: "agent:main:subagent:search-helper",
  message: "Expand this query.",
  provider: "openai",
  model: "gpt-4.1-mini",
  deliver: false,
});

图像生成:

ts
const result = await api.runtime.imageGeneration.generate({
  config: api.config,
  args: { prompt: "A friendly lobster mascot", size: "1024x1024" },
});

网关 HTTP 路由

ts
api.registerHttpRoute({
  path: "/acme/webhook",
  auth: "plugin",  // "gateway" 或 "plugin"
  match: "exact",
  handler: async (_req, res) => {
    res.statusCode = 200;
    res.end("ok");
    return true;
  },
});

注意:

  • auth 字段必填
  • Exact path + match 冲突被拒绝(除非 replaceExisting: true
  • 一个插件不能替换另一个插件的路由
  • auth: "plugin" 路由自动获得 operator 运行时 scope

Plugin SDK 导入路径

使用 SDK 子路径而非整体 openclaw/plugin-sdk 导入:

  • openclaw/plugin-sdk/plugin-entry — 插件注册原语
  • openclaw/plugin-sdk/core — 通用共享插件合约
  • openclaw/plugin-sdk/config-schema — root openclaw.json Zod schema
  • openclaw/plugin-sdk/channel-setupchannel-pairingchannel-contractchannel-inbound 等 — 渠道共享工具

兼容性提示:避免使用根 openclaw/plugin-sdk barrel;优先使用窄型稳定原语。

常见问题

Q: 开发自定义插件时,应该选择"原生插件"还是"bundle"模式?

A: 需要注册工具、Provider、渠道或 HTTP 路由等运行时能力时,必须使用原生插件。Bundle 只是内容包(skill、hook-pack、MCP 配置),适合发布 Claude/Cursor/Codex 格式的内容,但无法运行任意 TypeScript 代码。

Q: 插件报 hard error 怎么定位问题?

A: 运行 openclaw plugins inspect <id> 查看详细诊断,再查 openclaw logs --follow 中的加载错误。常见原因:manifest 格式不对(openclaw.plugin.json 缺失或字段错误)、入口文件路径错误、npm 依赖未安装。

Q: 两个插件都要注册同一个 provider id,会怎样?

A: 注册表在加载时检测到重复 ID 会产生插件诊断(hard error 级别),后加载的插件注册失败。通过 openclaw plugins inspect 可查看冲突详情。