Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs2.openclaw.ai/llms.txt

Use this file to discover all available pages before exploring further.

本指南介绍如何构建一个提供商插件,为 OpenClaw 添加模型提供商 (LLM)。完成后,你将拥有一个带有模型目录、API key 认证和动态模型解析的提供商。
如果你之前没有构建过任何 OpenClaw 插件,请先阅读 入门指南,了解基本的包结构和清单设置。
提供商插件会把模型添加到 OpenClaw 的常规推理循环中。如果模型 必须通过一个拥有线程、压缩或工具事件的原生智能体守护进程运行, 请将该提供商与 智能体运行框架 配套使用,而不是把守护进程协议细节放入核心。

演练

1

包和清单

第 1 步:包和清单

{
  "name": "@myorg/openclaw-acme-ai",
  "version": "1.0.0",
  "type": "module",
  "openclaw": {
    "extensions": ["./index.ts"],
    "providers": ["acme-ai"],
    "compat": {
      "pluginApi": ">=2026.3.24-beta.2",
      "minGatewayVersion": "2026.3.24-beta.2"
    },
    "build": {
      "openclawVersion": "2026.3.24-beta.2",
      "pluginSdkVersion": "2026.3.24-beta.2"
    }
  }
}
该清单声明了 providerAuthEnvVars,因此 OpenClaw 可以在不加载你的插件运行时的情况下 检测凭证。当某个提供商变体应复用另一个提供商 ID 的认证时,请添加 providerAuthAliasesmodelSupport 是可选的,它让 OpenClaw 能够在运行时钩子存在之前, 根据 acme-large 这样的简写模型 ID 自动加载你的提供商插件。如果你在 ClawHub 上发布该提供商,则 package.json 中必须包含这些 openclaw.compatopenclaw.build 字段。
2

注册提供商

一个最小文本提供商需要 idlabelauthcatalogcatalog 是由提供商拥有的运行时/配置钩子;它可以调用实时 供应商 API,并返回 models.providers 条目。
index.ts
import { definePluginEntry } from "openclaw/plugin-sdk/plugin-entry";
import { createProviderApiKeyAuthMethod } from "openclaw/plugin-sdk/provider-auth";

export default definePluginEntry({
  id: "acme-ai",
  name: "Acme AI",
  description: "Acme AI model provider",
  register(api) {
    api.registerProvider({
      id: "acme-ai",
      label: "Acme AI",
      docsPath: "/providers/acme-ai",
      envVars: ["ACME_AI_API_KEY"],

      auth: [
        createProviderApiKeyAuthMethod({
          providerId: "acme-ai",
          methodId: "api-key",
          label: "Acme AI API key",
          hint: "API key from your Acme AI dashboard",
          optionKey: "acmeAiApiKey",
          flagName: "--acme-ai-api-key",
          envVar: "ACME_AI_API_KEY",
          promptMessage: "Enter your Acme AI API key",
          defaultModel: "acme-ai/acme-large",
        }),
      ],

      catalog: {
        order: "simple",
        run: async (ctx) => {
          const apiKey =
            ctx.resolveProviderApiKey("acme-ai").apiKey;
          if (!apiKey) return null;
          return {
            provider: {
              baseUrl: "https://api.acme-ai.com/v1",
              apiKey,
              api: "openai-completions",
              models: [
                {
                  id: "acme-large",
                  name: "Acme Large",
                  reasoning: true,
                  input: ["text", "image"],
                  cost: { input: 3, output: 15, cacheRead: 0.3, cacheWrite: 3.75 },
                  contextWindow: 200000,
                  maxTokens: 32768,
                },
                {
                  id: "acme-small",
                  name: "Acme Small",
                  reasoning: false,
                  input: ["text"],
                  cost: { input: 1, output: 5, cacheRead: 0.1, cacheWrite: 1.25 },
                  contextWindow: 128000,
                  maxTokens: 8192,
                },
              ],
            },
          };
        },
      },
    });

    api.registerModelCatalogProvider({
      provider: "acme-ai",
      kinds: ["text"],
      liveCatalog: async (ctx) => {
        const apiKey = ctx.resolveProviderApiKey("acme-ai").apiKey;
        if (!apiKey) return null;
        return [
          {
            kind: "text",
            provider: "acme-ai",
            model: "acme-large",
            label: "Acme Large",
            source: "live",
          },
        ];
      },
    });
  },
});
registerModelCatalogProvider 是用于列表/帮助/选择器 UI 的较新控制平面目录接口。 请将它用于文本、图像生成、视频生成和音乐生成行。把供应商端点调用和 响应映射保留在插件中;OpenClaw 负责共享的行形状、来源标签和帮助渲染。这就是一个可工作的提供商。用户现在可以运行 openclaw onboard --acme-ai-api-key <key>,并选择 acme-ai/acme-large 作为他们的模型。如果上游提供商使用的控制标记与 OpenClaw 不同,请添加一个 小型双向文本转换,而不是替换流路径:
api.registerTextTransforms({
  input: [
    { from: /red basket/g, to: "blue basket" },
    { from: /paper ticket/g, to: "digital ticket" },
    { from: /left shelf/g, to: "right shelf" },
  ],
  output: [
    { from: /blue basket/g, to: "red basket" },
    { from: /digital ticket/g, to: "paper ticket" },
    { from: /right shelf/g, to: "left shelf" },
  ],
});
input 会在传输前重写最终系统提示词和文本消息内容。 output 会在 OpenClaw 解析自己的控制标记或进行渠道投递前, 重写助手文本增量和最终文本。对于只注册一个带 API-key 认证且由单一目录支持运行时的内置提供商, 优先使用更窄的 defineSingleProviderPluginEntry(...) 辅助函数:
import { defineSingleProviderPluginEntry } from "openclaw/plugin-sdk/provider-entry";

