Ana içeriğe atla
Bu kılavuz, OpenClaw’a bir model sağlayıcısı (LLM) ekleyen bir sağlayıcı Plugin’i oluşturmayı adım adım anlatır. Sonunda model kataloğu, API anahtarı kimlik doğrulaması ve dinamik model çözümlemesi olan bir sağlayıcınız olacak.
Daha önce herhangi bir OpenClaw Plugin’i oluşturmadıysanız, temel paket yapısı ve manifest kurulumu için önce Başlarken bölümünü okuyun.
Sağlayıcı Plugin’leri, OpenClaw’ın normal çıkarım döngüsüne model ekler. Modelin iş parçacıklarını, Compaction’ı veya araç olaylarını sahiplenen yerel bir ajan arka plan hizmeti üzerinden çalışması gerekiyorsa, arka plan hizmeti protokol ayrıntılarını çekirdeğe koymak yerine sağlayıcıyı bir ajan harness’ı ile eşleştirin.

İzlenecek yol

1

Package and manifest

Adım 1: Paket ve manifest

{
  "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"
    }
  }
}
{
  "id": "acme-ai",
  "name": "Acme AI",
  "description": "Acme AI model provider",
  "providers": ["acme-ai"],
  "modelSupport": {
    "modelPrefixes": ["acme-"]
  },
  "setup": {
    "providers": [
      {
        "id": "acme-ai",
        "envVars": ["ACME_AI_API_KEY"]
      }
    ]
  },
  "providerAuthAliases": {
    "acme-ai-coding": "acme-ai"
  },
  "providerAuthChoices": [
    {
      "provider": "acme-ai",
      "method": "api-key",
      "choiceId": "acme-ai-api-key",
      "choiceLabel": "Acme AI API key",
      "groupId": "acme-ai",
      "groupLabel": "Acme AI",
      "cliFlag": "--acme-ai-api-key",
      "cliOption": "--acme-ai-api-key <key>",
      "cliDescription": "Acme AI API key"
    }
  ],
  "configSchema": {
    "type": "object",
    "additionalProperties": false
  }
}
Manifest, OpenClaw’ın Plugin çalışma zamanınızı yüklemeden kimlik bilgilerini algılayabilmesi için setup.providers[].envVars bildirir. Bir sağlayıcı varyantının başka bir sağlayıcı kimliğinin kimlik doğrulamasını yeniden kullanması gerektiğinde providerAuthAliases ekleyin. modelSupport isteğe bağlıdır ve çalışma zamanı hook’ları mevcut olmadan önce OpenClaw’ın sağlayıcı Plugin’inizi acme-large gibi kısaltılmış model kimliklerinden otomatik yüklemesini sağlar. Sağlayıcıyı ClawHub’da yayımlarsanız, package.json içinde bu openclaw.compat ve openclaw.build alanları zorunludur.
2

Register the provider

En küçük metin sağlayıcısının bir id, label, auth ve catalog değerine ihtiyacı vardır. catalog, sağlayıcıya ait çalışma zamanı/yapılandırma hook’udur; canlı tedarikçi API’lerini çağırabilir ve models.providers girdileri döndürür.
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, liste/yardım/seçici arayüzü için daha yeni kontrol düzlemi katalog yüzeyidir. Bunu metin, görüntü oluşturma, video oluşturma ve müzik oluşturma satırları için kullanın. Tedarikçi uç nokta çağrılarını ve yanıt eşlemesini Plugin içinde tutun; ortak satır biçiminin, kaynak etiketlerinin ve yardım işleme mantığının sahibi OpenClaw’dır.Bu, çalışan bir sağlayıcıdır. Kullanıcılar artık openclaw onboard --acme-ai-api-key <key> çalıştırabilir ve model olarak acme-ai/acme-large seçebilir.

Canlı model keşfi

