尧图精选

OpenClaw 插件 SDK 边界指南:从契约、入口到演进规范

🕒 发布时间:2026/9/13 17:19:54 📁 来源:尧图网络
OpenClaw 插件 SDK 边界指南从契约、入口到演进规范【免费下载链接】openclawThe AI that really does things. Any OS. Any Platform. The lobster way. 项目地址: https://gitcode.com/GitHub_Trending/cl/openclawOpenClaw 的插件 SDKPlugin SDK是插件与核心core之间唯一的公共契约层承载着内置插件与第三方插件的全部能力注册与运行时交互。本文基于仓库中 src/plugin-sdk/CLAUDE.md 这一边界契约文档展开结合 docs/plugins 下的 SDK 文档与 src/plugin-sdk 的源码实现系统讲解边界规则的由来、版本化能力契约、验证手段以及如何安全地扩展 SDK 表面。读完本文你将掌握 OpenClaw 插件 SDK 的边界设计原则、入口辅助函数definePluginEntry/defineChannelPluginEntry/defineSingleProviderPluginEntry的注册语义以及为仓库新增公共子路径时必须对齐的文件清单。一、什么是 Plugin SDK 边界src/plugin-sdk/目录在仓库中承担一个特殊角色它是插件与核心之间的公共契约public contract。任何对这里的改动都可能同时影响内置插件bundled plugins和第三方插件third-party plugins因此仓库用一份专门的 CLAUDE.md 规定改动前的边界规则、必需能力、验证步骤与扩展流程。边界契约的核心立场可以概括为一句话宿主host即 OpenClaw 核心加载插件插件不应穿透 SDK 去抓取任意的宿主内部实现。SDK 应当是一层受控的、窄而文档化的接缝而不是一个把所有内部工具都倒出来的便利桶。二、边界的事实来源Source Of Truth要修改或扩展 SDK必须清楚哪些文件是权威事实来源。根据 src/plugin-sdk/CLAUDE.mdSDK 边界的权威定义分散在两类文件中文档侧docsdocs/plugins/sdk-overview.md —— 导入映射、注册 API 参考与 SDK 架构docs/plugins/sdk-entrypoints.md —— 入口辅助函数与注册模式docs/plugins/sdk-runtime.md ——api.runtime运行时助手docs/plugins/sdk-migration.md —— 从已废弃表面迁移docs/plugins/architecture.md —— 插件内部架构与能力模型定义文件definition filespackage.json—— 包导出exports映射scripts/lib/plugin-sdk-entrypoints.json —— 全部 SDK 子路径清单共 350 个入口scripts/lib/plugin-sdk-entries.mts —— 从清单派生出 public / private / production / deprecated 等入口集合src/plugin-sdk/api-baseline.ts —— API 基线baseline渲染用于契约漂移报告src/plugin-sdk/plugin-entry.ts —— 非渠道插件的规范入口src/plugin-sdk/core.ts —— 渠道插件入口与聊天渠道组合器src/plugin-sdk/provider-entry.ts —— 单 Provider 插件入口可以看到一套 SDK 公共表面同时由文档、入口清单、包导出和基线校验四类文件锁定任何一边单独改动都会造成漂移。这正是后文扩展边界要强调多文件对齐的原因。三、边界规则详解src/plugin-sdk/CLAUDE.md 用十余条规则定义了 SDK 表面应有的形状。下面按主题分组解读并给出源码层面的印证。3.1 窄入口优先拒绝便利桶宿主加载插件插件不得反向抓取宿主内部。SDK 应提供小的、带版本号的宿主/内核接缝 窄而文档化的入口点而不是宽泛的 barrel 再导出。不要从src/channels/**、src/agents/**、src/plugins/**或其他内部模块暴露实现便利除非是有意将其提升为受支持的公共契约。这条规则在 src/plugin-sdk/plugin-sdk-entries 相关脚本 中有具体落地入口被分为publicPluginSdkEntrypoints公开、带类型与文档与privateLocalOnlyPluginSdkEntrypoints仅本地使用、不进公共类型面从机制上防止内部模块被误导出。3.2 公共入口在模块加载时必须廉价Keep public SDK entrypoints cheap at module load.如果某个助手只会在异步路径如 send、monitor、probe、directory-live、login、setup上用到就应该放在窄的*.runtime子路径里而不是通过一个宽泛的 SDK barrel 再导出——因为热渠道入口hot channel entrypoints在启动时会 import 这些 barrel过重的加载会影响启动成本。仓库里大量*-runtime.ts文件正是这一原则的产物例如 src/plugin-sdk/blob-runtime.ts、src/plugin-sdk/fetch-runtime.ts、src/plugin-sdk/reply-runtime.ts 等。它们只承载运行时实现注册入口保持轻量。在 src/plugin-sdk/provider-entry.ts 中可以看到具体手法——createLazyRuntimeModule/createLazyRuntimeMethod把 live catalog 等重模块延迟到运行时钩子触发时才加载// src/plugin-sdk/provider-entry.ts const liveCatalogRuntime createLazyRuntimeModule( () import(./provider-catalog-live-runtime.js), ); const buildOpenAICompatibleProviderCatalog createLazyRuntimeMethod( liveCatalogRuntime, (runtime) runtime.buildOpenAICompatibleProviderCatalog, );3.3 保持 SDK 门面无环不要添加把轻量契约文件重新路由回更重的 policy/runtime 模块的反向再导出back-edge re-exports。不要在塑造 SDK 接缝时混用同一运行时表面的静态与动态导入如果某个表面必须保持懒加载就把急切侧放在轻量契约文件上把延迟侧放在专门的 runtime 子路径上。当核心或测试需要内置插件助手时优先使用插件包自身的api.ts或runtime-api.ts加上通用的 SDK 能力不要为了核心感知某个内置渠道的私有助手而新增一个以 provider 命名的src/plugin-sdk/id.ts接缝。3.4 Provider 工作优先家族级接缝共享助手应该描述可复用行为例如重放策略replay policy、工具 schema 兼容tool-schema compat、载荷归一化payload normalization、流包装组合stream-wrapper composition、传输装饰transport decoration。避免新增只包装某一家 provider 本地实现的 SDK 导出除非已经存在第二个消费者。当 options 编码的是稳定契约时优先命名助手而非原始 options 对象。文档中的例子是导出 OpenAI 风格的 Anthropic 工具载荷兼容 助手而不是让每个插件都传同样的 mode 标志。保持传输/运行时策略与插件面向的助手对齐如果同一行为既出现在插件注册路径又出现在核心运行时路径就暴露一个共享助手避免两条路径各自漂移。SDK 子路径应帮助调用方一次解决一个能力或运行时需求不要长出要求宽泛运行时注册表访问的新表面作为默认路径。如果某个提议的 SDK 导出主要是为了让 setup/config/control-plane 代码执行插件运行时这通常是边界异味boundary smell——应优先采用元数据或描述符驱动的 control-plane 接缝。四、版本化必需能力Versioned Required Capabilities边界文档用Always / Never / Ask first三档约束能力契约的演进这是 SDK 安全性的核心部分等级规则含义Always已发布的 Plugin SDK 参数契约一旦获得必需的宿主权限就必须引入需要该权限的版本化类型旧类型在文档化的弃用窗口内保持源码兼容并在同一改动中迁移所有内置/内部调用方Always宿主能力必须保持通用且闭包绑定closure-bound每个暴露的 tool、preparer、callback、审批操作与 native-action 表面都要绑定所有权或能力关闭后包括 await 策略工作期间的关闭保留的副本必须失效Never不要把旧的可选性当作无能力的运行时路径禁止在插件内部重建宿主权限也禁止给通用契约附加 provider 专属权限Never不要手工编辑生成的 SDK 基线、声明、哈希或预算必须通过规范流程重新生成Ask first缩短兼容窗口、让已发布类型源码不兼容、或扩大某项能力的信任/权限/持久化边界必须先征得 SDK 与安全负责人的认可最后一条Ask first尤其值得注意能力的信任、权限或持久化边界trust, authority, persistence boundary一旦扩大等于改变了整个插件生态的安全假设属于需要审批的变更而不是顺手就能做的清理。五、验证Verification改动 SDK 后仓库要求按影响范围执行验证涉及懒加载、热渠道入口或内置插件导入拓扑的改动运行pnpm build可能改变内置渠道启动成本的改动还要对受影响的插件运行隔离入口点分析器OPENCLAW_LOCAL_CHECK0 node --import tsx scripts/profile-extension-memory.mts --extension id --skip-combined --concurrency 1这条命令来自 scripts/profile-extension-memory.mts用于度量单个扩展入口的内存/加载画像是入口必须廉价这条规则的量化保障。六、如何扩展边界Expanding The Boundary6.1 不因便利而扩张SDK 表面已经太大不要为了便利添加兼容 barrel、别名或 fallback 导出。旧入口点应当被替换而不是叠加。公共第三方 API 是唯一的兼容例外文档化/版本化破坏性变更先迁移全部内置/内部插件再激进地弃用未使用的导出。6.2 新增或修改公共子路径时的对齐清单当添加或修改一个公共子路径时必须保持以下四处对齐docs/plugins 下的 SDK 文档scripts/lib/plugin-sdk-entrypoints.jsonscripts/lib/plugin-sdk-entries.mtspackage.json的 exports 字段API diff 与导出检查src/plugin-sdk/api-diff.ts。入口清单与导出映射的联动关系可以在 scripts/lib/plugin-sdk-entries.mts 中看到buildPluginSdkPackageExports()遍历全部入口公开入口生成./plugin-sdk/entry的 types default 双导出打包私有运行时入口只生成 default 导出其余一律不出现在包导出中。6.3 跨包边界的判断顺序如果内置渠道/助手的某个需求要跨包边界先问这个需求是否真正通用是 → 添加一个窄的通用子路径否 → 通过插件本地的api.ts/runtime-api.ts保持插件本地化。6.4 扩展 Provider 接缝时的测试锁定扩展 provider 面向的接缝时必须新增或更新匹配的窄测试来锁定契约Plugin SDK 的 diff/export 检查针对公共子路径针对被集中化的行为编写最直接的 provider/plugin 测试。6.5 破坏性变更的版本纪律破坏性的删除或重命名属于 major 版本工作而不是顺手清理drive-by cleanup。这要求任何移除导出都必须走完整的弃用窗口、内部迁移与版本号提升流程。七、从源码看边界的落地三类入口辅助函数SDK 边界最终通过一组入口辅助函数暴露给插件作者。它们把插件应该怎么声明自己规范化避免每个插件各自发明注册形状。7.1definePluginEntry—— 非渠道插件入口定义于 src/plugin-sdk/plugin-entry.ts适用于 provider、tool、command、service、memory、context-engine 插件。其选项结构为选项类型说明idstring插件 idnamestring显示名称descriptionstring描述kindOpenClawPluginDefinition[kind]已弃用专属插件类型请改在openclaw.plugin.json的 manifestkind中声明运行时kind仅作为旧插件兼容回退configSchemaOpenClawPluginConfigSchema \| (() ...)配置 schema支持懒工厂默认emptyPluginConfigSchemareloadOpenClawPluginDefinition[reload]重载注册nodeHostCommandsOpenClawPluginDefinition[nodeHostCommands]节点宿主命令securityAuditCollectors...安全审计收集器register(api: OpenClawPluginApi) void必填核心注册回调实现上configSchema通过createCachedLazyValueGetter懒求值其余字段只在提供时才透传——这保证了入口对象本身的加载是廉价的。7.2defineChannelPluginEntry—— 渠道插件入口定义于 src/plugin-sdk/core.ts除注册渠道能力外还按api.registrationMode分派不同的注册行为这是理解边界的关键。从 core.ts 的实现 可以看到实际分派逻辑cli-metadata模式只调用registerCliMetadata?.(api)用于 CLI 解析期元数据对应 docs/plugins/architecture.md 中parse-time metadata 来自registerCli(..., { descriptors })真实 CLI 模块保持懒加载的设计tool-discovery模式调用registerFullregisterCapabilities其他非 full 模式先api.registerChannel({ plugin })与setRuntime若为discovery模式再补registerCliMetadataregisterCapabilitiesfull模式registerCliMetadataregisterFullregisterCapabilities全部执行。7.3defineSingleProviderPluginEntry—— 单 Provider 插件入口定义于 src/plugin-sdk/provider-entry.ts面向运行时恰好导出一个主模型 provider 的插件。它替你规范化了API-key 认证从provider.auth或 manifest 的providerAuthChoices派生认证方法createProviderApiKeyAuthMethod并生成 setup wizard 元数据模型目录支持buildProvider静态目录、liveModelDiscovery从 OpenAI 兼容的 model-list 端点实时发现、或完全自定义的run目录实现统一文本目录投影通过projectProviderCatalogResultToUnifiedTextRows把目录结果投影为统一模型目录条目并自动注册api.registerModelCatalogProvider。在注册时如果 provider 既没有run目录、也没有buildProvider、manifest 中也没有对应modelCatalog.providers.id会直接抛出Missing modelCatalog.providers.${providerId}错误——入口辅助函数在边界上做静态完整性校验而不是把错误留到运行时。7.4 注册模式与插件形态根据 docs/plugins/sdk-overview.mdapi.registrationMode还包含轻量的setup-runtimesetup 流程runtime 可用而 docs/plugins/architecture.md 强调api.registrationMode full才是插件模块的完整运行时注册路径。每个已加载插件都会按实际注册行为归类为一种形态可用openclaw plugins inspect id查看形态说明示例plain-capability只注册一种能力类型provider-only 的arcee、chuteshybrid-capability注册多种能力类型openai同时拥有文本推理、语音、媒体理解、图像生成hook-only只注册 hooks无能力/工具/命令/服务受支持的路径但尚未迁移到能力注册non-capability有工具/命令/服务/路由但没有能力—形态分类的意义在于它是openclaw doctor、openclaw plugins inspect id、openclaw status --all、openclaw plugins doctor输出的兼容性信号config valid/hook-only提示 / 弃用的 memory-embedding API 警告 / 硬错误的基础。八、能力模型插件是所有权边界能力是核心契约docs/plugins/architecture.md 给出了边界之上的能力模型这是理解该把代码放哪的思维框架插件plugin 所有权边界一个厂商插件通常应拥有该厂商在 OpenClaw 上的全部表面文本、语音、图像、视频、web 搜索等而不是一堆互不相关的集成。能力capability 核心契约多个插件可以实现或消费它。例如 TTS 由elevenlabs、google、microsoft、openai各自实现合成voice-call消费共享的运行时助手而核心只拥有回复期 TTS 策略、回退顺序与渠道投递。能力注册方法覆盖推理、CLI 后端、嵌入、语音、实时转录、实时语音、媒体理解、字幕源、图像/音乐/视频生成、web fetch、web search、渠道、网关发现、迁移等十余类完整表格见 docs/plugins/architecture.md 的 Public capability model 一节。新增领域时的正确顺序是先在核心定义能力契约 → 通过 SDK 类型化暴露 → 接线渠道/特性消费者 → 让厂商插件注册实现。九、API 稳定性与兼容策略docs/plugins/sdk-overview.md 明确所有 OpenClaw 插件 API 均为实验性experimental包括每个openclaw/plugin-sdk/*子路径、注册与运行时 API、渠道与 provider 契约、hooks 以及原生 Control UI API。它们可能在版本间变化。因此插件作者需要固定开发与部署所用的 OpenClaw 版本并对声明的每个宿主版本进行测试从测试过的版本出发设置包兼容范围不要假设能跑的构建一定兼容未来版本实验性状态并不免除文档化的迁移路径——docs/plugins/sdk-migration.md 中的迁移路径依然适用。SDK 表面由 src/plugin-sdk/api-baseline.ts 渲染成 API 基线它用 TypeScript 编译程序扫描每个公开入口的导出符号、声明文本与闭包哈希供契约漂移报告使用——这正是Never: hand-edit generated SDK baselines的机器侧保障。十、实践清单为 OpenClaw 扩展或维护插件 SDK综合全文参与 SDK 相关工作时应按以下清单自查改动是否影响内置或第三方插件是 → 遵循 src/plugin-sdk/CLAUDE.md 的边界规则。新增导出是否真正通用否 → 留在插件本地api.ts/runtime-api.ts是 → 添加窄子路径不做 barrel。模块加载是否廉价只走异步路径的助手 → 放*.runtime子路径重模块 →createLazyRuntimeModule/ 动态import()。门面是否有环禁止轻量契约文件回路由到重模块的反向再导出。能力是否闭包绑定每个 tool/preparer/callback/审批/native-action 表面必须随 owner 或能力关闭而失效。需要新权限发布过的参数契约必须版本化并在同一改动迁移全部内部调用方。改动了公共子路径对齐 docs/plugins 文档、scripts/lib/plugin-sdk-entrypoints.json、scripts/lib/plugin-sdk-entries.mts、package.jsonexports、API diff 检查。运行验证。涉懒加载/热入口 →pnpm build涉启动成本 → 运行 scripts/profile-extension-memory.mts 的隔离入口分析器。是破坏性变更这是 major 版本工作走弃用窗口 内部迁移而不是顺手删除。生成了基线/声明/哈希重新生成绝不手工编辑。这套规则最终要回答的问题只有一个哪些表面是插件可以依赖的契约哪些只是实现细节。边界清晰核心与插件才能长期并行演进——这正是 OpenClaw 插件体系在拥有 350 SDK 子路径和数十个内置插件的情况下仍能保持契约一致性的根本原因。【免费下载链接】openclawThe AI that really does things. Any OS. Any Platform. The lobster way. 项目地址: https://gitcode.com/GitHub_Trending/cl/openclaw创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
上一篇/下一篇内容由系统自动关联 返回资讯列表 →