export default defineSingleProviderPluginEntry({
  id: "acme-ai",
  name: "Acme AI",
  description: "Acme AI model provider",
  provider: {
    label: "Acme AI",
    docsPath: "/providers/acme-ai",
    auth: [
      {
        methodId: "api-key",
        label: "Acme AI API key",
        hint: "API key from your Acme AI dashboard",
        optionKey: "acmeAiApiKey",
        flagName: "--acme-ai-api-key",
        envVar: "ACME_AI_API_KEY",
        promptMessage: "Enter your Acme AI API key",
        defaultModel: "acme-ai/acme-large",
      },
    ],
    catalog: {
      buildProvider: () => ({
        api: "openai-completions",
        baseUrl: "https://api.acme-ai.com/v1",
        models: [{ id: "acme-large", name: "Acme Large" }],
      }),
      buildStaticProvider: () => ({
        api: "openai-completions",
        baseUrl: "https://api.acme-ai.com/v1",
        models: [{ id: "acme-large", name: "Acme Large" }],
      }),
    },
  },
});
buildProvider 是当 OpenClaw 能够解析真实提供商认证时使用的实时目录路径。 它可以执行提供商特定的发现。仅将 buildStaticProvider 用于在配置认证之前 可以安全显示的离线行;它不得要求凭证或发起网络请求。 OpenClaw 的 models list --all 显示目前只对内置提供商插件执行静态目录, 并使用空配置、空环境,以及无智能体/工作区路径。如果你的认证流程还需要在新手引导期间修补 models.providers.*、别名和 智能体默认模型,请使用 openclaw/plugin-sdk/provider-onboard 中的预设辅助函数。 最窄的辅助函数是 createDefaultModelPresetAppliers(...)createDefaultModelsPresetAppliers(...)createModelCatalogPresetAppliers(...)当提供商的原生端点在常规 openai-completions 传输上支持流式用量块时, 请优先使用 openclaw/plugin-sdk/provider-catalog-shared 中的共享目录辅助函数, 而不是硬编码提供商 ID 检查。supportsNativeStreamingUsageCompat(...)applyProviderNativeStreamingUsageCompat(...) 会根据端点能力映射检测支持情况, 因此原生 Moonshot/DashScope 风格端点即使使用自定义提供商 ID 的插件, 仍然可以选择启用。
3

添加动态模型解析

如果你的提供商接受任意模型 ID(例如代理或路由器), 请添加 resolveDynamicModel
api.registerProvider({
  // ... id, label, auth, catalog from above

  resolveDynamicModel: (ctx) => ({
    id: ctx.modelId,
    name: ctx.modelId,
    provider: "acme-ai",
    api: "openai-completions",
    baseUrl: "https://api.acme-ai.com/v1",
    reasoning: false,
    input: ["text"],
    cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
    contextWindow: 128000,
    maxTokens: 8192,
  }),
});
如果解析需要网络调用,请使用 prepareDynamicModel 进行异步预热 - 它完成后会再次运行 resolveDynamicModel
4

添加运行时钩子(按需)