Sağlayıcınız /models tarzı bir API sunuyorsa, sağlayıcıya özgü uç noktayı ve satır izdüşümünü Plugin’inizde tutun ve ortak fetch yaşam döngüsü için openclaw/plugin-sdk/provider-catalog-live-runtime kullanın. Yardımcı, sağlayıcı ilkesini OpenClaw çekirdeğine koymadan size korumalı HTTP fetch’leri, sağlayıcı kimlik doğrulama başlıkları, yapılandırılmış HTTP hataları, TTL önbellekleme ve statik geri dönüş davranışı sağlar.Canlı API yalnızca sağlayıcıya ait hangi statik katalog satırlarının o anda kullanılabilir olduğunu söylüyorsa buildLiveModelProviderConfig kullanın:
index.ts
import { definePluginEntry } from "openclaw/plugin-sdk/plugin-entry";
import {
  buildLiveModelProviderConfig,
  type LiveModelCatalogFetchGuard,
} from "openclaw/plugin-sdk/provider-catalog-live-runtime";

const STATIC_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,
  },
] as const;

async function buildAcmeLiveProvider(params: {
  apiKey: string;
  discoveryApiKey?: string;
  fetchGuard?: LiveModelCatalogFetchGuard;
}) {
  return await buildLiveModelProviderConfig({
    providerId: "acme-ai",
    endpoint: "https://api.acme-ai.com/v1/models",
    providerConfig: {
      baseUrl: "https://api.acme-ai.com/v1",
      api: "openai-completions",
    },
    models: STATIC_MODELS,
    apiKey: params.apiKey,
    discoveryApiKey: params.discoveryApiKey,
    fetchGuard: params.fetchGuard,
    ttlMs: 60_000,
    auditContext: "acme-ai-model-discovery",
  });
}

export default definePluginEntry({
  id: "acme-ai",
  name: "Acme AI",
  register(api) {
    api.registerProvider({
      id: "acme-ai",
      label: "Acme AI",
      catalog: {
        order: "simple",
        run: async (ctx) => {
          const auth = ctx.resolveProviderAuth("acme-ai");
          const apiKey =
            auth.apiKey ?? ctx.resolveProviderApiKey("acme-ai").apiKey;
          if (!apiKey) return null;
          return {
            provider: await buildAcmeLiveProvider({
              apiKey,
              discoveryApiKey: auth.discoveryApiKey,
            }),
          };
        },
      },
      staticCatalog: {
        order: "simple",
        run: async () => ({
          provider: {
            baseUrl: "https://api.acme-ai.com/v1",
            api: "openai-completions",
            models: [...STATIC_MODELS],
          },
        }),
      },
    });
  },
});
Sağlayıcı API’si daha zengin metadata döndürüyorsa ve Plugin’in satırları OpenClaw model tanımlarına kendisinin yansıtması gerekiyorsa getCachedLiveProviderModelRows kullanın:
index.ts
import {
  getCachedLiveProviderModelRows,
  LiveModelCatalogHttpError,
} from "openclaw/plugin-sdk/provider-catalog-live-runtime";

