Provider runtime hooks
Provider plugins have three layers:- Manifest metadata for cheap pre-runtime lookup:
setup.providers[].envVars,providerAuthAliases,providerAuthChoices, andchannelConfigs. - Config-time hooks:
catalogplusapplyConfigDefaults. - Runtime hooks: 40+ optional hooks covering auth, model resolution, stream wrapping, thinking levels, replay policy, and usage endpoints. See Hook order and usage.
setup.providers[].envVars when the provider has env-based
credentials that generic auth/status/model-picker paths should see without
loading plugin runtime. Use manifest providerAuthAliases
when one provider id should reuse another provider id’s env vars, auth profiles,
config-backed auth, and API-key onboarding choice. Use manifest
providerAuthChoices when onboarding/auth-choice CLI surfaces should know the
provider’s choice id, group labels, and simple one-flag auth wiring without
loading provider runtime. Keep provider runtime
envVars for operator-facing hints such as onboarding labels or OAuth
client-id/client-secret setup vars.
Describe env-driven channel setup and auth through the owning
channelConfigs.<id>.schema and setup descriptors.
Hook order and usage
For model/provider plugins, OpenClaw calls hooks in this rough order. The “When to use” column is the quick decision guide. Compatibility-only provider fields that OpenClaw no longer calls, such asProviderPlugin.capabilities and suppressBuiltInModel, are intentionally not
listed here.
reconcileLocalService runs only for configured local services, including a
healthy process reused from outside the current Gateway process. Keep it cheap,
idempotent, and abort-aware. A rejection blocks the provider request and
releases its lease without classifying the healthy process as a startup failure.
Normalization dispatch is hook-specific:
- Model references apply manifest-declared model-ID normalization once before
normalizeModelIddispatch. The matched provider hook can refine that prepared model ID; an empty result keeps it unchanged. OpenClaw does not try other providers’ normalization hooks or reapply manifest rules afterward. Reference parsing reads the selected runtime registry without activating plugins. Executable normalization requires a prepared runtime owner; reads without one use static manifest policies only. A directly registered provider owns its ID; compatibility aliases match only when no literal provider exists, preserving alias-only routes and explicit API-owner eligibility. normalizeTransporttries the matched provider first. Only if that does not changeapiorbaseUrland the provider has nomodels.providers.<id>entry does it try other transport hooks, stopping at the first change.normalizeConfiguses the owning bundled provider’s lightweight policy surface first. If that surface has nonormalizeConfighook, OpenClaw may call the matched runtime owner, provided runtime loading is allowed and, when a config is supplied, that owner has explicit plugin activation. It never scans other providers’ hooks or falls through after the owning hook returns no change. Config assembly passesallowRuntimePluginLoad: false, so it uses bundled policy without loading provider runtime.
normalizeConfig hook, shared with its lightweight policy surface. It is not a
separate core compatibility backstop.
If the provider needs a fully custom wire protocol or custom request executor,
that is a different class of extension. These hooks are for provider behavior
that still runs on OpenClaw’s normal inference loop.
resolveUsageAuth decides whether OpenClaw should call fetchUsageSnapshot or
fall back to generic credential resolution for usage/status surfaces. Return
{ token, accountId?, subscriptionType?, rateLimitTier? } when the provider
has a usage credential (the optional plan metadata flows into
fetchUsageSnapshot), return
{ handled: true } when provider-owned usage auth has handled the request and
must suppress generic API-key/OAuth fallback, and return null or undefined
when the provider did not handle usage auth.
Declare organization or billing credentials in manifest
providerUsageAuthEnvVars. This lets generic discovery and secret-scrubbing
surfaces recognize them without making them inference auth candidates.
Provider example
Built-in examples
Bundled provider plugins combine the hooks above to fit each vendor’s catalog, auth, thinking, replay, and usage needs. The authoritative hook set lives with each plugin underextensions/; this page illustrates the shapes rather than
mirroring the list.
Pass-through catalog providers
Pass-through catalog providers
OpenRouter, Kilocode, Z.AI, xAI register
catalog plus
resolveDynamicModel / prepareDynamicModel so they can surface upstream
model ids ahead of OpenClaw’s static catalog.OAuth and usage endpoint providers
OAuth and usage endpoint providers
GitHub Copilot, Gemini CLI, ChatGPT Codex, MiniMax, Xiaomi, z.ai pair
prepareRuntimeAuth or formatApiKey with resolveUsageAuth +
fetchUsageSnapshot to own token exchange and /usage integration.Replay and transcript cleanup families
Replay and transcript cleanup families
Shared named families (
google-gemini, passthrough-gemini,
anthropic-by-model, hybrid-anthropic-openai) let providers opt into
transcript policy via buildReplayPolicy instead of each plugin
re-implementing cleanup.Catalog-only providers
Catalog-only providers
byteplus, cloudflare-ai-gateway, huggingface, kimi-coding, nvidia,
qianfan, synthetic, together, venice, vercel-ai-gateway, and
volcengine register just catalog and ride the shared inference loop.Anthropic-specific stream helpers
Anthropic-specific stream helpers
Beta headers,
/fast / serviceTier, and context1m live inside the
Anthropic plugin’s public api.ts / contract-api.ts seam
(wrapAnthropicProviderStream, resolveAnthropicBetas,
resolveAnthropicFastMode, resolveAnthropicServiceTier) rather than in
the generic SDK.Provider catalogs
Provider plugins can define model catalogs for inference withregisterProvider({ catalog: { run(...) { ... } } }).
catalog.run(...) returns the same shape OpenClaw writes into
models.providers:
{ provider }for one provider entry{ providers }for multiple provider entries
catalog when the plugin owns provider-specific model ids, base URL
defaults, or auth-gated model metadata.
catalog.order controls when a plugin’s catalog merges relative to OpenClaw’s
built-in implicit providers:
simple: plain API-key or env-driven providersprofile: providers that appear when auth profiles existpaired: providers that synthesize multiple related provider entrieslate: last pass, after other implicit providers
api.registerModelCatalogProvider({ provider, kinds, staticCatalog, liveCatalog }). This is the forward path for list/help/picker surfaces and supports
text, voice, image_generation, video_generation, and music_generation
rows. Provider plugins still own live endpoint calls, token exchange, and
vendor response mapping; core owns the common row shape, source labels, and
media tool help formatting. Media-generation provider registrations synthesize
static catalog rows automatically from defaultModel, models, and
capabilities.
Compatibility:
discoverystill works as a legacy alias, but emits a deprecation warning- if both
cataloganddiscoveryare registered, OpenClaw usescatalogand emits a warning augmentModelCatalogis deprecated; bundled providers should publish supplemental rows throughregisterModelCatalogProvider