大多数提供商只需要 catalog + resolveDynamicModel。请随着提供商需求 逐步添加钩子。共享辅助构建器现在覆盖了最常见的重放/工具兼容系列, 因此插件通常不需要逐个手动连接每个钩子:
import { buildProviderReplayFamilyHooks } from "openclaw/plugin-sdk/provider-model-shared";
import { buildProviderStreamFamilyHooks } from "openclaw/plugin-sdk/provider-stream";
import { buildProviderToolCompatFamilyHooks } from "openclaw/plugin-sdk/provider-tools";

const GOOGLE_FAMILY_HOOKS = {
  ...buildProviderReplayFamilyHooks({ family: "google-gemini" }),
  ...buildProviderStreamFamilyHooks("google-thinking"),
  ...buildProviderToolCompatFamilyHooks("gemini"),
};

api.registerProvider({
  id: "acme-gemini-compatible",
  // ...
  ...GOOGLE_FAMILY_HOOKS,
});
当前可用的重放系列:
系列接入内容内置示例
openai-compatible面向 OpenAI 兼容传输协议的共享 OpenAI 风格重放策略,包括工具调用 ID 清理、assistant 优先顺序修复,以及在传输协议需要时进行通用 Gemini 轮次验证moonshot, ollama, xai, zai
anthropic-by-model根据 modelId 选择的 Claude 感知重放策略,因此只有当解析出的模型确实是 Claude ID 时,Anthropic 消息传输协议才会获得 Claude 专属 thinking-block 清理amazon-bedrock, anthropic-vertex
google-gemini原生 Gemini 重放策略,加上引导重放清理和带标签的推理输出模式google, google-gemini-cli
passthrough-gemini通过 OpenAI 兼容代理传输协议运行的 Gemini 模型的 Gemini thought-signature 清理;不会启用原生 Gemini 重放验证或引导重写openrouter, kilocode, opencode, opencode-go
hybrid-anthropic-openai适用于在一个插件中混合 Anthropic 消息和 OpenAI 兼容模型表面的提供商的混合策略;可选的仅限 Claude 的 thinking-block 丢弃仍限定在 Anthropic 侧minimax
当前可用的流系列:
系列接入内容内置示例
google-thinking共享流路径上的 Gemini thinking 载荷规范化google, google-gemini-cli
kilocode-thinking共享代理流路径上的 Kilo 推理包装器,kilo/auto 和不受支持的代理推理 ID 会跳过注入式 thinkingkilocode
moonshot-thinking根据配置 + /think 级别映射 Moonshot 二进制原生 thinking 载荷moonshot
minimax-fast-mode共享流路径上的 MiniMax fast-mode 模型重写minimax, minimax-portal
openai-responses-defaults共享的原生 OpenAI/Codex Responses 包装器:归因标头、/fast/serviceTier、文本详细程度、原生 Codex Web 搜索、推理兼容载荷整形,以及 Responses 上下文管理openai, openai-codex
openrouter-thinking面向代理路由的 OpenRouter 推理包装器,集中处理不受支持模型/auto 跳过openrouter
tool-stream-default-on面向 Z.AI 等提供商的默认开启 tool_stream 包装器,除非显式禁用,否则启用工具流式传输zai
每个系列构建器都由同一包导出的更低层级公共辅助函数组成。当提供商需要偏离通用模式时,你可以使用这些辅助函数:
  • openclaw/plugin-sdk/provider-model-shared - ProviderReplayFamilybuildProviderReplayFamilyHooks(...),以及原始重放构建器(buildOpenAICompatibleReplayPolicybuildAnthropicReplayPolicyForModelbuildGoogleGeminiReplayPolicybuildHybridAnthropicOrOpenAIReplayPolicy)。还导出 Gemini 重放辅助函数(sanitizeGoogleGeminiReplayHistoryresolveTaggedReasoningOutputMode)和端点/模型辅助函数(resolveProviderEndpointnormalizeProviderIdnormalizeGooglePreviewModelId)。
  • openclaw/plugin-sdk/provider-stream - ProviderStreamFamilybuildProviderStreamFamilyHooks(...)composeProviderStreamWrappers(...),以及共享 OpenAI/Codex 包装器(createOpenAIAttributionHeadersWrappercreateOpenAIFastModeWrappercreateOpenAIServiceTierWrappercreateOpenAIResponsesContextManagementWrappercreateCodexNativeWebSearchWrapper)、DeepSeek V4 OpenAI 兼容包装器(createDeepSeekV4OpenAICompatibleThinkingWrapper)、Anthropic Messages thinking 预填清理(createAnthropicThinkingPrefillPayloadWrapper),以及共享代理/提供商包装器(createOpenRouterWrappercreateToolStreamWrappercreateMinimaxFastModeWrapper)。
  • openclaw/plugin-sdk/provider-tools - ProviderToolCompatFamilybuildProviderToolCompatFamilyHooks("gemini"),以及底层 Gemini schema 辅助函数(normalizeGeminiToolSchemasinspectGeminiToolSchemas)。