async function discoverAcmeModels(apiKey: string) {
  try {
    const rows = await getCachedLiveProviderModelRows({
      providerId: "acme-ai",
      endpoint: "https://api.acme-ai.com/v1/models",
      apiKey,
      ttlMs: 60_000,
      auditContext: "acme-ai-model-discovery",
    });
    return rows
      .map((row) => projectAcmeModel(row))
      .filter((model) => model !== null);
  } catch (error) {
    if (error instanceof LiveModelCatalogHttpError) {
      return STATIC_MODELS;
    }
    throw error;
  }
}
run, kimlik doğrulama kapılı kalmalı ve kullanılabilir kimlik bilgisi olmadığında null döndürmelidir. Kurulum, dokümanlar, testler ve seçici yüzeylerinin canlı ağ erişimine bağlı olmaması için çevrimdışı bir staticRun veya statik geri dönüş bulundurun. Model listesi güncelliğine uygun bir TTL kullanın, istek zamanında dosya sistemi polling’inden kaçının ve sağlayıcıya özgü readRows / readModelId değerlerini yalnızca upstream yanıtı OpenAI uyumlu { data: [{ id, object }] } biçiminde değilse geçirin.Upstream sağlayıcı OpenClaw’dan farklı kontrol token’ları kullanıyorsa, akış yolunu değiştirmek yerine küçük bir çift yönlü metin dönüştürmesi ekleyin:
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, taşıma öncesinde son sistem prompt’unu ve metin mesajı içeriğini yeniden yazar. output, OpenClaw kendi kontrol işaretlerini ayrıştırmadan veya kanala teslim etmeden önce asistan metin deltalarını ve son metni yeniden yazar.Yalnızca API anahtarı kimlik doğrulaması ve tek katalog destekli çalışma zamanı ile bir metin sağlayıcısı kaydeden paketli sağlayıcılar için daha dar defineSingleProviderPluginEntry(...) yardımcısını tercih edin:
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 gerçek sağlayıcı kimlik doğrulamasını çözebildiğinde kullanılan canlı katalog yoludur. Sağlayıcıya özgü keşif gerçekleştirebilir. buildStaticProvider yalnızca kimlik doğrulama yapılandırılmadan önce gösterilmesi güvenli olan çevrimdışı satırlar için kullanılmalıdır; kimlik bilgisi gerektirmemeli veya ağ isteği yapmamalıdır. OpenClaw’ın models list --all gösterimi şu anda statik katalogları yalnızca paketlenmiş sağlayıcı Plugin’leri için, boş yapılandırma, boş ortam ve agent/workspace yolları olmadan çalıştırır.Kimlik doğrulama akışınızın onboarding sırasında models.providers.*, alias’lar ve agent varsayılan modelini de yamaması gerekiyorsa openclaw/plugin-sdk/provider-onboard içindeki preset yardımcılarını kullanın. En dar kapsamlı yardımcılar createDefaultModelPresetAppliers(...), createDefaultModelsPresetAppliers(...) ve createModelCatalogPresetAppliers(...) şeklindedir.Bir sağlayıcının yerel uç noktası normal openai-completions taşımasında akışlı kullanım bloklarını destekliyorsa sağlayıcı kimliği kontrollerini sabit kodlamak yerine openclaw/plugin-sdk/provider-catalog-shared içindeki paylaşılan katalog yardımcılarını tercih edin. supportsNativeStreamingUsageCompat(...) ve applyProviderNativeStreamingUsageCompat(...) desteği uç nokta yetenek haritasından algılar; böylece yerel Moonshot/DashScope tarzı uç noktalar, bir Plugin özel sağlayıcı kimliği kullanıyor olsa bile yine de opt in yapar.Yukarıdaki canlı keşif örnekleri /models tarzı sağlayıcı API’lerini kapsar. Bu keşfi kullanılabilir kimlik doğrulamayla sınırlandırarak catalog.run içinde tutun ve çevrimdışı katalog üretimi için staticRun yolunu ağsız bırakın.
3

Dinamik model çözümlemesi ekle

Sağlayıcınız rastgele model kimliklerini kabul ediyorsa (proxy veya router gibi), resolveDynamicModel ekleyin:
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,
  }),
});
Çözümleme bir ağ çağrısı gerektiriyorsa eşzamansız ısınma için prepareDynamicModel kullanın; tamamlandıktan sonra resolveDynamicModel yeniden çalışır.
4

Çalışma zamanı hook'ları ekle (gerektiğinde)

