Appearance
OpenClaw Plugin SDK 的导入和注册都通过 openclaw/plugin-sdk/<子路径> 进行,所有注册方法集中在 OpenClawPluginApi 对象上。本页列出全部可用方法及作用(能力注册、工具/命令、基础设施、独占槽位、内存嵌入适配器)、钩子的阻断/跳过语义(before_tool_call、reply_dispatch 等),以及推荐的文件组织结构(api.ts、runtime-api.ts)。上游英文原文是唯一事实来源,所有命令、路径、方法名保持原样。
OpenClaw Plugin SDK 子路径导入与注册API完整参考
Plugin SDK 是插件与 core 之间的类型化合约。本页是导入路径和注册方法的完整参考。
本页面向在 OpenClaw 内部使用
openclaw/plugin-sdk/*的插件作者。外部应用、脚本、仪表盘、CI 作业和 IDE 扩展需要使用 OpenClaw App SDK 和@openclaw/sdk包。
需要操作指南?请从插件开发入门开始,渠道插件参考渠道插件开发,Provider 插件参考 Provider 插件开发,本地 AI CLI 后端参考 CLI 后端插件,工具或生命周期钩子参考插件钩子。
导入约定
始终从特定子路径导入:
typescript
import { definePluginEntry } from "openclaw/plugin-sdk/plugin-entry";
import { defineChannelPluginEntry } from "openclaw/plugin-sdk/channel-core";每个子路径是一个小型、自包含的模块,可保持启动速度快、避免循环依赖。渠道特定的入口/构建 helper 优先用 openclaw/plugin-sdk/channel-core;openclaw/plugin-sdk/core 保留给更宽泛的伞形接口和共享 helper(如 buildChannelConfigSchema)。
渠道配置通过 openclaw.plugin.json#channelConfigs 发布 JSON Schema。plugin-sdk/channel-config-schema 用于共享 schema 原语和通用构建器。OpenClaw 内置插件使用 plugin-sdk/bundled-channel-config-schema 保留捆绑渠道 schema。已废弃的兼容导出仍在 plugin-sdk/channel-config-schema-legacy 上。
警告:不要导入 Provider 或渠道品牌的便利接缝(如
openclaw/plugin-sdk/slack、.../discord、.../signal、api.ts/runtime-api.tsbarrel 组合通用 SDK 子路径;core 消费者应使用插件本地的 barrel,或在真正跨渠道需求时添加窄通用的 SDK 合约。
一小部分内置插件 helper 接缝仍出现在生成的导出映射中,仅供内置插件维护,不推荐用于新的第三方插件。
openclaw/plugin-sdk/discord和openclaw/plugin-sdk/telegram-account作为已废弃的兼容门面保留,请勿在新插件中复制这些导入路径。
子路径参考
Plugin SDK 按区域暴露为一组窄子路径(插件入口、渠道、Provider、认证、运行时、能力、内存和预留的内置插件 helper)。完整的分组列表及链接,请查看Plugin SDK 子路径。
编译器入口清单位于 scripts/lib/plugin-sdk-entrypoints.json;包导出从公共子集中生成(减去 scripts/lib/plugin-sdk-private-local-only-subpaths.json 中列出的仓库本地测试/内部子路径)。运行 pnpm plugin-sdk:surface 审计公共导出数量。废弃的公共子路径(足够旧且未被内置扩展生产代码使用)跟踪在 scripts/lib/plugin-sdk-deprecated-public-subpaths.json;广泛的已废弃重导出 barrel 跟踪在 scripts/lib/plugin-sdk-deprecated-barrel-subpaths.json。
注册 API
register(api) 回调接收 OpenClawPluginApi 对象,包含以下方法:
能力注册
| 方法 | 注册内容 |
|---|---|
api.registerProvider(...) | 文本推理(LLM) |
api.registerAgentHarness(...) | 实验性低层级 Agent 执行器 |
api.registerCliBackend(...) | 本地 CLI 推理后端 |
api.registerChannel(...) | 消息渠道 |
api.registerEmbeddingProvider(...) | 可复用的向量嵌入 Provider |
api.registerSpeechProvider(...) | 文本转语音 / 语音转文字合成 |
api.registerRealtimeTranscriptionProvider(...) | 流式实时转录 |
api.registerRealtimeVoiceProvider(...) | 双工实时语音会话 |
api.registerMediaUnderstandingProvider(...) | 图像/音频/视频分析 |
api.registerImageGenerationProvider(...) | 图像生成 |
api.registerMusicGenerationProvider(...) | 音乐生成 |
api.registerVideoGenerationProvider(...) | 视频生成 |
api.registerWebFetchProvider(...) | 网页抓取/爬取 Provider |
api.registerWebSearchProvider(...) | 网页搜索 |
使用 api.registerEmbeddingProvider(...) 注册的嵌入 Provider 必须在插件 manifest 的 contracts.embeddingProviders 中列出。这是用于可复用向量生成的通用嵌入接口。仅限内存的适配器仍使用 api.registerMemoryEmbeddingProvider(...) 和 contracts.memoryEmbeddingProviders。
工具和命令
简单工具插件(固定工具名)使用 defineToolPlugin。混合插件或完全动态工具注册使用 api.registerTool(...)。
| 方法 | 注册内容 |
|---|---|
api.registerTool(tool, opts?) | Agent 工具(必选或 { optional: true }) |
api.registerCommand(def) | 自定义命令(绕过 LLM) |
插件命令可设置 agentPromptGuidance,当 Agent 需要一个简短、命令所属的路由提示时。提示文本应仅关于命令本身,不要添加 Provider 或插件特定的策略到核心 prompt builder 中。
Guidance 条目可以是传统字符串(应用于所有 prompt 表面),或者结构化条目:
ts
agentPromptGuidance: [
"全局命令提示。",
{ text: "仅在主 PI 提示中显示。", surfaces: ["pi_main"] },
];结构化 surfaces 可包含 pi_main、codex_app_server、cli_backend、acp_backend 或 subagent。省略 surfaces 表示有意应用于所有表面。不要传递空 surfaces 数组,会被拒绝。
原生 Codex app-server 开发者指令比其他 prompt 表面更严格:只有显式限定到 codex_app_server 的 guidance 会提升到该高优先级通道。传统字符串 guidance 和非限定结构化 guidance 仍对其他非 Codex prompt 表面可用。
基础设施
| 方法 | 注册内容 |
|---|---|
api.registerHook(events, handler, opts?) | 事件钩子 |
api.registerHttpRoute(params) | 网关 HTTP 端点 |
api.registerGatewayMethod(name, handler) | 网关 RPC 方法 |
api.registerGatewayDiscoveryService(service) | 本地网关发现广播器 |
api.registerCli(registrar, opts?) | CLI 子命令 |
api.registerNodeCliFeature(registrar, opts?) | openclaw nodes 下的节点功能 CLI |
api.registerService(service) | 后台服务 |
api.registerInteractiveHandler(registration) | 交互式处理器 |
api.registerAgentToolResultMiddleware(...) | 运行时工具结果中间件 |
api.registerMemoryPromptSupplement(builder) | 附加的内存相邻 prompt 节 |
api.registerMemoryCorpusSupplement(adapter) | 附加的内存搜索/读取语料库 |
工作流插件的主机钩子
主机钩子是 SDK 用于需要参与主机生命周期而不仅仅是添加 Provider、渠道或工具的插件的接缝。它们是通用合约;Plan Mode 可以使用,审批工作流、工作区策略门控、后台监视器、设置向导和 UI 伴侣插件也可以使用。
| 方法 | 所属合约 |
|---|---|
api.session.state.registerSessionExtension(...) | 插件拥有的、JSON 兼容的会话状态,通过 Gateway sessions 投射 |
api.session.workflow.enqueueNextTurnInjection(...) | 持久化 exactly-once 上下文,注入到下一 Agent 回合(一个会话) |
api.registerTrustedToolPolicy(...) | 内置/信任的预插件工具策略,可阻止或重写工具参数 |
api.registerToolMetadata(...) | 工具目录显示元数据,不改变工具实现 |
api.registerCommand(...) | 限域插件命令;命令结果可设置 continueAgent: true;Discord 原生命令支持 descriptionLocalizations |
api.session.controls.registerControlUiDescriptor(...) | 针对会话、工具、运行或设置表面的控制 UI 贡献描述符 |
api.lifecycle.registerRuntimeLifecycle(...) | 插件拥有的运行时资源的清理回调(重置/删除/重载路径) |
api.agent.events.registerAgentEventSubscription(...) | 经过清理的事件订阅(用于工作流状态和监视器) |
api.runContext.setRunContext(...) / getRunContext(...) / clearRunContext(...) | 每个运行的插件暂存状态,在运行终了生命周期清除 |
api.session.workflow.registerSessionSchedulerJob(...) | 插件拥有的调度器作业的清理元数据;不调度工作或创建任务记录 |
api.session.workflow.sendSessionAttachment(...) | 仅内置插件:主机中介的文件附件交付到活动直接出站会话路由 |
api.session.workflow.scheduleSessionTurn(...) / unscheduleSessionTurnsByTag(...) | 仅内置插件:基于 Cron 的调度的会话回合及标签清理 |
新插件代码使用分组命名空间:
api.session.state.registerSessionExtension(...)api.session.workflow.enqueueNextTurnInjection(...)api.session.workflow.registerSessionSchedulerJob(...)api.session.workflow.sendSessionAttachment(...)api.session.workflow.scheduleSessionTurn(...)api.session.workflow.unscheduleSessionTurnsByTag(...)api.session.controls.registerSessionAction(...)api.session.controls.registerControlUiDescriptor(...)api.agent.events.registerAgentEventSubscription(...)api.agent.events.emitAgentEvent(...)api.runContext.setRunContext(...)/getRunContext(...)/clearRunContext(...)api.lifecycle.registerRuntimeLifecycle(...)
等价的扁平方法作为已废弃的兼容别名仍可用。不要在新插件代码中直接调用 api.registerSessionExtension、api.enqueueNextTurnInjection 等。
scheduleSessionTurn(...) 是会话范围的便利方法,底层使用 Gateway Cron 调度器。Cron 负责计时,并在回合运行时创建后台任务记录;Plugin SDK 仅限定目标会话、插件拥有的命名和清理。在调度的回合内需要持久多步任务流状态时,使用 api.runtime.tasks.managedFlows。
合约有意拆分权限:
- 外部插件可以拥有会话扩展、UI 描述符、命令、工具元数据、下一回合注入和普通钩子。
- 受信任的工具策略在普通
before_tool_call钩子之前运行,仅限内置插件,因为它们参与主机安全策略。 - 预留命令所有权仅限内置插件。外部插件应使用自己的命令名或别名。
allowPromptInjection=false禁用 prompt 变异钩子,包括agent_turn_prepare、before_prompt_build、heartbeat_prompt_contribution、来自旧版before_agent_start的 prompt 字段,以及enqueueNextTurnInjection。
非 Plan 消费者的示例:
| 插件原型 | 使用的钩子 |
|---|---|
| 审批工作流 | 会话扩展、命令延续、下一回合注入、UI 描述符 |
| 预算/工作区策略门控 | 受信任工具策略、工具元数据、会话投影 |
| 后台生命周期监视器 | 运行时生命周期清理、Agent 事件订阅、会话调度器拥有/清理、心跳 prompt 贡献、UI 描述符 |
| 设置或入职向导 | 会话扩展、限域命令、控制 UI 描述符 |
预留 core 管理员命名空间(
config.*、exec.approvals.*、wizard.*、update.*)始终解析为operator.admin,即使插件尝试分配更窄的网关方法作用域。插件拥有的方法应使用插件特定前缀。
何时使用工具结果中间件
内置插件可以使用 api.registerAgentToolResultMiddleware(...) 当需要在工具执行后、运行时将结果反馈回模型之前重写工具结果。这是用于异步输出归约器(例如 tokenjuice)的受信任运行时中立接缝。
内置插件必须为每个目标运行时声明 contracts.agentToolResultMiddleware,例如 ["pi", "codex"]。外部插件不能注册此中间件;对于不需要预模型工具结果定时的任务,使用普通的 OpenClaw 插件钩子。旧的 Pi 专用嵌入式扩展工厂注册路径已被移除。
网关发现注册
api.registerGatewayDiscoveryService(...) 让插件在本地发现传输(如 mDNS/Bonjour)上广播活动的 Gateway。OpenClaw 在 Gateway 启动时调用该服务(如果本地发现启用),传递当前 Gateway 端口和非秘密 TXT 提示数据,并在 Gateway 关闭时调用返回的 stop 处理器。
typescript
api.registerGatewayDiscoveryService({
id: "my-discovery",
async advertise(ctx) {
const handle = await startMyAdvertiser({
gatewayPort: ctx.gatewayPort,
tls: ctx.gatewayTlsEnabled,
displayName: ctx.machineDisplayName,
});
return { stop: () => handle.stop() };
},
});Gateway 发现插件不得将广播的 TXT 值视为秘密或认证。发现只是路由提示;网关认证和 TLS 固定仍负责信任。
CLI 注册元数据
api.registerCli(registrar, opts?) 接受两类命令元数据:
commands:注册器拥有的显式命令名descriptors:解析时命令描述符(用于 CLI 帮助、路由和懒加载插件 CLI 注册)parentPath:可选父命令路径(用于嵌套命令组,如["nodes"])
对于配对节点功能,优先使用 api.registerNodeCliFeature(registrar, opts?)。它是 api.registerCli(..., { parentPath: ["nodes"] }) 的包装器,使命令(如 openclaw nodes canvas)成为显式的插件拥有节点功能。
如果希望插件命令在正常根 CLI 路径中保持懒加载,提供覆盖该注册器暴露的每个顶级命令根的描述符。
typescript
api.registerCli(
async ({ program }) => {
const { registerMatrixCli } = await import("./src/cli.js");
registerMatrixCli({ program });
},
{
descriptors: [
{
name: "matrix",
description: "管理 Matrix 账号、验证、设备和配置文件状态",
hasSubcommands: true,
},
],
},
);嵌套命令将已解析的父命令作为 program 接收:
typescript
api.registerCli(
async ({ program }) => {
const { registerNodesCanvasCommands } = await import("./src/cli.js");
registerNodesCanvasCommands(program);
},
{
parentPath: ["nodes"],
descriptors: [
{
name: "canvas",
description: "从配对的节点捕获或渲染画布内容",
hasSubcommands: true,
},
],
},
);仅当不需要懒加载根 CLI 注册时,才单独使用 commands。该急切兼容路径仍受支持,但不安装基于描述符的占位符以支持解析时懒加载。
CLI 后端注册
api.registerCliBackend(...) 让插件拥有本地 AI CLI 后端(如 claude-cli 或 my-cli)的默认配置。
- 后端
id成为模型引用中的 Provider 前缀,例如my-cli/gpt-5。 - 后端
config使用与agents.defaults.cliBackends.<id>相同的形状。 - 用户配置优先。OpenClaw 在运行 CLI 前将
agents.defaults.cliBackends.<id>合并到插件默认值之上。 - 当后端需要在合并后进行兼容性重写(例如标准化旧 flag 形状)时,使用
normalizeConfig。 - 对于请求范围的 argv 重写(属于 CLI 方言,例如将 OpenClaw 思维级别映射到原生 effort flag),使用
resolveExecutionArgs。
端到端编写指南请参阅 CLI 后端插件。
独占槽位
| 方法 | 注册内容 |
|---|---|
api.registerContextEngine(id, factory) | 上下文引擎(一次只能激活一个)。assemble() 回调接收 availableTools 和 citationsMode,以便引擎定制 prompt 添加内容。 |
api.registerMemoryCapability(capability) | 统一内存能力 |
api.registerMemoryPromptSection(builder) | 内存 prompt 节构建器 |
api.registerMemoryFlushPlan(resolver) | 内存刷写计划解析器 |
api.registerMemoryRuntime(runtime) | 内存运行时适配器 |
内存嵌入适配器
| 方法 | 注册内容 |
|---|---|
api.registerMemoryEmbeddingProvider(adapter) | 激活的插件拥有的内存嵌入适配器 |
registerMemoryCapability是优先的独占内存插件 API。registerMemoryCapability也可以暴露publicArtifacts.listArtifacts(...),以便伴侣插件通过openclaw/plugin-sdk/memory-host-core消费导出的内存工件,而不是深入特定内存插件的私有布局。registerMemoryPromptSection、registerMemoryFlushPlan和registerMemoryRuntime是向后兼容的旧版独占内存插件 API。MemoryFlushPlan.model可以将刷写回合固定到确切的provider/model引用(例如ollama/qwen3:8b),而不继承活动的后备链。registerMemoryEmbeddingProvider允许激活的内存插件注册一个或多个嵌入适配器 id(例如openai、gemini或自定义 id)。- 用户配置如
agents.defaults.memorySearch.provider和agents.defaults.memorySearch.fallback会解析到这些已注册的适配器 id。
事件与生命周期
| 方法 | 作用 |
|---|---|
api.on(hookName, handler, opts?) | 类型化生命周期钩子 |
api.onConversationBindingResolved(handler) | 会话绑定回调 |
详见插件钩子的示例、常见钩子名和守卫语义。
钩子决策语义
before_tool_call:返回{ block: true }是终止决策,后续低优先级处理器被跳过;{ block: false }视为无决策(等同于省略block),不覆盖。before_install:返回{ block: true }终止,{ block: false }无决策。reply_dispatch:返回{ handled: true, ... }终止,后续处理器和默认模型调度路径被跳过。message_sending:返回{ cancel: true }终止,{ cancel: false }无决策。message_received:需要入站线程/主题路由时使用类型化threadId字段。渠道特定的额外信息放在metadata中。message_sending:优先使用类型化replyToId/threadId路由字段,再回退到渠道特定的metadata。gateway_start:使用ctx.config、ctx.workspaceDir和ctx.getCron?.()获取网关拥有的启动状态,不要依赖内部gateway:startup钩子。cron_changed:观察网关拥有的 cron 生命周期变化。同步外部唤醒调度器时使用event.job?.state?.nextRunAtMs和ctx.getCron?.(),并将 OpenClaw 作为到期检查和执行的事实来源。
API 对象字段
| 字段 | 类型 | 说明 |
|---|---|---|
api.id | string | 插件 id |
api.name | string | 显示名称 |
api.version | string? | 插件版本(可选) |
api.description | string? | 插件描述(可选) |
api.source | string | 插件源路径 |
api.rootDir | string? | 插件根目录(可选) |
api.config | OpenClawConfig | 当前配置快照(有可用运行时内存快照时使用活动内存快照) |
api.pluginConfig | Record<string, unknown> | 插件特定配置(来自 plugins.entries.<id>.config) |
api.runtime | PluginRuntime | 运行时辅助工具 |
api.logger | PluginLogger | 作用域日志器(debug、info、warn、error) |
api.registrationMode | PluginRegistrationMode | 当前加载模式;"setup-runtime" 是轻量级预完整入口的启动/设置窗口 |
api.resolvePath(input) | (string) => string | 解析相对于插件根的路径 |
插件内部模块约定
在插件内部使用本地 barrel 文件管理内部导入:
my-plugin/
api.ts # 外部消费者的公开导出
runtime-api.ts # 仅内部使用的运行时导出
index.ts # 插件入口点
setup-entry.ts # 轻量设置专用入口(可选)警告:永远不要在生产代码中通过
openclaw/plugin-sdk/<your-plugin>导入自己的插件。内部导入通过./api.ts或./runtime-api.ts路由。SDK 路径仅是对外合约。
门面加载的内置插件公共表面(api.ts、runtime-api.ts、index.ts、setup-entry.ts 等)在 OpenClaw 已运行时优先使用活动运行时配置快照。如果尚无运行时快照,回退到磁盘上已解析的配置文件。打包的内置插件门面应通过 OpenClaw 的插件门面加载器加载;从 dist/extensions/... 直接导入会绕过打包安装用于插件拥有代码的 manifest 和运行时 sidecar 检查。
Provider 插件可以在需要助手时暴露窄的插件本地合约 barrel(当 helper 是 Provider 特定且尚未属于通用 SDK 子路径时)。内置示例:
- Anthropic:公共
api.ts/contract-api.ts接缝,用于 Claude beta-header 和service_tier流 helper。 @openclaw/openai-provider:api.ts导出 Provider 构建器、默认模型 helper 和实时 Provider 构建器。@openclaw/openrouter-provider:api.ts导出 Provider 构建器以及入职/配置 helper。
扩展生产代码也应避免
openclaw/plugin-sdk/<other-plugin>导入。如果 helper 确实需要共享,请将其提升到中立的 SDK 子路径,例如openclaw/plugin-sdk/speech、.../provider-model-shared或其他能力导向的表面,而不是将两个插件耦合在一起。
相关文档
- 入口点参考 —
definePluginEntry和defineChannelPluginEntry选项 - 运行时辅助工具 —
api.runtime命名空间完整参考 - 插件打包与配置 — 打包、manifest、config schema
- 测试工具 — 测试工具和 lint 规则
- SDK 迁移 — 从废弃接口迁移
- 插件架构 — 深度架构和能力模型
常见问题
如何选择正确的导入子路径?
渠道插件首选 openclaw/plugin-sdk/channel-core;Provider 插件使用 openclaw/plugin-sdk/provider-entry 和相关的子路径(如 plugin-sdk/provider-auth、plugin-sdk/provider-http)。通用工具插件使用 openclaw/plugin-sdk/plugin-entry。完整的子路径分组列表见 Plugin SDK 子路径。
registerTool 和 registerCommand 有什么区别?
registerTool 注册一个可由 LLM 调用的 Agent 工具(可选或必需);registerCommand 注册一个绕过 LLM 的自定义命令,可用于实现 /slash 命令等。命令可以设置 agentPromptGuidance 来影响 Agent 行为。
为什么不能在插件内通过 openclaw/plugin-sdk/<自己> 导入?
SDK 路径是对外合约,供 core 或其他插件使用。插件内部导入应通过本地的 ./api.ts 或 ./runtime-api.ts,以保持封装并避免循环依赖。内置插件门面加载时优先使用运行时配置快照,直接导入会绕过这些检查。