有些流辅助函数会有意保持在提供商本地。@openclaw/anthropic-providerwrapAnthropicProviderStreamresolveAnthropicBetasresolveAnthropicFastModeresolveAnthropicServiceTier,以及更低层级的 Anthropic 包装器构建器保留在自己的公共 api.ts / contract-api.ts 接缝中,因为它们编码了 Claude OAuth beta 处理和 context1m 门控。xAI 插件同样将原生 xAI Responses 整形保留在自己的 wrapStreamFn 中(/fast 别名、默认 tool_stream、不受支持的 strict-tool 清理、xAI 专属推理载荷移除)。同样的包根模式也支持 @openclaw/openai-provider(提供商构建器、默认模型辅助函数、实时提供商构建器)和 @openclaw/openrouter-provider(提供商构建器以及新手引导/配置辅助函数)。
对于需要在每次推理调用前进行令牌交换的提供商:
prepareRuntimeAuth: async (ctx) => {
  const exchanged = await exchangeToken(ctx.apiKey);
  return {
    apiKey: exchanged.token,
    baseUrl: exchanged.baseUrl,
    expiresAt: exchanged.expiresAt,
  };
},
OpenClaw 按以下顺序调用钩子。大多数提供商只使用 2-3 个: OpenClaw 不再调用的仅兼容提供商字段,例如 ProviderPlugin.capabilitiessuppressBuiltInModel,未在此列出。
#钩子使用时机
1catalog模型目录或基础 URL 默认值
2applyConfigDefaults配置物化期间由提供商拥有的全局默认值
3normalizeModelId查找前清理旧版/预览模型 ID 别名
4normalizeTransport通用模型组装前清理提供商系列 api / baseUrl
5normalizeConfig规范化 models.providers.<id> 配置
6applyNativeStreamingUsageCompat面向配置提供商的原生流式用量兼容重写
7resolveConfigApiKey提供商拥有的环境标记凭证解析
8resolveSyntheticAuth本地/自托管或配置支持的合成凭证
9shouldDeferSyntheticProfileAuth将合成的已存储配置文件占位符降低到环境/配置凭证之后
10resolveDynamicModel接受任意上游模型 ID
11prepareDynamicModel解析前异步获取元数据
12normalizeResolvedModel运行器前的传输协议重写
13contributeResolvedModelCompat位于另一种兼容传输协议背后的供应商模型的兼容标志
14normalizeToolSchemas注册前由提供商拥有的工具 schema 清理
15inspectToolSchemas提供商拥有的工具 schema 诊断
16resolveReasoningOutputMode带标签与原生推理输出契约
17prepareExtraParams默认请求参数
18createStreamFn完全自定义的 StreamFn 传输协议
19wrapStreamFn正常流路径上的自定义标头/正文包装器
20resolveTransportTurnState原生逐轮标头/元数据
21resolveWebSocketSessionPolicy原生 WS 会话标头/冷却时间
22formatApiKey自定义运行时令牌形态
23refreshOAuth自定义 OAuth 刷新
24buildAuthDoctorHint凭证修复指引
25matchesContextOverflowError提供商拥有的溢出检测
26classifyFailoverReason提供商拥有的速率限制/过载分类
27isCacheTtlEligible提示缓存 TTL 门控
28buildMissingAuthMessage自定义缺失凭证提示
29augmentModelCatalog合成的前向兼容行
30resolveThinkingProfile模型专属 /think 选项集
31isBinaryThinking二进制 thinking 开/关兼容性
32supportsXHighThinkingxhigh 推理支持兼容性
33resolveDefaultThinkingLevel默认 /think 策略兼容性
34isModernModelRef实时/冒烟模型匹配
35prepareRuntimeAuth推理前的令牌交换
36resolveUsageAuth自定义用量凭证解析
37fetchUsageSnapshot自定义用量端点
38createEmbeddingProvider提供商拥有的记忆/搜索嵌入适配器
39buildReplayPolicy自定义转录重放/压缩策略
40sanitizeReplayHistory通用清理后的提供商特定重放重写
41validateReplayTurns嵌入式运行器前的严格重放轮次验证
42onModelSelected选择后的回调(例如 telemetry)
运行时回退说明:
  • normalizeConfig 首先检查匹配的提供商,然后检查其他具备钩子能力的提供商插件,直到某个插件实际更改配置。如果没有提供商钩子重写受支持的 Google 系列配置条目,仍会应用内置的 Google 配置规范化器。
  • resolveConfigApiKey 在公开时使用提供商钩子。内置 amazon-bedrock 路径在这里也有内置的 AWS 环境标记解析器,尽管 Bedrock 运行时凭证本身仍使用 AWS SDK 默认链。
  • resolveSystemPromptContribution 允许提供商为一个模型系列注入缓存感知的系统提示指引。当行为属于某个提供商/模型系列并且应保留稳定/动态缓存拆分时,优先使用它而不是 before_prompt_build