Çoğu sağlayıcı yalnızca catalog + resolveDynamicModel gerektirir. Sağlayıcınız ihtiyaç duydukça hook’ları kademeli olarak ekleyin.Paylaşılan yardımcı oluşturucular artık en yaygın replay/tool-compat ailelerini kapsıyor; bu nedenle Plugin’lerin genellikle her hook’u tek tek elle bağlaması gerekmez:
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,
});
Bugün kullanılabilen replay aileleri:
AileNeyi bağlarPaketlenmiş örnekler
openai-compatibleOpenAI uyumlu taşımalar için paylaşılan OpenAI tarzı replay ilkesi; tool-call-id temizleme, assistant-first sıralama düzeltmeleri ve taşımanın ihtiyaç duyduğu yerlerde genel Gemini-turn doğrulaması dahilmoonshot, ollama, xai, zai
anthropic-by-modelmodelId tarafından seçilen Claude duyarlı replay ilkesi; böylece Anthropic-message taşımaları yalnızca çözümlenen model gerçekten bir Claude kimliği olduğunda Claude’a özgü thinking-block temizliği alıramazon-bedrock, anthropic-vertex
google-geminiYerel Gemini replay ilkesi ve bootstrap replay temizliği. Paylaşılan aile, metin çıktılı Gemini CLI’yi etiketli reasoning üzerinde tutar; doğrudan google sağlayıcısı Gemini API thinking’i yerel thought parçaları olarak geldiği için resolveReasoningOutputMode değerini native olarak override eder.google, google-gemini-cli
passthrough-geminiOpenAI uyumlu proxy taşımaları üzerinden çalışan Gemini modelleri için Gemini thought-signature temizliği; yerel Gemini replay doğrulamasını veya bootstrap yeniden yazımlarını etkinleştirmezopenrouter, kilocode, opencode, opencode-go
hybrid-anthropic-openaiTek bir Plugin içinde Anthropic-message ve OpenAI uyumlu model yüzeylerini karıştıran sağlayıcılar için hibrit ilke; isteğe bağlı yalnızca Claude thinking-block düşürme Anthropic tarafıyla sınırlı kalırminimax
Bugün kullanılabilen stream aileleri:
AileNeyi bağlarPaketlenmiş örnekler
google-thinkingPaylaşılan stream yolunda Gemini thinking payload normalizasyonugoogle, google-gemini-cli
kilocode-thinkingPaylaşılan proxy stream yolunda Kilo reasoning sarmalayıcısı; kilo/auto ve desteklenmeyen proxy reasoning kimlikleri enjekte edilen thinking’i atlarkilocode
moonshot-thinkingYapılandırma + /think seviyesinden Moonshot ikili yerel-thinking payload eşlemesimoonshot
minimax-fast-modePaylaşılan stream yolunda MiniMax fast-mode model yeniden yazımıminimax, minimax-portal
openai-responses-defaultsPaylaşılan yerel OpenAI/Codex Responses sarmalayıcıları: atıf üstbilgileri, /fast/serviceTier, metin ayrıntı düzeyi, yerel Codex web araması, reasoning-compat payload biçimlendirme ve Responses bağlam yönetimiopenai
openrouter-thinkingProxy rotaları için OpenRouter reasoning sarmalayıcısı; desteklenmeyen-model/auto atlamaları merkezi olarak ele alınıropenrouter
tool-stream-default-onAçıkça devre dışı bırakılmadıkça tool streaming isteyen Z.AI gibi sağlayıcılar için varsayılan olarak açık tool_stream sarmalayıcısızai
Her aile oluşturucu, aynı paketten dışa aktarılan daha düşük düzeyli genel yardımcıların bileşiminden oluşur; bir sağlayıcının ortak kalıbın dışına çıkması gerektiğinde bunları kullanabilirsiniz:
  • openclaw/plugin-sdk/provider-model-shared - ProviderReplayFamily, buildProviderReplayFamilyHooks(...) ve ham replay oluşturucuları (buildOpenAICompatibleReplayPolicy, buildAnthropicReplayPolicyForModel, buildGoogleGeminiReplayPolicy, buildHybridAnthropicOrOpenAIReplayPolicy). Ayrıca Gemini replay yardımcılarını (sanitizeGoogleGeminiReplayHistory, resolveTaggedReasoningOutputMode) ve uç nokta/model yardımcılarını (resolveProviderEndpoint, normalizeProviderId, normalizeGooglePreviewModelId) dışa aktarır.
  • openclaw/plugin-sdk/provider-stream - ProviderStreamFamily, buildProviderStreamFamilyHooks(...), composeProviderStreamWrappers(...), ayrıca paylaşılan OpenAI/Codex sarmalayıcıları (createOpenAIAttributionHeadersWrapper, createOpenAIFastModeWrapper, createOpenAIServiceTierWrapper, createOpenAIResponsesContextManagementWrapper, createCodexNativeWebSearchWrapper), DeepSeek V4 OpenAI uyumlu sarmalayıcısı (createDeepSeekV4OpenAICompatibleThinkingWrapper), Anthropic Messages thinking prefill temizliği (createAnthropicThinkingPrefillPayloadWrapper), düz metin tool-call compat (createPlainTextToolCallCompatWrapper) ve paylaşılan proxy/sağlayıcı sarmalayıcıları (createOpenRouterWrapper, createToolStreamWrapper, createMinimaxFastModeWrapper).
  • openclaw/plugin-sdk/provider-stream-shared - sıcak sağlayıcı yolları için hafif payload ve olay sarmalayıcıları; createOpenAICompatibleCompletionsThinkingOffWrapper, createPayloadPatchStreamWrapper, createPlainTextToolCallCompatWrapper, normalizeOpenAICompatibleReasoningPayload(...) ve setQwenChatTemplateThinking(...) dahil.
  • openclaw/plugin-sdk/provider-tools - ProviderToolCompatFamily, buildProviderToolCompatFamilyHooks("deepseek" | "gemini" | "openai") ve temel sağlayıcı şema yardımcıları.
