openclaw.plugin.json。有关兼容的 bundle 布局(Agent Plugins、Codex、Claude、Cursor),请参见插件 bundle。
兼容的 bundle 格式使用各自的清单文件:
- Agent Plugins bundle:包根目录中的
plugin.json,遵循开放的 Agent Plugins 标准 - Codex bundle:
.codex-plugin/plugin.json - Claude bundle:
.claude-plugin/plugin.json,或不使用清单的默认 Claude 组件布局 - Cursor bundle:
.cursor-plugin/plugin.json
openclaw.plugin.json schema 进行校验。对于兼容的 bundle,当布局符合 OpenClaw 的运行时预期时,OpenClaw 会读取 bundle 元数据、声明的 skill 根目录、Claude 命令根目录、Claude settings.json 默认值、Claude LSP 默认值以及受支持的 hook pack。
每个原生 OpenClaw 插件必须在插件根目录中提供 openclaw.plugin.json。OpenClaw 会读取它来验证配置,不会执行插件代码。缺失或无效的清单会阻止配置校验,并被视为插件错误。
有关完整的插件系统指南,请参见 插件;有关原生能力模型和当前外部兼容性说明,请参见 能力模型。
此文件的作用
openclaw.plugin.json 是 OpenClaw 在加载插件代码之前读取的元数据文件。其中的所有内容都必须足够轻量,以便在不启动插件运行时的情况下完成检查。
用于:
- 插件标识、配置验证和配置界面提示
- 身份验证、入门引导和设置元数据(别名、自动启用、提供商环境变量、身份验证选项)
- 控制平面界面的激活提示
- 模型系列所有权简写
- 静态能力所有权快照(
contracts) - 仪表板组件数据绑定和操作动词
- 插件启用期间应存在的静态 MCP 服务器
- 共享
openclaw qa主机可检查的 QA 运行器元数据 - 合并到目录和验证界面中的频道专属配置元数据
package.json 中。
最小示例
丰富示例
顶层字段参考
对于静态 doctor 所有权,优先使用顶层的
sessionRouteStateOwners。较旧的
doctorContract.sessionRouteStateOwners: true 声明,以及从
doctor-contract-api 导出的 sessionRouteStateOwners,对于外部插件仍受支持,
但已弃用。当清单字段存在时,OpenClaw 会直接使用该字段,而无需加载
doctor-contract 模块。移除计划:在外部插件迁移窗口结束后,于 OpenClaw
2027.1 中移除模块回退机制。
当 doctor-contract 模块导出非空的 legacyConfigRules、normalizeCompatibilityConfig
函数,或同时导出两者时,请设置 doctorContract.configRepair: true。一项声明即可涵盖完整的配置修复构件。
MCP 服务器参考
mcpServers 允许原生插件提供 MCP 服务器(包括 MCP App),无需操作员在 openclaw.json 中重复定义其静态进程:
command、args、cwd 和 workingDirectory 路径均从插件根目录解析。用户配置仍具有权威性:mcp.servers.<name> 可以替换插件默认值,或设置 enabled: false 以将其省略。MCP App 渲染和服务器工具调用仍需要正常的 MCP Apps 设置以及生效的工具策略;声明服务器不会绕过这两个边界。
仪表盘参考
dashboard 允许已启用的插件向获授权的仪表盘小组件公开现有的 Gateway RPC,而无需向核心添加插件策略。数据绑定必须指定插件通过 operator.read 注册的同名方法;操作动词必须指定插件通过 operator.write 注册的方法。若不匹配,插件会在注册期间被拒绝。
<plugin-id>.<id>,例如 example.items.list 和 example.refresh。为确保持久化授权命名空间明确无歧义,OpenClaw 会将 plugin-id 部分中的 % 和 . 分别转义为 %25 和 %2E;普通插件 ID 保持自然形式。paramShape 是一个可选的 JSON Schema,在 OpenClaw 调用插件 RPC 前应用于操作参数对象。
目录参考
catalog 为插件浏览器提供可选的显示提示。主机可以忽略这些提示。它们不会安装或启用插件,也不会改变其运行时行为或信任级别。
生成 provider 元数据参考
generation provider 元数据字段描述的是与匹配的contracts.*GenerationProviders 列表中声明的 provider 相关的静态 auth 信号。OpenClaw 会在 provider 运行时加载之前读取这些字段,因此核心工具可以在不导入每个 provider 插件的情况下,判断某个 generation provider 是否可用。
仅将这些字段用于便宜、声明式的事实。传输、请求转换、token 刷新、凭证验证以及实际生成行为都保留在插件运行时中。
每个
configSignals 条目支持:
每个
mode 守卫支持:
每个
authSignals 条目支持:
每个
providerBaseUrl 守卫支持:
工具元数据参考
toolMetadata 使用与生成提供者元数据相同的 configSignals 和 authSignals 结构,并按工具名称作为键。contracts.tools 声明所有权。toolMetadata 声明廉价的可用性证据,这样 OpenClaw 就可以避免仅仅为了让其工具工厂返回 null 而导入插件运行时。
toolMetadata 条目还支持在上述共享的 configSignals/authSignals 字段之外,添加 optional(将该工具标记为插件激活时非必需)和 replaySafe(将工具执行标记为在不完整的模型轮次之后可安全重复)。
如果某个工具没有 toolMetadata,当工具契约与策略匹配时,OpenClaw 会保留现有行为并加载所属插件。对于其工厂依赖 auth/config 的热点路径工具,插件作者应声明 toolMetadata,而不是让 core 导入运行时去询问。
providerAuthChoices 参考
每个 providerAuthChoices 条目描述一种引导或身份验证选项。OpenClaw 会在加载 Provider 运行时之前读取这些内容。Provider 设置列表会使用这些清单选项、由描述符派生的设置选项,以及安装目录元数据,而不会加载 Provider 运行时。
当
appGuidedDiscovery 为 true 时,匹配的 Provider 身份验证方法必须提供
appGuidedSetup.detect 和 appGuidedSetup.prepare。检测必须是
只读的:不得执行登录、模型拉取、下载或配置写入。准备步骤会重新检查
精确选定的模型并返回配置提案;OpenClaw 会在隔离环境中对该提案进行实时测试,
仅在成功后才提交。Provider 还可以提供
appGuidedSetup.detectAvailability,以便在本地服务可访问但没有模型符合自动设置
条件时,将其设置选项标记为已检测。可用性探测同样是只读的。
commandAliases 参考
当某个插件拥有一个运行时命令名,而用户可能误将其填写到 plugins.allow 中,或尝试将其作为根 CLI 命令运行时,请使用 commandAliases。OpenClaw 会在不导入插件运行时代码的情况下使用这些元数据进行诊断。
activation 参考
当插件可以廉价地声明哪些控制平面事件应将其包含在激活/加载计划中时,请使用activation。
这个块是规划器元数据,不是生命周期 API。它不会注册运行时行为,不会替代 register(...),也不保证插件代码已经执行。激活规划器会使用这些字段来缩小候选插件范围,然后再回退到现有的 manifest 归属元数据,例如 providers、channels、commandAliases、setup.providers、contracts.tools 和 hooks。
优先使用已经描述归属关系的最窄元数据。当这些字段能够表达这种关系时,请使用 providers、channels、commandAliases、setup 描述符或 contracts。当需要一些无法由这些归属字段表示的额外规划器提示时,再使用 activation。对于诸如 claude-cli、my-cli 或 google-gemini-cli 这类 CLI 运行时别名,请使用顶层 cliBackends;activation.onAgentHarnesses 仅用于那些没有现有归属字段的嵌入式 agent harness id。
每个插件都应有意设置 activation.onStartup。仅当插件必须在 Gateway 启动期间运行时将其设为 true。当插件在启动时处于非激活状态,并且只应通过更窄的触发器加载时,将其设为 false。省略 onStartup 不再会隐式地在启动时加载插件;请为启动、channel、config、agent-harness、memory 或其他更窄的激活触发器使用显式的 activation 元数据。
当前实时使用方:
- Gateway 启动规划使用
activation.onStartup进行显式启动导入。 - 命令触发的 CLI 规划会回退到旧版
commandAliases[].cliCommand或commandAliases[].name。 - Agent runtime 启动规划对嵌入式 harness 使用
activation.onAgentHarnesses,对 CLI runtime 别名使用顶层cliBackends[]。 - Channel 触发的 setup/channel 规划在缺少显式 channel 激活元数据时,会回退到旧版
channels[]归属。 - 启动插件规划对非 channel 的根配置界面使用
activation.onConfigPaths,例如内置 browser 插件的browser块。 - Provider 触发的 setup/runtime 规划在缺少显式 provider 激活元数据时,会回退到旧版
providers[]和顶层cliBackends[]归属。
activation-command-hint 表示匹配到了 activation.onCommands,而 manifest-command-alias 表示规划器改为使用 commandAliases 归属。这些原因标签仅用于宿主诊断和测试;插件作者应继续声明最能描述归属关系的元数据。
qaRunners 参考
当插件在共享的openclaw qa 根命令下提供一个或多个传输运行器时,请使用 qaRunners。保持此元数据轻量且静态;插件运行时仍通过轻量的 qa-runner-api.ts 接口负责实际的 CLI 注册,该接口导出相匹配的 qaRunnerCliRegistrations。对于使用随附的 runtime-api.ts 契约的插件,在作者进行迁移期间,旧接口仍将接受至 2026-10-01。可选的 adapterFactory 会将传输暴露给共享 QA 场景,而不会更改已注册命令的运行器。
基于模块的流程场景是由适配器负责执行的一种形式。仅当该工厂创建的每个适配器都实现了 prepareFlow 时,才将
adapterFactory.supportsModuleFlows 设置为 true;QA 规划会将未声明支持的实现中的模块流程排除在外。
adapterFactory 的 id 必须与 commandName 匹配。不要为清单中不存在的命令导出注册项。
setup 参考
在 setup 和 onboarding 界面需要在运行时加载之前就能获取插件自有的廉价元数据时,请使用setup。
cliBackends 仍然有效,并继续用于描述 CLI 推理后端。setup.cliBackends 是 setup 专用的描述符表面,适用于应保持仅元数据的控制平面/setup 流程。
当存在时,setup.providers 和 setup.cliBackends 是 setup 发现的首选“先描述符”查找表面。如果描述符只缩小了候选插件范围,而 setup 仍需要更丰富的 setup 期运行时钩子,请设置 requiresRuntime: true 并保留 setup-api 作为回退执行路径。
OpenClaw 会将 setup.providers[].envVars 纳入通用 provider 认证和环境变量查找。请将 setup 和状态环境元数据放在那里。
当计费或组织级凭据必须激活 resolveUsageAuth 但又不能成为推理凭据时,请使用 providerUsageAuthEnvVars。这些名称会加入 workspace dotenv 阻止、ACP 子进程剥离、沙箱 secret 过滤以及广泛的 secret 清理。provider 运行时仍会在 resolveUsageAuth 中读取并分类该值。
当没有 setup 条目可用时,或者当 setup.requiresRuntime: false 声明 setup 不需要运行时时,OpenClaw 还可以从 setup.providers[].authMethods 推导简单的 setup 选项。显式的 providerAuthChoices 条目仍然更适合用于自定义标签、CLI 标志、onboarding 范围和助手元数据。
只有在这些描述符足以满足 setup 界面的需要时,才设置 requiresRuntime: false。OpenClaw 会将显式的 false 视为仅描述符契约,并且不会为了 setup 查找而执行 setup-api 或 openclaw.setupEntry。如果一个仅描述符插件仍然提供了这些 setup 运行时入口之一,OpenClaw 会报告一个附加诊断并继续忽略它。省略 requiresRuntime 会保留旧版回退行为,因此不会破坏那些在未设置该标志的情况下添加了描述符的现有插件。
由于 setup 查找可以执行插件拥有的 setup-api 代码,规范化后的 setup.providers[].id 和 setup.cliBackends[] 值必须在已发现的插件之间保持唯一。若所有权存在歧义,系统会关闭失败,而不是根据发现顺序挑选赢家。
当 setup 运行时确实执行时,如果 setup-api 注册了清单描述符未声明的 provider 或 CLI backend,或者某个描述符没有匹配的运行时注册,setup 注册表诊断会报告描述符漂移。这些诊断是附加性的,不会拒绝旧版插件。
setup.providers 参考
authEvidence 用于 provider 自有的本地凭据标记验证,这类验证无需加载运行时代码即可完成。这些检查必须保持廉价且本地化:不能有网络调用、不能读取密钥环或 secret manager、不能执行 shell 命令,也不能探测 provider API。
支持的证据条目:
setup 字段
uiHints 参考
uiHints 是一个从配置字段名到小型渲染提示的映射。键可以使用点号表示嵌套配置字段,但任何路径段都不能是 __proto__、constructor 或 prototype;setup 会拒绝这些名称。
频道配置部分会在频道根级别以及
accounts.<id> 下,为每个频道共用的叶字段(enabled、allowFrom、dmPolicy、groupPolicy、streaming 及类似字段)继承 help。如果某个频道为其中某个键声明了自己的 help,则始终以该声明为准;因此,当共享措辞不适用于你的提供商时,请进行覆盖。凭据、主机和 Webhook 等提供商特有的键仍然需要各自的提示。
contracts 参考
仅将contracts 用于静态能力所有权元数据,OpenClaw 可以在不导入插件运行时的情况下读取这些元数据。
contracts.embeddedExtensionFactories 保留给捆绑的、仅限 Codex app-server 的扩展工厂。捆绑的工具结果中间件应声明 contracts.agentToolResultMiddleware,并改为使用 api.registerAgentToolResultMiddleware(...) 注册。已安装插件也可以使用相同的中间件接入点,但前提是显式启用,并且仅限于它们在 contracts.agentToolResultMiddleware 中声明的运行时。
需要主机信任的前置工具策略层的已安装插件,必须在 contracts.trustedToolPolicies 中声明每个已注册的本地 ID,并且必须显式启用。捆绑插件保留现有的受信任策略路径,但未声明策略 ID 的已安装插件会在注册前被拒绝。策略 ID 的作用域限定为注册它的插件,因此两个插件都可以声明并注册 workflow-budget;但单个插件不能重复注册同一个本地 ID 两次。
运行时的 api.registerTool(...) 注册必须与 contracts.tools 匹配。工具发现会使用此列表,仅加载能够拥有所请求工具的插件运行时。
实现 resolveExternalAuthProfiles 的提供方插件应声明 contracts.externalAuthProviders;未声明的外部认证钩子会被忽略。
实现了 resolveUsageAuth 和 fetchUsageSnapshot 的提供方插件,应在 contracts.usageProviders 中声明每个自动发现的提供方 ID。用量发现会在加载运行时代码之前读取此契约,然后仅在加载声明的所有者之后验证这两个钩子。
通用嵌入提供方应为每个通过 api.registerEmbeddingProvider(...) 注册的适配器声明 contracts.embeddingProviders。将通用契约用于可复用的向量生成,包括内存搜索所消费的提供方。contracts.memoryEmbeddingProviders 是已弃用的内存专用兼容项,仅在现有提供方迁移到通用嵌入提供方接入点期间保留。
Worker 提供方必须在 contracts.workerProviders 中声明每个 api.registerWorkerProvider(...) ID。Core 会在调用 provision 之前持久化耐久意图;提供方会在外部分配之前验证其设置,并且使用相同操作 ID 的重复调用必须采用同一个租约。对于有界配置时间超过 Core 默认五分钟的提供方,可以实现 resolveProvisionTimeoutMs(profile),并在返回的正毫秒预算中包含获取、提供方自有设置和清理的时间。Core 还会持久化经过验证的设置快照,并将其与 leaseId 一起传递给 inspect({ leaseId, profile }) 和 destroy({ leaseId, profile }),包括在命名配置文件被更改或删除之后。销毁操作具有幂等性,检查会返回已关闭的 active/destroyed/unknown 状态联合,并且 SSH 私钥材料只能通过 SecretRef 引用。已配置的 SSH 端点还必须使用来自受信任配置输出的公共 hostKey,其格式必须严格为 algorithm base64,且不得包含主机名或注释,以便 Core 在连接前固定主机密钥。它们可以包含最多 10 个有序且唯一的 fallbackPorts,但不得包含主 port;Core 会持久化这些候选端口,并且仅在幂等探测、内容寻址传输、收据/锁保护的工件安装、收敛式托管工作树镜像和隧道重连期间在这些端口之间轮换。含义不明确且未受保护的有状态命令会安全失败,不会在候选端口之间重放。当 SSH 账户还拥有无关进程时,租约可以设置 sharedHost: true;这样 Core 在工作区协调期间会避免冻结整个主机上的进程。省略该字段或设置为 false 表示使用专用工作器主机。活动检查会重复这一事实,以便 Core 能够为在该字段存在之前持久化的租约协调由提供方拥有的隔离;隧道启动会等待首次权威检查完成。可选的桌面元数据可以公布最多八个唯一的已关闭应用:browser 应包含绝对路径的 executablePath 和 1 至 65535 之间的 CDP 端口,或者 terminal 应包含绝对路径的 executablePath。Core 会拒绝未知的应用 ID 和字段,并将经过验证的元数据与现有桌面记录一同持久化。生成动态身份引用的提供方可以实现权威的 resolveSshIdentity({ leaseId, profile, keyRef });没有实现该方法的提供方则使用 Core 的通用密钥解析器。权威的 unknown 状态会使本地活动记录成为孤立记录;在持久化销毁请求之后,它会确认拆除完成。
contracts.gatewayMethodDispatch 当前接受 "authenticated-request"。它是针对原生插件 HTTP 路由的 API 卫生门禁,这些路由会有意在进程内分发 Gateway 控制平面方法,而不是用来作为防御恶意原生插件的沙箱。仅将其用于已严格审查、且本身就需要 Gateway HTTP 认证的捆绑/运维面。只有当一个具备权限的路由同时声明 auth: "gateway" 和路由特定的 gatewayRuntimeScopeSurface: "trusted-operator" 时,它才会在 Gateway 根工作接入关闭时仍保持可达;同一插件中的普通兄弟路由仍会处于接入边界之后。这样可以在不赋予整个插件接入绕过权限的前提下,保持挂起状态和恢复操作的可达性。解析和响应整形应限制在分发之外;实质性工作或变更性工作必须通过 Gateway 方法分发完成,因为它负责接入和作用域强制执行。
configContracts 参考
将configContracts 用于清单所有的配置行为,这些行为是通用核心辅助工具所需,但又不能导入插件运行时:危险标志检测、SecretRef 迁移目标,以及旧版配置路径缩窄。
每个
dangerousFlags 条目支持:
secretInputs 支持:
mediaUnderstandingProviderMetadata 参考
当某个媒体理解提供商具有默认模型、自动认证回退优先级,或原生文档支持,而通用核心辅助函数在运行时加载之前就需要这些信息时,请使用mediaUnderstandingProviderMetadata。这些键也必须在 contracts.mediaUnderstandingProviders 中声明。
channelConfigs 参考
当某个 channel 插件在运行时加载之前需要廉价的配置元数据时,请使用channelConfigs。只读的 channel 设置/状态发现可以在没有 setup 条目的情况下,直接对已配置的外部 channel 使用这些元数据;或者当 setup.requiresRuntime: false 声明 setup 不需要运行时环境时,也可以这样使用。
channelConfigs 是插件 manifest 元数据,不是新的顶层用户配置章节。用户仍然在 channels.<channel-id> 下配置 channel 实例。OpenClaw 会先读取 manifest 元数据,以决定在插件运行时代码执行之前,哪个插件拥有该已配置的 channel。
对于 channel 插件,configSchema 和 channelConfigs 描述的是不同路径:
configSchema验证plugins.entries.<plugin-id>.configchannelConfigs.<channel-id>.schema验证channels.<channel-id>
channels[] 的非 bundled 插件也应声明匹配的 channelConfigs 条目。如果没有这些条目,OpenClaw 仍然可以加载插件,但冷路径配置 schema、setup 和 Control UI 界面在插件运行时执行之前,无法了解 channel 所拥有的选项结构或显示专用的 UI 提示。
channelConfigs.<channel-id>.commands.nativeCommandsAutoEnabled 和 nativeSkillsAutoEnabled 可以为在 channel 运行时加载之前执行的命令配置检查声明静态的 auto 默认值。bundled channels 也可以通过 package.json#openclaw.channel.commands 与其余归该包所有的 channel catalog 元数据一起发布相同的默认值。
替换另一个 channel 插件
当你的插件是某个 channel id 的首选拥有者,而另一个插件也可以提供该 channel id 时,请使用preferOver。常见情况包括:插件 id 更名、某个独立插件取代了一个 bundled 插件,或一个维护中的 fork 为了配置兼容性而保留相同的 channel id。
channels.chat 时,OpenClaw 会同时考虑 channel id 和首选插件 id。如果优先级较低的插件只是因为它是 bundled 或默认启用而被选中,OpenClaw 会在有效运行时配置中禁用它,这样就只有一个插件拥有该 channel 及其工具。显式的用户选择仍然优先:如果用户明确启用了这两个插件(通过 plugins.allow 或一个具体的 plugins.entries 配置),OpenClaw 会保留该选择,并报告重复的 channel/tool 诊断,而不是静默更改用户请求的插件集合。
请将 preferOver 的范围限制在确实能够提供相同 channel 的插件 id 上。它不是通用的优先级字段,也不会重命名用户配置键。
modelSupport 参考
当 OpenClaw 应在插件运行时加载前,根据诸如gpt-5.6-sol 或 claude-sonnet-4.6 这样的简写 model id 推断你的 provider 插件时,请使用 modelSupport。
- 显式的
provider/model引用使用其所属的providers清单元数据 modelPatterns优先于modelPrefixes- 如果一个非内置插件和一个内置插件都匹配,则非内置插件获胜
- 其余歧义会被忽略,直到用户或配置指定一个提供方
modelPatterns 条目会通过 compileSafeRegex 编译,该函数会拒绝包含嵌套重复的模式(例如 (a+)+$)。未通过安全检查的模式会被静默跳过,与语法无效的正则表达式相同。请保持模式简单,避免嵌套量词。
modelCatalog 参考
当 OpenClaw 在加载插件运行时之前需要知道 provider 模型元数据时,请使用modelCatalog。这是由 manifest 拥有的、用于固定 catalog 行、provider 别名、抑制规则和发现模式的来源。运行时刷新仍然属于 provider 运行时代码,但 manifest 会告知核心何时需要运行时。
aliases 会参与 model-catalog 规划中的 provider 归属查找。别名目标必须是由同一插件拥有的顶层 provider。当 provider 过滤列表使用别名时,OpenClaw 可以读取拥有者 manifest,并应用别名 API/base URL 覆盖,而无需加载 provider 运行时。别名不会扩展未过滤的 catalog 列表;宽泛列表只输出拥有者的规范 provider 行。
suppressions 替代了旧的 provider 运行时 suppressBuiltInModel 钩子。只有当 provider 归该插件拥有,或者被声明为指向已拥有 provider 的 modelCatalog.aliases 键时,抑制项才会生效。模型解析期间不再调用运行时抑制钩子。
Provider 字段:
Model 字段:
抑制字段:
upstreamModel 标记一行模型,表示它与另一个捆绑 catalog 中、名称不同的一行模型对应同一个上游模型,例如订阅端点旁边的供应商 API 端点。这是编写元数据:规范化会丢弃它,而契约测试会使用它,确保提供相同模型的 catalog 之间的 compat.codeMode 等能力标志不会发生偏移。大多数行无需此标记,因为匹配会忽略开头的供应商命名空间和大小写:moonshotai/kimi-k3 和 zai-org/GLM-5.2 已经可以分别匹配第一方的 kimi-k3 和 glm-5.2 行。只有当供应商自身使用的名称确实不同时,才使用 upstreamModel。请参阅代码模式。
不要将仅运行时数据放入 modelCatalog。只有当 manifest 行足够完整,使得按 provider 过滤的列表和选择器界面可以跳过 registry/runtime 发现时,才使用 static。当 manifest 行可作为可列出的种子或补充内容,但刷新/缓存稍后可以添加更多行时,使用 refreshable;仅凭 refreshable 行本身不具有权威性。当 OpenClaw 必须加载 provider 运行时才能知道模型列表时,使用 runtime。
modelIdNormalization 参考
使用modelIdNormalization 来进行廉价的、由提供方拥有的模型 ID 清理,这类清理必须在提供方运行时加载之前完成。这样可以把诸如简短模型名、提供方本地旧版 ID,以及代理前缀规则等内容保留在所属插件清单中,而不是放在核心模型选择表里。
providerEndpoints 参考
将providerEndpoints 用于端点分类,通用请求策略必须在 provider 运行时加载之前知晓这一信息。核心仍然负责每个 endpointClass 的含义,而插件清单负责主机和 base URL 元数据。
官方外部化的 provider 插件会被排除在核心 dist 之外,因此在安装之前,它们的清单是不可见的。它们的 providerEndpoints 也必须镜像到 scripts/lib/official-external-provider-catalog.json 中,这样即使没有插件,端点分类也能继续工作;契约测试会强制校验这份镜像。
端点字段:
providerRequest 参考
将providerRequest 用于轻量级的请求兼容性元数据,这些元数据是通用请求策略所需的,而无需加载提供方运行时。把与行为相关的载荷重写保留在提供方运行时钩子或共享的提供方家族辅助函数中。
secretProviderIntegrations 参考
当某个插件可以发布可复用的 SecretRef exec 提供方预设时,请使用secretProviderIntegrations。OpenClaw 会在插件运行时加载之前读取这些元数据,将插件所有权存储到 secrets.providers.<alias>.pluginIntegration,并将实际的密钥解析交由 SecretRef 运行时处理。预设仅对内置插件以及从受管理的插件安装根目录(例如 git 和 ClawHub 安装)中发现的已安装插件可用。
providerAlias,OpenClaw 会使用该集成 id 作为 SecretRef 的提供方别名。提供方别名必须匹配常规的 SecretRef 提供方别名模式,例如 team-secrets 或 onepassword-work。
当操作员选择该预设时,OpenClaw 会写入类似这样的提供方引用:
command/args 提供方。
目前仅支持 source: "exec" 预设。command 必须是 ${node},并且 args[0] 必须是一个以 ./ 开头、相对于插件根目录的解析脚本。OpenClaw 会在启动/重载时将其实例化为当前 Node 可执行文件以及插件内脚本的绝对路径。诸如 --require、--import、--loader、--env-file、--eval 和 --print 之类的 Node 选项不属于清单预设契约的一部分。需要非 Node 命令的操作员可以直接配置独立的手动 exec 提供方。
OpenClaw 会根据插件根目录,以及对于 ${node} 预设根据当前 Node 可执行文件所在目录,为清单预设推导 trustedDirs。清单中声明的 trustedDirs 会被忽略。其他 exec 提供方选项,例如 timeoutMs、noOutputTimeoutMs、maxOutputBytes、jsonOnly、env 和 passEnv,会原样传递给常规的 SecretRef exec 提供方配置。
modelPricing 参考
当托管目录发布者需要提供方特定的定价键行为时,请使用modelPricing。发布者读取此元数据时无需导入提供方运行时代码。
来源字段:
OpenClaw 提供方索引
OpenClaw 提供方索引是 OpenClaw 拥有的预览元数据,适用于插件可能尚未安装的提供方。它不是插件清单的一部分。插件清单仍然是已安装插件的权威来源。当提供方插件未安装时,提供方索引是未来可安装提供方和预安装模型选择器界面将消费的内部兜底契约。 目录权威顺序:- 用户配置。
- 已安装插件清单
modelCatalog。 - 来自显式刷新的模型目录缓存。
- OpenClaw 提供方索引预览行。
modelCatalog provider 行形状,但应仅限于稳定的显示元数据,除非像 api、baseUrl、定价或兼容性标志这样的运行时适配器字段被有意保持与已安装插件清单一致。具有实时 /models 发现能力的提供方应通过显式的模型目录缓存路径写入刷新后的行,而不是在正常的列出或引导流程中调用提供方 API。
对于那些插件已从核心移出或尚未安装的提供方,提供方索引条目也可以携带可安装插件元数据。此元数据遵循通道目录模式:包名、npm 安装规范、预期完整性校验以及简洁的认证选项标签,足以展示一个可安装的设置选项。一旦插件安装完成,其清单将生效,而该提供方的提供方索引条目会被忽略。
openclaw doctor --fix 会将一小组封闭的旧版顶层清单能力键迁移到 contracts.* 中:speechProviders、mediaUnderstandingProviders、imageGenerationProviders 和 tools。这些内容(以及任何其他能力列表)不再作为顶层清单字段读取;正常的清单加载只会在 contracts 下识别它们。
Manifest 与 package.json
这两个文件用途不同:
如果你不确定某条元数据应该放在哪里,请使用以下规则:
- 如果 OpenClaw 在加载插件代码之前必须知道它,就放在
openclaw.plugin.json中 - 如果它涉及打包、入口文件或 npm 安装行为,就放在
package.json中
影响发现的 package.json 字段
一些运行前插件元数据有意放在package.json 的 openclaw 块下,而不是 openclaw.plugin.json 中。openclaw.bundle 和 openclaw.bundle.json 不是 OpenClaw 插件契约;原生插件必须使用 openclaw.plugin.json 以及下面支持的 package.json#openclaw 字段。
重要示例:
清单元数据决定在运行时加载之前,引导过程中会出现哪些 provider/channel/setup 选项。
package.json#openclaw.install 告诉引导流程,当用户选择这些选项之一时如何获取或启用该插件。不要把安装提示移到 openclaw.plugin.json 中。
已配置的启动插件会在网关开始监听后,从其完整运行时注册 HTTP 路由。在启动侧车准备就绪之前,其他未声明归属的 HTTP 请求会返回带有 Retry-After: 1 的 503;核心路由在整个启动期间仍然可用。
对于 openclaw.channel.cliAddOptions,请使用 Commander 的长选项语法,例如 --initial-sync-limit <n>。设置 valueType: "int" 可将输入解析为非负整数;设置 valueType: "list" 可在插件设置适配器接收输入前,将以逗号、分号或换行分隔的输入拆分为字符串。省略 valueType 时,会将解析后的 Commander 值原样传递。
openclaw.install.minHostVersion 会在非捆绑插件来源的安装和清单注册表加载期间强制执行。无效值会被拒绝;对于较旧的主机,较新但有效的版本值会跳过外部插件。捆绑源插件被视为与主机检出版本保持同步。
openclaw.install.requiredPlatformPackages 适用于通过可选的、按平台区分的别名暴露所需原生二进制文件的 npm 包。为每个受支持的平台别名列出裸 npm 包名。在 npm install 期间,OpenClaw 只会验证锁文件约束与当前主机匹配的已声明别名。如果 npm 报告成功但省略了该别名,OpenClaw 会用新的缓存重试一次;如果该别名仍然缺失,则回滚安装。
openclaw.compat.pluginApi 会在非捆绑插件来源的包安装期间强制执行。把它用于该包构建时所依赖的 OpenClaw 插件 SDK/运行时 API 下限。当插件包需要更高的 API,但在其他流程中仍希望保留较低的安装提示时,它可以比 minHostVersion 更严格。官方 OpenClaw 发布同步默认会把现有官方插件的 API 下限提升到 OpenClaw 发布版本,但仅插件发布可以在包有意支持旧主机时保留较低下限。不要仅用包版本作为兼容性契约。peerDependencies.openclaw 仍然是 npm 包元数据;OpenClaw 使用 openclaw.compat.pluginApi 契约来做安装兼容性决策。
官方按需安装元数据在插件发布到 ClawHub 时应使用 clawhubSpec;引导流程会将其视为首选远程来源,并在安装后记录 ClawHub 工件事实。npmSpec 仍然是尚未迁移到 ClawHub 的包的兼容回退方案。
精确的 npm 版本锁定已经存在于 npmSpec 中,例如 "npmSpec": "@wecom/[email protected]"。官方外部目录条目应将精确规格与 expectedIntegrity 配对,以便在获取到的 npm 工件不再匹配固定发布版本时,更新流程能够安全失败。交互式引导仍会提供受信任的注册表 npm 规格,包括裸包名和 dist-tags,以保证兼容性。目录诊断可以区分精确、浮动、完整性固定、缺少完整性、包名不匹配以及无效默认选择来源。它们还会在存在 expectedIntegrity 但没有可用于固定它的有效 npm 来源时发出警告。存在 expectedIntegrity 时,安装/更新流程会强制执行它;省略时,则会记录注册表解析结果而不附加完整性固定。
当状态、channel 列表或 SecretRef 扫描需要在加载完整运行时之前识别已配置账户时,channel 插件应提供 openclaw.setupEntry。设置入口应暴露 channel 元数据以及设置安全的配置、状态和 secrets 适配器;将网络客户端、网关监听器和传输运行时保留在主扩展入口点中。
运行时入口点字段不会覆盖源入口点字段的包边界检查。例如,openclaw.runtimeExtensions 不能让一个会越界的 openclaw.extensions 路径变得可加载。
openclaw.install.allowInvalidConfigRecovery 的范围故意很窄。它不会让任意损坏的配置都能安装。当前它只允许安装流程从特定的过期捆绑插件升级失败中恢复,例如缺失的捆绑插件路径,或同一捆绑插件对应的过期 channels.<id> 条目。无关的配置错误仍会阻止安装,并将操作者引导到 openclaw doctor --fix。
openclaw.channel.persistedAuthState 是一个小型检查器模块的包元数据:
openclaw.channel.configuredState 支持廉价的已配置状态检查。当环境变量足够时,优先使用声明式环境元数据:
env.allOf;当任意一个非空变量满足条件时使用 env.anyOf。如果一个小型的非运行时检查所需信息超出环境元数据范围,请像 persistedAuthState 示例那样使用 specifier 加 exportName;存在 env 时,OpenClaw 会直接使用它,而不会加载该模块。如果检查需要完整的配置解析或真正的 channel 运行时,请将该逻辑保留在插件的 config.hasConfiguredState hook 中。
发现优先级(重复的插件 id)
OpenClaw 从三个根目录发现插件,按以下顺序检查:随 OpenClaw 一起发布的捆绑插件、全局安装根目录(~/.openclaw/extensions),以及当前工作区根目录(<workspace>/.openclaw/extensions),另外还包括任何显式的 plugins.load.paths 条目。
如果两个发现项共享相同的 id,则只保留优先级最高的 manifest;较低优先级的重复项会被丢弃,而不会与其并列加载。优先级从高到低如下:
- 配置选定 — 在
plugins.entries.<id>中显式固定的路径 - 与已跟踪的安装记录匹配的全局安装 — 通过
openclaw plugin install/openclaw plugin update安装的插件,且 OpenClaw 的安装跟踪将其识别为同一个 id,即使该 id 也属于某个捆绑插件 - 捆绑 — 随 OpenClaw 一起发布的插件
- 工作区 — 相对于当前工作区发现的插件
- 任何其他已发现的候选项
- 位于工作区或全局根目录中、未被跟踪的某个捆绑插件的分支副本或过时副本,不会覆盖捆绑版本。
- 要覆盖一个捆绑插件,可以针对该 id 运行
openclaw plugin install,这样被跟踪的全局安装会比捆绑副本优先级更高;或者通过plugins.entries.<id>固定一个特定路径,让它凭借配置选定优先级获胜。 - 重复项被丢弃时会记录日志,因此 Doctor 和启动诊断可以指出被丢弃的副本。
- 配置选定的重复覆盖会在诊断中表述为显式覆盖,但仍会发出警告,以便让过时分支和意外的覆盖保持可见。
JSON Schema 要求
- 每个插件都必须提供 JSON Schema,即使它不接受任何配置。
- 空 schema 是可以接受的(例如,
{ "type": "object", "additionalProperties": false })。 - Schema 会在配置读写时进行验证,而不是在运行时。
- 当扩展或分叉捆绑插件并加入新的配置键时,请同时更新该插件的
openclaw.plugin.json中的configSchema。捆绑插件的 schema 非常严格,因此如果没有在configSchema.properties中添加myNewKey,就在用户配置中添加plugins.entries.<id>.config.myNewKey,会在插件运行时加载之前被拒绝。
校验行为
- 未知的
channels.*键是错误,除非该 channel id 已由插件清单声明。如果相同的 id 也出现在plugins.allow、plugins.entries或plugins.installs中(即被引用但当前不可发现的插件),OpenClaw 会将其降级为警告。 plugins.entries.<id>、plugins.allow和plugins.deny引用未知插件 id 时是警告(“stale config entry ignored”),不是错误,因此升级和已移除/重命名的插件不会阻止网关启动。plugins.slots.memory引用未知插件 id 时是错误,但已知的memory-lancedb官方外部插件除外,它会改为警告。- 如果插件已安装,但清单或 schema 损坏或缺失,校验会失败,Doctor 会报告该插件错误。
- 如果插件配置存在,但插件已禁用,配置会被保留,并且 Doctor 和日志中会显示一个警告。
plugins.* schema 请参见配置参考。
注意事项
- 原生 OpenClaw 插件必须提供清单,包括从本地文件系统加载的插件。运行时仍会单独加载插件模块;清单仅用于发现和验证。
- 原生清单使用 JSON5 解析,因此支持注释、尾随逗号和不带引号的键名,只要最终值仍然是一个对象。
- 清单加载器只读取已记录的清单字段。避免使用自定义顶层键。
- 如果插件不需要
channels、providers、cliBackends和skills,可以全部省略。 providerCatalogEntry必须保持轻量,不应导入宽泛的运行时代码;应将其用于静态提供商目录元数据或范围狭窄的发现描述,而不是请求时执行。- 独占插件类型通过
plugins.slots.*选择:kind: "memory"通过plugins.slots.memory选择(默认为memory-core),kind: "context-engine"通过plugins.slots.contextEngine选择(默认为legacy)。 - 在此清单中声明独占插件类型。运行时入口中的
OpenClawPluginDefinition.kind已弃用,仅作为旧版插件的兼容性回退保留。 setup.providers[].envVars中的环境变量元数据仅具有声明性。状态、审计、cron 传递验证及其他只读界面,在将环境变量视为已配置之前,仍会应用插件信任和有效激活策略。- 对于需要提供商代码的运行时向导元数据,请参阅 提供商运行时钩子。
- 如果你的插件依赖原生模块,请记录构建步骤以及任何包管理器允许列表要求(例如 pnpm 的
allow-build-scripts+pnpm rebuild <package>)。
相关内容
构建插件
插件入门。
插件架构
内部架构和能力模型。
SDK 概览
插件 SDK 参考和子路径导入。