From 15bee338e9e7e9cdfdc6115ba77373e31b2805ff Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Sat, 4 Apr 2026 07:46:02 +0100 Subject: [PATCH] docs: refresh provider hook docs --- docs/concepts/model-providers.md | 28 ++++++++---- docs/plugins/architecture.md | 66 ++++++++++++++++------------ docs/plugins/sdk-provider-plugins.md | 56 ++++++++++++----------- 3 files changed, 86 insertions(+), 64 deletions(-) diff --git a/docs/concepts/model-providers.md b/docs/concepts/model-providers.md index 9527fbb26f3..a9ee40ead83 100644 --- a/docs/concepts/model-providers.md +++ b/docs/concepts/model-providers.md @@ -28,14 +28,14 @@ For model selection rules, see [/concepts/models](/concepts/models). map is now just for non-plugin/core providers and a few generic-precedence cases such as Anthropic API-key-first onboarding. - Provider plugins can also own provider runtime behavior via - `resolveDynamicModel`, `prepareDynamicModel`, `normalizeResolvedModel`, - `capabilities`, `prepareExtraParams`, `wrapStreamFn`, `formatApiKey`, - `refreshOAuth`, `buildAuthDoctorHint`, - `isCacheTtlEligible`, `buildMissingAuthMessage`, - `suppressBuiltInModel`, `augmentModelCatalog`, `isBinaryThinking`, - `supportsXHighThinking`, `resolveDefaultThinkingLevel`, - `isModernModelRef`, `prepareRuntimeAuth`, `resolveUsageAuth`, and - `fetchUsageSnapshot`. + `normalizeConfig`, `resolveDynamicModel`, `prepareDynamicModel`, + `normalizeResolvedModel`, `capabilities`, `prepareExtraParams`, + `wrapStreamFn`, `formatApiKey`, `refreshOAuth`, `buildAuthDoctorHint`, + `matchesContextOverflowError`, `classifyFailoverReason`, + `isCacheTtlEligible`, `buildMissingAuthMessage`, `suppressBuiltInModel`, + `augmentModelCatalog`, `isBinaryThinking`, `supportsXHighThinking`, + `resolveDefaultThinkingLevel`, `applyConfigDefaults`, `isModernModelRef`, + `prepareRuntimeAuth`, `resolveUsageAuth`, and `fetchUsageSnapshot`. - Note: provider runtime `capabilities` is shared runner metadata (provider family, transcript/tooling quirks, transport/cache hints). It is not the same as the [public capability model](/plugins/architecture#public-capability-model) @@ -53,6 +53,7 @@ Typical split: - `wizard.setup` / `wizard.modelPicker`: provider owns auth-choice labels, legacy aliases, onboarding allowlist hints, and setup entries in onboarding/model pickers - `catalog`: provider appears in `models.providers` +- `normalizeConfig`: provider normalizes `models.providers.` config before runtime uses it - `resolveDynamicModel`: provider accepts model ids not present in the local static catalog yet - `prepareDynamicModel`: provider needs a metadata refresh before retrying @@ -67,6 +68,10 @@ Typical split: refreshers are not enough - `buildAuthDoctorHint`: provider appends repair guidance when OAuth refresh fails +- `matchesContextOverflowError`: provider recognizes provider-specific + context-window overflow errors that generic heuristics would miss +- `classifyFailoverReason`: provider maps provider-specific raw transport/API + errors to failover reasons such as rate limit or overload - `isCacheTtlEligible`: provider decides which upstream model ids support prompt-cache TTL - `buildMissingAuthMessage`: provider replaces the generic auth-store error with a provider-specific recovery hint @@ -78,6 +83,8 @@ Typical split: - `supportsXHighThinking`: provider opts selected models into `xhigh` - `resolveDefaultThinkingLevel`: provider owns default `/think` policy for a model family +- `applyConfigDefaults`: provider applies provider-specific global defaults + during config materialization based on auth mode, env, or model family - `isModernModelRef`: provider owns live/smoke preferred-model matching - `prepareRuntimeAuth`: provider turns a configured credential into a short lived runtime token @@ -89,7 +96,10 @@ Typical split: Current bundled examples: - `anthropic`: Claude 4.6 forward-compat fallback, auth repair hints, usage - endpoint fetching, and cache-TTL/provider-family metadata + endpoint fetching, cache-TTL/provider-family metadata, and auth-aware global + config defaults +- `amazon-bedrock`: provider-owned context-overflow matching and failover + reason classification for Bedrock-specific throttle/not-ready errors - `openrouter`: pass-through model ids, request wrappers, provider capability hints, and cache-TTL policy - `github-copilot`: onboarding/device login, forward-compat model fallback, diff --git a/docs/plugins/architecture.md b/docs/plugins/architecture.md index c81d32239fd..eda5fa320fb 100644 --- a/docs/plugins/architecture.md +++ b/docs/plugins/architecture.md @@ -597,8 +597,8 @@ Provider plugins now have two layers: - manifest metadata: `providerAuthEnvVars` for cheap env-auth lookup before runtime load, plus `providerAuthChoices` for cheap onboarding/auth-choice labels and CLI flag metadata before runtime load -- config-time hooks: `catalog` / legacy `discovery` -- runtime hooks: `resolveDynamicModel`, `prepareDynamicModel`, `normalizeResolvedModel`, `capabilities`, `prepareExtraParams`, `wrapStreamFn`, `formatApiKey`, `refreshOAuth`, `buildAuthDoctorHint`, `isCacheTtlEligible`, `buildMissingAuthMessage`, `suppressBuiltInModel`, `augmentModelCatalog`, `isBinaryThinking`, `supportsXHighThinking`, `resolveDefaultThinkingLevel`, `isModernModelRef`, `prepareRuntimeAuth`, `resolveUsageAuth`, `fetchUsageSnapshot`, `buildReplayPolicy`, `sanitizeReplayHistory`, `validateReplayTurns` +- config-time hooks: `catalog` / legacy `discovery` plus `applyConfigDefaults` +- runtime hooks: `normalizeConfig`, `resolveDynamicModel`, `prepareDynamicModel`, `normalizeResolvedModel`, `capabilities`, `prepareExtraParams`, `wrapStreamFn`, `formatApiKey`, `refreshOAuth`, `buildAuthDoctorHint`, `matchesContextOverflowError`, `classifyFailoverReason`, `isCacheTtlEligible`, `buildMissingAuthMessage`, `suppressBuiltInModel`, `augmentModelCatalog`, `isBinaryThinking`, `supportsXHighThinking`, `resolveDefaultThinkingLevel`, `isModernModelRef`, `prepareRuntimeAuth`, `resolveUsageAuth`, `fetchUsageSnapshot`, `buildReplayPolicy`, `sanitizeReplayHistory`, `validateReplayTurns` OpenClaw still owns the generic agent loop, failover, transcript handling, and tool policy. These hooks are the extension surface for provider-specific behavior without @@ -620,30 +620,34 @@ The "When to use" column is the quick decision guide. | # | Hook | What it does | When to use | | --- | ----------------------------- | ---------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------ | | 1 | `catalog` | Publish provider config into `models.providers` during `models.json` generation | Provider owns a catalog or base URL defaults | +| 2 | `applyConfigDefaults` | Apply provider-owned global config defaults during config materialization | Defaults depend on auth mode, env, or provider model-family semantics | | -- | _(built-in model lookup)_ | OpenClaw tries the normal registry/catalog path first | _(not a plugin hook)_ | -| 2 | `resolveDynamicModel` | Sync fallback for provider-owned model ids not in the local registry yet | Provider accepts arbitrary upstream model ids | -| 3 | `prepareDynamicModel` | Async warm-up, then `resolveDynamicModel` runs again | Provider needs network metadata before resolving unknown ids | -| 4 | `normalizeResolvedModel` | Final rewrite before the embedded runner uses the resolved model | Provider needs transport rewrites but still uses a core transport | -| 5 | `capabilities` | Provider-owned transcript/tooling metadata used by shared core logic | Provider needs transcript/provider-family quirks | -| 6 | `prepareExtraParams` | Request-param normalization before generic stream option wrappers | Provider needs default request params or per-provider param cleanup | -| 7 | `wrapStreamFn` | Stream wrapper after generic wrappers are applied | Provider needs request headers/body/model compat wrappers without a custom transport | -| 8 | `formatApiKey` | Auth-profile formatter: stored profile becomes the runtime `apiKey` string | Provider stores extra auth metadata and needs a custom runtime token shape | -| 9 | `refreshOAuth` | OAuth refresh override for custom refresh endpoints or refresh-failure policy | Provider does not fit the shared `pi-ai` refreshers | -| 10 | `buildAuthDoctorHint` | Repair hint appended when OAuth refresh fails | Provider needs provider-owned auth repair guidance after refresh failure | -| 11 | `isCacheTtlEligible` | Prompt-cache policy for proxy/backhaul providers | Provider needs proxy-specific cache TTL gating | -| 12 | `buildMissingAuthMessage` | Replacement for the generic missing-auth recovery message | Provider needs a provider-specific missing-auth recovery hint | -| 13 | `suppressBuiltInModel` | Stale upstream model suppression plus optional user-facing error hint | Provider needs to hide stale upstream rows or replace them with a vendor hint | -| 14 | `augmentModelCatalog` | Synthetic/final catalog rows appended after discovery | Provider needs synthetic forward-compat rows in `models list` and pickers | -| 15 | `isBinaryThinking` | On/off reasoning toggle for binary-thinking providers | Provider exposes only binary thinking on/off | -| 16 | `supportsXHighThinking` | `xhigh` reasoning support for selected models | Provider wants `xhigh` on only a subset of models | -| 17 | `resolveDefaultThinkingLevel` | Default `/think` level for a specific model family | Provider owns default `/think` policy for a model family | -| 18 | `isModernModelRef` | Modern-model matcher for live profile filters and smoke selection | Provider owns live/smoke preferred-model matching | -| 19 | `prepareRuntimeAuth` | Exchange a configured credential into the actual runtime token/key just before inference | Provider needs a token exchange or short-lived request credential | -| 20 | `resolveUsageAuth` | Resolve usage/billing credentials for `/usage` and related status surfaces | Provider needs custom usage/quota token parsing or a different usage credential | -| 21 | `fetchUsageSnapshot` | Fetch and normalize provider-specific usage/quota snapshots after auth is resolved | Provider needs a provider-specific usage endpoint or payload parser | -| 22 | `buildReplayPolicy` | Return a replay policy controlling transcript handling for the provider | Provider needs custom transcript policy (for example, thinking-block stripping) | -| 23 | `sanitizeReplayHistory` | Rewrite replay history after generic transcript cleanup | Provider needs provider-specific replay rewrites beyond shared compaction helpers | -| 24 | `validateReplayTurns` | Final replay-turn validation or reshaping before the embedded runner | Provider transport needs stricter turn validation after generic sanitation | +| 3 | `normalizeConfig` | Normalize `models.providers.` before runtime/provider resolution | Provider needs config cleanup that should live with the plugin | +| 4 | `resolveDynamicModel` | Sync fallback for provider-owned model ids not in the local registry yet | Provider accepts arbitrary upstream model ids | +| 5 | `prepareDynamicModel` | Async warm-up, then `resolveDynamicModel` runs again | Provider needs network metadata before resolving unknown ids | +| 6 | `normalizeResolvedModel` | Final rewrite before the embedded runner uses the resolved model | Provider needs transport rewrites but still uses a core transport | +| 7 | `capabilities` | Provider-owned transcript/tooling metadata used by shared core logic | Provider needs transcript/provider-family quirks | +| 8 | `prepareExtraParams` | Request-param normalization before generic stream option wrappers | Provider needs default request params or per-provider param cleanup | +| 9 | `wrapStreamFn` | Stream wrapper after generic wrappers are applied | Provider needs request headers/body/model compat wrappers without a custom transport | +| 10 | `formatApiKey` | Auth-profile formatter: stored profile becomes the runtime `apiKey` string | Provider stores extra auth metadata and needs a custom runtime token shape | +| 11 | `refreshOAuth` | OAuth refresh override for custom refresh endpoints or refresh-failure policy | Provider does not fit the shared `pi-ai` refreshers | +| 12 | `buildAuthDoctorHint` | Repair hint appended when OAuth refresh fails | Provider needs provider-owned auth repair guidance after refresh failure | +| 13 | `matchesContextOverflowError` | Provider-owned context-window overflow matcher | Provider has raw overflow errors generic heuristics would miss | +| 14 | `classifyFailoverReason` | Provider-owned failover reason classification | Provider can map raw API/transport errors to rate-limit/overload/etc | +| 15 | `isCacheTtlEligible` | Prompt-cache policy for proxy/backhaul providers | Provider needs proxy-specific cache TTL gating | +| 16 | `buildMissingAuthMessage` | Replacement for the generic missing-auth recovery message | Provider needs a provider-specific missing-auth recovery hint | +| 17 | `suppressBuiltInModel` | Stale upstream model suppression plus optional user-facing error hint | Provider needs to hide stale upstream rows or replace them with a vendor hint | +| 18 | `augmentModelCatalog` | Synthetic/final catalog rows appended after discovery | Provider needs synthetic forward-compat rows in `models list` and pickers | +| 19 | `isBinaryThinking` | On/off reasoning toggle for binary-thinking providers | Provider exposes only binary thinking on/off | +| 20 | `supportsXHighThinking` | `xhigh` reasoning support for selected models | Provider wants `xhigh` on only a subset of models | +| 21 | `resolveDefaultThinkingLevel` | Default `/think` level for a specific model family | Provider owns default `/think` policy for a model family | +| 22 | `isModernModelRef` | Modern-model matcher for live profile filters and smoke selection | Provider owns live/smoke preferred-model matching | +| 23 | `prepareRuntimeAuth` | Exchange a configured credential into the actual runtime token/key just before inference | Provider needs a token exchange or short-lived request credential | +| 24 | `resolveUsageAuth` | Resolve usage/billing credentials for `/usage` and related status surfaces | Provider needs custom usage/quota token parsing or a different usage credential | +| 25 | `fetchUsageSnapshot` | Fetch and normalize provider-specific usage/quota snapshots after auth is resolved | Provider needs a provider-specific usage endpoint or payload parser | +| 26 | `buildReplayPolicy` | Return a replay policy controlling transcript handling for the provider | Provider needs custom transcript policy (for example, thinking-block stripping) | +| 27 | `sanitizeReplayHistory` | Rewrite replay history after generic transcript cleanup | Provider needs provider-specific replay rewrites beyond shared compaction helpers | +| 28 | `validateReplayTurns` | Final replay-turn validation or reshaping before the embedded runner | Provider transport needs stricter turn validation after generic sanitation | 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 @@ -707,10 +711,10 @@ api.registerProvider({ - Anthropic uses `resolveDynamicModel`, `capabilities`, `buildAuthDoctorHint`, `resolveUsageAuth`, `fetchUsageSnapshot`, `isCacheTtlEligible`, - `resolveDefaultThinkingLevel`, and `isModernModelRef` because it owns Claude - 4.6 forward-compat, provider-family hints, auth repair guidance, usage - endpoint integration, prompt-cache eligibility, and Claude default/adaptive - thinking policy. + `resolveDefaultThinkingLevel`, `applyConfigDefaults`, and `isModernModelRef` + because it owns Claude 4.6 forward-compat, provider-family hints, auth + repair guidance, usage endpoint integration, prompt-cache eligibility, + auth-aware config defaults, and Claude default/adaptive thinking policy. - OpenAI uses `resolveDynamicModel`, `normalizeResolvedModel`, and `capabilities` plus `buildMissingAuthMessage`, `suppressBuiltInModel`, `augmentModelCatalog`, `supportsXHighThinking`, and `isModernModelRef` @@ -740,6 +744,10 @@ api.registerProvider({ modern-model matching; Gemini CLI OAuth also uses `formatApiKey`, `resolveUsageAuth`, and `fetchUsageSnapshot` for token formatting, token parsing, and quota endpoint wiring. +- Amazon Bedrock uses `buildReplayPolicy`, `matchesContextOverflowError`, + `classifyFailoverReason`, and `resolveDefaultThinkingLevel` because it owns + Bedrock-specific replay policy plus throttle/not-ready/context-overflow + error classification for Anthropic-on-Bedrock traffic. - Moonshot uses `catalog` plus `wrapStreamFn` because it still uses the shared OpenAI transport but needs provider-owned thinking payload normalization. - Kilocode uses `catalog`, `capabilities`, `wrapStreamFn`, and diff --git a/docs/plugins/sdk-provider-plugins.md b/docs/plugins/sdk-provider-plugins.md index 7a879fb6d65..b032c8d28d6 100644 --- a/docs/plugins/sdk-provider-plugins.md +++ b/docs/plugins/sdk-provider-plugins.md @@ -318,32 +318,36 @@ API key auth, and dynamic model resolution. | # | Hook | When to use | | --- | --- | --- | | 1 | `catalog` | Model catalog or base URL defaults | - | 2 | `resolveDynamicModel` | Accept arbitrary upstream model IDs | - | 3 | `prepareDynamicModel` | Async metadata fetch before resolving | - | 4 | `normalizeResolvedModel` | Transport rewrites before the runner | - | 5 | `capabilities` | Transcript/tooling metadata (data, not callable) | - | 6 | `prepareExtraParams` | Default request params | - | 7 | `wrapStreamFn` | Custom headers/body wrappers | - | 8 | `resolveTransportTurnState` | Native per-turn headers/metadata | - | 9 | `resolveWebSocketSessionPolicy` | Native WS session headers/cool-down | - | 10 | `formatApiKey` | Custom runtime token shape | - | 11 | `refreshOAuth` | Custom OAuth refresh | - | 12 | `buildAuthDoctorHint` | Auth repair guidance | - | 13 | `isCacheTtlEligible` | Prompt cache TTL gating | - | 14 | `buildMissingAuthMessage` | Custom missing-auth hint | - | 15 | `suppressBuiltInModel` | Hide stale upstream rows | - | 16 | `augmentModelCatalog` | Synthetic forward-compat rows | - | 17 | `isBinaryThinking` | Binary thinking on/off | - | 18 | `supportsXHighThinking` | `xhigh` reasoning support | - | 19 | `resolveDefaultThinkingLevel` | Default `/think` policy | - | 20 | `isModernModelRef` | Live/smoke model matching | - | 21 | `prepareRuntimeAuth` | Token exchange before inference | - | 22 | `resolveUsageAuth` | Custom usage credential parsing | - | 23 | `fetchUsageSnapshot` | Custom usage endpoint | - | 24 | `onModelSelected` | Post-selection callback (e.g. telemetry) | - | 25 | `buildReplayPolicy` | Custom transcript policy (e.g. thinking-block stripping) | - | 26 | `sanitizeReplayHistory` | Provider-specific replay rewrites after generic cleanup | - | 27 | `validateReplayTurns` | Strict replay-turn validation before the embedded runner | + | 2 | `applyConfigDefaults` | Provider-owned global defaults during config materialization | + | 3 | `normalizeConfig` | Normalize `models.providers.` config | + | 4 | `resolveDynamicModel` | Accept arbitrary upstream model IDs | + | 5 | `prepareDynamicModel` | Async metadata fetch before resolving | + | 6 | `normalizeResolvedModel` | Transport rewrites before the runner | + | 7 | `capabilities` | Transcript/tooling metadata (data, not callable) | + | 8 | `prepareExtraParams` | Default request params | + | 9 | `wrapStreamFn` | Custom headers/body wrappers | + | 10 | `resolveTransportTurnState` | Native per-turn headers/metadata | + | 11 | `resolveWebSocketSessionPolicy` | Native WS session headers/cool-down | + | 12 | `formatApiKey` | Custom runtime token shape | + | 13 | `refreshOAuth` | Custom OAuth refresh | + | 14 | `buildAuthDoctorHint` | Auth repair guidance | + | 15 | `matchesContextOverflowError` | Provider-owned overflow detection | + | 16 | `classifyFailoverReason` | Provider-owned rate-limit/overload classification | + | 17 | `isCacheTtlEligible` | Prompt cache TTL gating | + | 18 | `buildMissingAuthMessage` | Custom missing-auth hint | + | 19 | `suppressBuiltInModel` | Hide stale upstream rows | + | 20 | `augmentModelCatalog` | Synthetic forward-compat rows | + | 21 | `isBinaryThinking` | Binary thinking on/off | + | 22 | `supportsXHighThinking` | `xhigh` reasoning support | + | 23 | `resolveDefaultThinkingLevel` | Default `/think` policy | + | 24 | `isModernModelRef` | Live/smoke model matching | + | 25 | `prepareRuntimeAuth` | Token exchange before inference | + | 26 | `resolveUsageAuth` | Custom usage credential parsing | + | 27 | `fetchUsageSnapshot` | Custom usage endpoint | + | 28 | `onModelSelected` | Post-selection callback (e.g. telemetry) | + | 29 | `buildReplayPolicy` | Custom transcript policy (e.g. thinking-block stripping) | + | 30 | `sanitizeReplayHistory` | Provider-specific replay rewrites after generic cleanup | + | 31 | `validateReplayTurns` | Strict replay-turn validation before the embedded runner | For detailed descriptions and real-world examples, see [Internals: Provider Runtime Hooks](/plugins/architecture#provider-runtime-hooks).