Gemini ailesi sağlayıcıları için reasoning-output modunu taşıma ile uyumlu tutun. Doğrudan Google Gemini API sağlayıcıları native reasoning çıktısı kullanmalıdır; böylece OpenClaw yerel thought parçalarını <think> / <final> prompt yönergeleri eklemeden tüketir. Son JSON/metin yanıtını ayrıştıran yalnızca metin Gemini CLI tarzı backend’ler paylaşılan google-gemini etiketli sözleşmesini koruyabilir.Bazı stream yardımcıları bilerek sağlayıcıya yerel kalır. @openclaw/anthropic-provider, wrapAnthropicProviderStream, resolveAnthropicBetas, resolveAnthropicFastMode, resolveAnthropicServiceTier ve daha düşük düzeyli Anthropic sarmalayıcı oluşturucularını kendi genel api.ts / contract-api.ts sınırında tutar; çünkü bunlar Claude OAuth beta işleme ve context1m kapılamasını kodlar. xAI Plugin’i de yerel xAI Responses biçimlendirmesini kendi wrapStreamFn içinde tutar (/fast alias’ları, varsayılan tool_stream, desteklenmeyen strict-tool temizliği, xAI’ye özgü reasoning-payload kaldırma).Aynı paket kökü kalıbı @openclaw/openai-provider (sağlayıcı oluşturucular, varsayılan model yardımcıları, realtime sağlayıcı oluşturucuları) ve @openclaw/openrouter-provider (sağlayıcı oluşturucu ve onboarding/yapılandırma yardımcıları) için de temel oluşturur.
Her çıkarım çağrısından önce token değişimine ihtiyaç duyan sağlayıcılar için:
prepareRuntimeAuth: async (ctx) => {
  const exchanged = await exchangeToken(ctx.apiKey);
  return {
    apiKey: exchanged.token,
    baseUrl: exchanged.baseUrl,
    expiresAt: exchanged.expiresAt,
  };
},
OpenClaw hook’ları bu sırayla çağırır. Çoğu sağlayıcı yalnızca 2-3 tanesini kullanır: OpenClaw’ın artık çağırmadığı, ProviderPlugin.capabilities ve suppressBuiltInModel gibi yalnızca uyumluluk amaçlı sağlayıcı alanları burada listelenmez.
#HookNe zaman kullanılır
1catalogModel kataloğu veya temel URL varsayılanları
2applyConfigDefaultsYapılandırma somutlaştırması sırasında sağlayıcıya ait genel varsayılanlar
3normalizeModelIdAramadan önce eski/önizleme model kimliği takma ad temizliği
4normalizeTransportGenel model birleştirmesinden önce sağlayıcı ailesi api / baseUrl temizliği
5normalizeConfigmodels.providers.<id> yapılandırmasını normalleştirme
6applyNativeStreamingUsageCompatYapılandırma sağlayıcıları için yerel akış kullanım uyumluluğu yeniden yazımları
7resolveConfigApiKeySağlayıcıya ait env-marker kimlik doğrulaması çözümleme
8resolveSyntheticAuthYerel/kendi barındırılan veya yapılandırma destekli sentetik kimlik doğrulama
9shouldDeferSyntheticProfileAuthEnv/yapılandırma kimlik doğrulamasının arkasındaki sentetik saklanan profil yer tutucularını düşürme
10resolveDynamicModelRastgele upstream model kimliklerini kabul etme
11prepareDynamicModelÇözümlemeden önce zaman uyumsuz metadata getirme
12normalizeResolvedModelÇalıştırıcıdan önce taşıma yeniden yazımları
13normalizeToolSchemasKayıttan önce sağlayıcıya ait araç şeması temizliği
14inspectToolSchemasSağlayıcıya ait araç şeması tanılamaları
15resolveReasoningOutputModeEtiketli ve yerel reasoning çıktısı sözleşmesi
16prepareExtraParamsVarsayılan istek parametreleri
17createStreamFnTamamen özel StreamFn taşıması
19wrapStreamFnNormal akış yolunda özel header/body sarmalayıcıları
20resolveTransportTurnStateHer turn için yerel header/metadata
21resolveWebSocketSessionPolicyYerel WS oturum header’ları/bekleme süresi
22formatApiKeyÖzel çalışma zamanı belirteç biçimi
23refreshOAuthÖzel OAuth yenileme
24buildAuthDoctorHintKimlik doğrulama onarım rehberliği
25matchesContextOverflowErrorSağlayıcıya ait overflow algılama
26classifyFailoverReasonSağlayıcıya ait hız sınırı/aşırı yük sınıflandırması
27isCacheTtlEligiblePrompt önbelleği TTL geçidi
28buildMissingAuthMessageÖzel eksik kimlik doğrulama ipucu
29augmentModelCatalogSentetik ileriye dönük uyumluluk satırları
30resolveThinkingProfileModele özgü /think seçenek kümesi
31isBinaryThinkingİkili düşünme açık/kapalı uyumluluğu
32supportsXHighThinkingxhigh reasoning desteği uyumluluğu
33resolveDefaultThinkingLevelVarsayılan /think ilkesi uyumluluğu
34isModernModelRefCanlı/smoke model eşleştirme
35prepareRuntimeAuthÇıkarımdan önce belirteç değişimi
36resolveUsageAuthÖzel kullanım kimlik bilgisi ayrıştırma
37fetchUsageSnapshotÖzel kullanım endpoint’i
38createEmbeddingProviderBellek/arama için sağlayıcıya ait embedding adaptörü
39buildReplayPolicyÖzel transcript yeniden oynatma/Compaction ilkesi
40sanitizeReplayHistoryGenel temizlikten sonra sağlayıcıya özgü yeniden oynatma yeniden yazımları
41validateReplayTurnsGömülü çalıştırıcıdan önce katı yeniden oynatma turn doğrulaması
42onModelSelectedSeçim sonrası callback (örn. telemetri)
Çalışma zamanı geri dönüş notları:
  • normalizeConfig önce eşleşen sağlayıcıyı, ardından biri yapılandırmayı gerçekten değiştirene kadar hook destekli diğer sağlayıcı Plugin’lerini kontrol eder. Hiçbir sağlayıcı hook’u desteklenen bir Google ailesi yapılandırma girdisini yeniden yazmazsa, paketlenmiş Google yapılandırma normalleştiricisi yine de uygulanır.
  • resolveConfigApiKey, sunulduğunda sağlayıcı hook’unu kullanır. Amazon Bedrock AWS env-marker çözümlemesini kendi sağlayıcı Plugin’inde tutar; çalışma zamanı kimlik doğrulamasının kendisi auth: "aws-sdk" ile yapılandırıldığında hâlâ AWS SDK varsayılan zincirini kullanır.
  • resolveThinkingProfile(ctx), seçilen provider, modelId, isteğe bağlı birleştirilmiş reasoning katalog ipucu ve isteğe bağlı birleştirilmiş model compat bilgilerini alır. compat değerini yalnızca sağlayıcının düşünme UI/profilini seçmek için kullanın.
  • resolveSystemPromptContribution, bir sağlayıcının bir model ailesi için önbellek duyarlı sistem prompt rehberliği enjekte etmesine olanak tanır. Davranış tek bir sağlayıcı/model ailesine ait olduğunda ve kararlı/dinamik önbellek ayrımını koruması gerektiğinde before_prompt_build yerine bunu tercih edin.