有关详细描述和真实示例,请参阅 内部机制:提供商运行时钩子
5

添加额外能力(可选)

步骤 5:添加额外能力

提供商插件可以在文本推理之外,同时注册语音、实时转录、实时 语音、媒体理解、图像生成、视频生成、Web 获取 和 Web 搜索。OpenClaw 将其归类为 混合能力插件 - 这是公司插件的推荐模式 (每个厂商一个插件)。请参阅 内部机制:能力所有权register(api) 内与你现有的 api.registerProvider(...) 调用一起注册每项能力。只选择你需要的标签页:
import {
  assertOkOrThrowProviderError,
  postJsonRequest,
} from "openclaw/plugin-sdk/provider-http";

api.registerSpeechProvider({
  id: "acme-ai",
  label: "Acme Speech",
  isConfigured: ({ config }) => Boolean(config.messages?.tts),
  synthesize: async (req) => {
    const { response, release } = await postJsonRequest({
      url: "https://api.example.com/v1/speech",
      headers: new Headers({ "Content-Type": "application/json" }),
      body: { text: req.text },
      timeoutMs: req.timeoutMs,
      fetchFn: fetch,
      auditContext: "acme speech",
    });
    try {
      await assertOkOrThrowProviderError(response, "Acme Speech API error");
      return {
        audioBuffer: Buffer.from(await response.arrayBuffer()),
        outputFormat: "mp3",
        fileExtension: ".mp3",
        voiceCompatible: false,
      };
    } finally {
      await release();
    }
  },
});
对提供商 HTTP 失败使用 assertOkOrThrowProviderError(...),这样 插件可以共享受限的错误正文读取、JSON 错误解析和 请求 ID 后缀。
6

Test

步骤 6:测试

src/provider.test.ts
import { describe, it, expect } from "vitest";
// Export your provider config object from index.ts or a dedicated file
import { acmeProvider } from "./provider.js";

describe("acme-ai provider", () => {
  it("resolves dynamic models", () => {
    const model = acmeProvider.resolveDynamicModel!({
      modelId: "acme-beta-v3",
    } as any);
    expect(model.id).toBe("acme-beta-v3");
    expect(model.provider).toBe("acme-ai");
  });

  it("returns catalog when key is available", async () => {
    const result = await acmeProvider.catalog!.run({
      resolveProviderApiKey: () => ({ apiKey: "test-key" }),
    } as any);
    expect(result?.provider?.models).toHaveLength(2);
  });

  it("returns null catalog when no key", async () => {
    const result = await acmeProvider.catalog!.run({
      resolveProviderApiKey: () => ({ apiKey: undefined }),
    } as any);
    expect(result).toBeNull();
  });
});

发布到 ClawHub

提供商插件的发布方式与任何其他外部代码插件相同:
clawhub package publish your-org/your-plugin --dry-run
clawhub package publish your-org/your-plugin
不要在这里使用旧的仅技能发布别名;插件包应使用 clawhub package publish

文件结构

<bundled-plugin-root>/acme-ai/
├── package.json              # openclaw.providers metadata
├── openclaw.plugin.json      # Manifest with provider auth metadata
├── index.ts                  # definePluginEntry + registerProvider
└── src/
    ├── provider.test.ts      # Tests
    └── usage.ts              # Usage endpoint (optional)

Catalog 顺序参考

catalog.order 控制你的 catalog 相对于内置 提供商的合并时机:
顺序时机使用场景
simple第一轮普通 API key 提供商
profilesimple 之后受 auth profile 限制的提供商
pairedprofile 之后合成多个相关条目
late最后一轮覆盖现有提供商(冲突时胜出)

后续步骤

相关内容