如果你之前没有构建过任何 OpenClaw 插件,请先阅读
入门指南,了解基本的软件包
结构和清单配置。
操作流程
Package 和 manifest
第 1 步:Package 和 manifest
setup.providers[].envVars,这样 OpenClaw 就能在不加载你的插件运行时的情况下检测
凭据。当某个提供方变体应复用另一个提供方 id 的认证时,添加 providerAuthAliases。modelSupport
是可选项,它允许 OpenClaw 在运行时钩子存在之前,就从像 acme-large 这样的简写
模型 id 自动加载你的提供方插件。如果你在 ClawHub 上发布该提供方,那么 package.json 中的
openclaw.compat 和 openclaw.build 字段是必需的。注册提供方
一个最小的文本提供方需要 当提供方 API 返回更丰富的元数据,而插件需要自行将行投影为 OpenClaw 模型定义时,请使用
id、label、auth 和 catalog。
catalog 是提供方拥有的运行时/配置钩子;它可以调用实时
厂商 API,并返回 models.providers 条目。index.ts
registerModelCatalogProvider 是用于列表/帮助/选择器 UI 的较新的控制平面目录
表面。将它用于文本、图像生成、视频生成和音乐生成条目。把厂商端点调用和
响应映射保留在插件中;OpenClaw 负责共享的行形状、来源
标签和帮助渲染。这就是一个可工作的提供方。用户现在可以
openclaw onboard --acme-ai-api-key <key> 并选择
acme-ai/acme-large 作为他们的模型。Live model discovery
如果你的提供方暴露了一个/models 风格的 API,请将提供方特定的
端点和行投影保留在插件中,并使用
openclaw/plugin-sdk/provider-catalog-live-runtime 来处理共享的获取生命周期。
该辅助函数为你提供受保护的 HTTP 获取、提供方认证头、
结构化 HTTP 错误、TTL 缓存和静态回退行为,而不会把提供方策略放进 OpenClaw 核心。当 live API 只告诉你哪些由提供方拥有的静态目录行当前可用时,请使用 buildLiveModelProviderConfig:index.ts
getCachedLiveProviderModelRows:index.ts
run 应保持认证门控,并在没有可用凭据时返回 null。保留一个离线的 staticRun 或静态回退,
这样设置、文档、测试和选择器界面就不会依赖实时网络访问。使用适合模型列表新鲜度的 TTL,
避免请求时文件系统轮询,并且只有在上游响应不是 OpenAI 兼容的 { data: [{ id, object }] }
形状时,才传入提供方特定的 readRows / readModelId。如果上游提供方使用的控制标记与 OpenClaw 不同,请添加一个小型的双向文本变换,而不是替换流路径:input 会在传输前重写最终的系统提示词和文本消息内容。output 会在 OpenClaw 解析
自己的控制标记或通道投递之前,重写助手文本增量和最终文本。对于只注册一个文本提供方、使用 API 密钥认证并且只有一个基于目录的运行时的打包提供方,
优先使用更窄的 defineSingleProviderPluginEntry(...) 辅助函数:buildProvider 是动态目录路径,在 OpenClaw 能解析真实提供方认证时使用。它可以执行
提供方特定的发现逻辑。buildStaticProvider 仅用于离线行,这些内容在认证配置完成之前也应是安全可展示的;
它不能依赖凭据,也不能发起网络请求。OpenClaw 的 models list --all 当前只会为打包的提供方插件执行静态目录,
并且配置为空、环境变量为空,也没有 agent/workspace 路径。如果你的认证流程还需要在 onboarding 期间修补 models.providers.*、别名和 agent 默认模型,
请使用 openclaw/plugin-sdk/provider-onboard 中的预设辅助函数。最小粒度的辅助函数有
createDefaultModelPresetAppliers(...)、
createDefaultModelsPresetAppliers(...) 和
createModelCatalogPresetAppliers(...)。当某个提供方的原生端点在常规 openai-completions 传输上支持流式 usage 块时,
应优先使用 openclaw/plugin-sdk/provider-catalog-shared 中共享的目录辅助函数,而不是硬编码
提供方 id 判断。supportsNativeStreamingUsageCompat(...) 和
applyProviderNativeStreamingUsageCompat(...) 会根据端点能力映射检测支持情况,因此即使插件使用了自定义提供方 id,
原生 Moonshot/DashScope 风格端点也仍然可以接入。上面的 live discovery 示例涵盖了 /models 风格的提供方 API。请将该发现逻辑保留在 catalog.run 中,
并基于可用认证进行门控,同时让 staticRun 保持不依赖网络,以便离线生成目录。添加动态模型解析
如果你的提供方接受任意模型 ID(例如代理或路由器),请添加
如果解析需要网络调用,请使用
resolveDynamicModel:prepareDynamicModel 进行异步
预热 - 完成后 resolveDynamicModel 会再次运行。添加运行时钩子(按需)
大多数提供方只需要 当前可用的 replay 家族:
当前可用的 stream 家族:
catalog + resolveDynamicModel。随着你的提供方需要,再逐步添加钩子。现在共享辅助构建器已经覆盖了最常见的 replay/tool-compat 家族,因此插件通常不需要逐个手工连接每个钩子:| Family | 作用 | 打包示例 |
|---|---|---|
openai-compatible | Shared OpenAI-style replay policy for OpenAI-compatible transports, including tool-call-id sanitation, assistant-first ordering fixes, and generic Gemini-turn validation where the transport needs it | moonshot, ollama, xai, zai |
anthropic-by-model | Claude-aware replay policy chosen by modelId, so Anthropic-message transports only get Claude-specific thinking-block cleanup when the resolved model is actually a Claude id | amazon-bedrock, anthropic-vertex |
google-gemini | Native Gemini replay policy plus bootstrap replay sanitation. The shared family keeps the text-output Gemini CLI on tagged reasoning; the direct google provider overrides resolveReasoningOutputMode to native because Gemini API thinking arrives as native thought parts. | google, google-gemini-cli |
passthrough-gemini | Gemini thought-signature sanitation for Gemini models running through OpenAI-compatible proxy transports; does not enable native Gemini replay validation or bootstrap rewrites | openrouter, kilocode, opencode, opencode-go |
hybrid-anthropic-openai | Hybrid policy for providers that mix Anthropic-message and OpenAI-compatible model surfaces in one plugin; optional Claude-only thinking-block dropping stays scoped to the Anthropic side | minimax |
| Family | 作用 | 打包示例 |
|---|---|---|
google-thinking | Gemini thinking payload normalization on the shared stream path | google, google-gemini-cli |
kilocode-thinking | Kilo reasoning wrapper on the shared proxy stream path, with kilo/auto and unsupported proxy reasoning ids skipping injected thinking | kilocode |
moonshot-thinking | Moonshot binary native-thinking payload mapping from config + /think level | moonshot |
minimax-fast-mode | MiniMax fast-mode model rewrite on the shared stream path | minimax, minimax-portal |
openai-responses-defaults | Shared native OpenAI/Codex Responses wrappers: attribution headers, /fast/serviceTier, text verbosity, native Codex web search, reasoning-compat payload shaping, and Responses context management | openai |
openrouter-thinking | OpenRouter reasoning wrapper for proxy routes, with unsupported-model/auto skips handled centrally | openrouter |
tool-stream-default-on | Default-on tool_stream wrapper for providers like Z.AI that want tool streaming unless explicitly disabled | zai |
驱动这些家族构建器的 SDK 接口
驱动这些家族构建器的 SDK 接口
每个家族构建器都由同一软件包导出的更底层公共辅助函数组合而成;当某个提供方需要脱离通用模式时,
你可以直接使用这些函数:
openclaw/plugin-sdk/provider-model-shared-ProviderReplayFamily,buildProviderReplayFamilyHooks(...), and the raw replay builders (buildOpenAICompatibleReplayPolicy,buildAnthropicReplayPolicyForModel,buildGoogleGeminiReplayPolicy,buildHybridAnthropicOrOpenAIReplayPolicy). Also exports Gemini replay helpers (sanitizeGoogleGeminiReplayHistory,resolveTaggedReasoningOutputMode) and endpoint/model helpers (resolveProviderEndpoint,normalizeProviderId,normalizeGooglePreviewModelId).openclaw/plugin-sdk/provider-stream-ProviderStreamFamily,buildProviderStreamFamilyHooks(...),composeProviderStreamWrappers(...), plus the shared OpenAI/Codex wrappers (createOpenAIAttributionHeadersWrapper,createOpenAIFastModeWrapper,createOpenAIServiceTierWrapper,createOpenAIResponsesContextManagementWrapper,createCodexNativeWebSearchWrapper), DeepSeek V4 OpenAI-compatible wrapper (createDeepSeekV4OpenAICompatibleThinkingWrapper), Anthropic Messages thinking prefill cleanup (createAnthropicThinkingPrefillPayloadWrapper), plain-text tool-call compat (createPlainTextToolCallCompatWrapper), and shared proxy/provider wrappers (createOpenRouterWrapper,createToolStreamWrapper,createMinimaxFastModeWrapper).openclaw/plugin-sdk/provider-tools-ProviderToolCompatFamily,buildProviderToolCompatFamilyHooks("deepseek" | "gemini" | "openai"), and underlying provider schema helpers.
native reasoning output,这样 OpenClaw 就会消费原生 thought parts,而不会额外加入 <think> / <final> 提示指令。
解析最终 JSON/text 响应的仅文本 Gemini CLI 风格后端则可以保留共享的 google-gemini 标记契约。某些流式辅助函数有意保持为提供方本地。@openclaw/anthropic-provider 将 wrapAnthropicProviderStream、resolveAnthropicBetas、resolveAnthropicFastMode、resolveAnthropicServiceTier 以及更底层的 Anthropic 包装器构建器保留在其自己的公开 api.ts / contract-api.ts 接口中,因为它们编码了 Claude OAuth beta 处理和 context1m 门控。xAI 插件也将原生 xAI Responses 形态保留在自己的 wrapStreamFn 中(/fast 别名、默认 tool_stream、不支持的 strict-tool 清理、xAI 特定的 reasoning-payload 移除)。同样的 package-root 模式也支撑着 @openclaw/openai-provider(提供方构建器、默认模型辅助函数、realtime 提供方构建器)以及 @openclaw/openrouter-provider(提供方构建器加 onboarding/config 辅助函数)。- Token 交换
- 自定义请求头
- 原生传输身份
- 用量和计费
对于需要在每次推理调用前进行 token 交换的提供方:
所有可用的提供方钩子
所有可用的提供方钩子
OpenClaw 会按以下顺序调用这些钩子。大多数提供方只会用到 2-3 个:
OpenClaw 不再调用的仅兼容字段,例如
运行时回退说明:
ProviderPlugin.capabilities 和 suppressBuiltInModel,不在此列出。| # | Hook | 适用场景 |
|---|---|---|
| 1 | catalog | Model catalog or base URL defaults |
| 2 | applyConfigDefaults | Provider-owned global defaults during config materialization |
| 3 | normalizeModelId | Legacy/preview model-id alias cleanup before lookup |
| 4 | normalizeTransport | Provider-family api / baseUrl cleanup before generic model assembly |
| 5 | normalizeConfig | Normalize models.providers.<id> config |
| 6 | applyNativeStreamingUsageCompat | Native streaming-usage compat rewrites for config providers |
| 7 | resolveConfigApiKey | Provider-owned env-marker auth resolution |
| 8 | resolveSyntheticAuth | Local/self-hosted or config-backed synthetic auth |
| 9 | shouldDeferSyntheticProfileAuth | Lower synthetic stored-profile placeholders behind env/config auth |
| 10 | resolveDynamicModel | Accept arbitrary upstream model IDs |
| 11 | prepareDynamicModel | Async metadata fetch before resolving |
| 12 | normalizeResolvedModel | Transport rewrites before the runner |
| 13 | normalizeToolSchemas | Provider-owned tool-schema cleanup before registration |
| 14 | inspectToolSchemas | Provider-owned tool-schema diagnostics |
| 15 | resolveReasoningOutputMode | Tagged vs native reasoning-output contract |
| 16 | prepareExtraParams | Default request params |
| 17 | createStreamFn | Fully custom StreamFn transport |
| 19 | wrapStreamFn | Custom headers/body wrappers on the normal stream path |
| 20 | resolveTransportTurnState | Native per-turn headers/metadata |
| 21 | resolveWebSocketSessionPolicy | Native WS session headers/cool-down |
| 22 | formatApiKey | Custom runtime token shape |
| 23 | refreshOAuth | Custom OAuth refresh |
| 24 | buildAuthDoctorHint | Auth repair guidance |
| 25 | matchesContextOverflowError | Provider-owned overflow detection |
| 26 | classifyFailoverReason | Provider-owned rate-limit/overload classification |
| 27 | isCacheTtlEligible | Prompt cache TTL gating |
| 28 | buildMissingAuthMessage | Custom missing-auth hint |
| 29 | augmentModelCatalog | Synthetic forward-compat rows |
| 30 | resolveThinkingProfile | Model-specific /think option set |
| 31 | isBinaryThinking | Binary thinking on/off compatibility |
| 32 | supportsXHighThinking | xhigh reasoning support compatibility |
| 33 | resolveDefaultThinkingLevel | Default /think policy compatibility |
| 34 | isModernModelRef | Live/smoke model matching |
| 35 | prepareRuntimeAuth | Token exchange before inference |
| 36 | resolveUsageAuth | Custom usage credential parsing |
| 37 | fetchUsageSnapshot | Custom usage endpoint |
| 38 | createEmbeddingProvider | Provider-owned embedding adapter for memory/search |
| 39 | buildReplayPolicy | Custom transcript replay/compaction policy |
| 40 | sanitizeReplayHistory | Provider-specific replay rewrites after generic cleanup |
| 41 | validateReplayTurns | Strict replay-turn validation before the embedded runner |
| 42 | onModelSelected | Post-selection callback (e.g. telemetry) |
normalizeConfigchecks the matched provider first, then other hook-capable provider plugins until one actually changes the config. If no provider hook rewrites a supported Google-family config entry, the bundled Google config normalizer still applies.resolveConfigApiKeyuses the provider hook when exposed. Amazon Bedrock keeps AWS env-marker resolution in its provider plugin; runtime auth itself still uses the AWS SDK default chain when configured withauth: "aws-sdk".resolveThinkingProfile(ctx)receives the selectedprovider,modelId, optional mergedreasoningcatalog hint, and optional merged modelcompatfacts. Usecompatonly to select the provider’s thinking UI/profile.resolveSystemPromptContributionlets a provider inject cache-aware system-prompt guidance for a model family. Prefer it overbefore_prompt_buildwhen the behavior belongs to one provider/model family and should preserve the stable/dynamic cache split.
添加额外能力(可选)
第 5 步:添加额外能力
提供方插件可以在文本推理之外同时注册 embeddings、语音、实时转写、 实时语音、媒体理解、图像生成、视频生成、网页抓取和网页搜索。OpenClaw 将这类插件归类为 hybrid-capability 插件——这是公司级插件的推荐模式 (每个厂商一个插件)。参见 内部机制:能力所有权。在register(api) 中与你现有的
api.registerProvider(...) 调用并列注册每种能力。只选择你需要的选项卡:- 语音(TTS)
- 实时转写
- 实时语音
- 媒体理解
- Embeddings
- 图像和视频生成
- 网页抓取与搜索
assertOkOrThrowProviderError(...),这样插件可以共享
有上限的错误正文读取、JSON 错误解析和 request-id 后缀。测试
第 6 步:测试
src/provider.test.ts
发布到 ClawHub
提供方插件与其他外部代码插件的发布方式相同:clawhub package publish。
文件结构
目录顺序参考
catalog.order 控制你的目录与内置提供者合并的相对时机:
| 顺序 | 时机 | 使用场景 |
|---|---|---|
simple | 第一轮 | 纯 API 密钥提供者 |
profile | simple 之后 | 由认证配置文件控制的提供者 |
paired | profile 之后 | 合成多个相关条目 |
late | 最后一轮 | 覆盖现有提供者(冲突时获胜) |
下一步
- Channel Plugins - 如果你的插件还提供一个 channel
- SDK Runtime -
api.runtime辅助函数(TTS、搜索、subagent) - SDK Overview - 完整的子路径导入参考
- Plugin Internals - hook 详情和捆绑示例