Ayrıntılı açıklamalar ve gerçek dünya örnekleri için bkz. İç Mekanizmalar: Sağlayıcı Çalışma Zamanı Hook’ları.
5

Ek yetenekler ekleyin (isteğe bağlı)

Adım 5: Ek yetenekler ekleyin

Bir sağlayıcı Plugin’i metin çıkarımının yanında embedding’ler, konuşma, gerçek zamanlı transkripsiyon, gerçek zamanlı ses, medya anlama, görüntü oluşturma, video oluşturma, web getirme ve web arama kaydedebilir. OpenClaw bunu bir hibrit-yetenek Plugin’i olarak sınıflandırır; şirket Plugin’leri için önerilen kalıp budur (satıcı başına bir Plugin). Bkz. İç Mekanizmalar: Yetenek Sahipliği.Her yeteneği mevcut api.registerProvider(...) çağrınızın yanında register(api) içinde kaydedin. Yalnızca ihtiyacınız olan sekmeleri seçin:
import {
  assertOkOrThrowProviderError,
  postJsonRequest,
} from "openclaw/plugin-sdk/provider-http";

api.registerSpeechProvider({
  id: "acme-ai",
  label: "Acme Speech",
  defaultTimeoutMs: 120_000,
  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();
    }
  },
});
Provider HTTP hataları için assertOkOrThrowProviderError(...) kullanın; böylece Plugin’ler sınırlandırılmış hata gövdesi okumalarını, JSON hata ayrıştırmasını ve istek kimliği son eklerini paylaşır.
6

Test

Adım 6: Test

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’a yayımlama

Provider plugin’leri, diğer harici kod plugin’leriyle aynı şekilde yayımlanır:
clawhub package publish your-org/your-plugin --dry-run
clawhub package publish your-org/your-plugin
Burada eski yalnızca skill yayımlama takma adını kullanmayın; plugin paketleri clawhub package publish kullanmalıdır.

Dosya yapısı

<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)

Katalog sırası referansı

catalog.order, kataloğunuzun yerleşik provider’lara göre ne zaman birleştirileceğini kontrol eder:
SıraNe zamanKullanım durumu
simpleİlk geçişDüz API anahtarlı provider’lar
profilesimple sonrasıKimlik doğrulama profillerine bağlı provider’lar
pairedprofile sonrasıBirden fazla ilgili girdiyi sentezle
lateSon geçişMevcut provider’ları geçersiz kıl (çakışmada kazanır)

Sonraki adımlar

İlgili