ClawRouter: Credential-Scoped Model Routing and Quotas
Route credential-scoped models through ClawRouter with the bundled plugin and see managed quotas. This page covers setup, model discovery, and usage screens for OpenClaw users.
Read this when
- You want one managed key for multiple model providers
- You need ClawRouter model discovery or quota reporting in OpenClaw
A single policy-scoped key from ClawRouter covers several upstream model providers for OpenClaw. Only the models that key permits are discovered by the bundled clawrouter plugin, which routes every model over its declared protocol and surfaces the key's budget and combined usage on OpenClaw usage screens.
Upstream credentials, along with forwarding specific to each provider, remain inside ClawRouter. That means no upstream provider plugin has to be installed or authenticated on the OpenClaw host. Because the plugin ships bundled with OpenClaw (enabledByDefault: true), an issued ClawRouter key is all you need.
| Property | Value |
|---|---|
| Provider | clawrouter |
| Plugin | bundled (included in OpenClaw) |
| Auth | CLAWROUTER_API_KEY |
| Default URL | https://clawrouter.openclaw.ai |
| Model catalog | Credential-scoped via /v1/catalog |
| Quotas | Monthly budget and usage via /v1/usage |
Getting started
Get a scoped credential
Request a ClawRouter key from your ClawRouter administrator, making sure its policy covers the providers, models, and monthly budget you intend to use. A ClawRouter key is shown only once, at issue time.
Configure OpenClaw
export CLAWROUTER_API_KEY="..."
openclaw onboard --auth-choice clawrouter-api-key
openclaw plugins enable clawrouter
clawrouter comes bundled and is on by default. When plugins.allow is set in your configuration, that list must include clawrouter before you enable it. For a custom deployment, point models.providers.clawrouter.baseUrl at the ClawRouter origin; https://clawrouter.openclaw.ai is the default.
List granted models
openclaw models list --all --provider clawrouter
Reuse the returned model refs exactly as they come back. Each keeps its upstream namespace, for example clawrouter/openai/gpt-5.5, clawrouter/anthropic/claude-sonnet-4-6, or clawrouter/google/gemini-3.5-flash. Where agents.defaults.modelPolicy.allow is configured, every selected ClawRouter ref needs to be added to it.
Select a model
openclaw models set clawrouter/<provider>/<model>
A returned model can also be picked for a single run through openclaw agent --model clawrouter/<provider>/<model> --message "...".
Decision models
Native Decisions needs support on the ClawRouter service side plus an eligible router key. Hosted availability: native Decisions is not generally available on the hosted ClawRouter service as of October 20, 2026. Service support remains pending; the bundled OpenClaw adapter does not turn it on by itself.
The example below is conditional: apply it only once your ClawRouter administrator confirms that your deployment and key support the native Decisions route. Compatible self-hosted deployments and future hosted availability are the cases it covers. Pick Luna separately from the conversational model:
{
agents: {
defaults: { decisionModel: "clawrouter/openai/gpt-6-luna" },
entries: {
support: { decisionModel: "clawrouter/openai/gpt-6-luna" },
quiet: { decisionModel: "" },
},
},
}
When an agent override is present, that agent uses its own decision model; an empty string turns off decisions for that agent rather than falling back to the default. Primary, fallback, utility, thinking, and Fast settings are unaffected.
Native OpenAI Decisions for Boolean, choice, and score questions is implemented by the bundled clawrouter owner. Inputs may be explicit text/JSON or inline PNG, JPEG, or WebP images (up to 4 MiB). V2 batches handle as many as 400 questions and 255 choice alternatives. Callers on legacy V1 keep the host's 256-question limit; larger batches need contractVersion: 2. Only auto is accepted for reasoning (or the field may be omitted). Provider probabilities, confidence, usage, and individual refusals stay typed; there is no fallback to chat/JSON, no invented probability, and no ambient conversation history.
Support for a static decision catalog is not a key grant. Every evaluation checks the effective ClawRouter endpoint's /v1/catalog using the router credential prepared for that call. The key has to grant openai/gpt-6-luna with llm.decisions and the native OpenAI Decisions route. Inference then posts to /v1/native/openai/v1/decisions with upstream model gpt-6-luna and the same prepared auth/transport. The host never looks up an upstream OpenAI key. Where a deployment lacks that native service route or key grant, these decisions cannot be evaluated; its existing chat access is not used in place of it. This adapter does not implement the SystemOne or SubQ protocols.
The typed-only declaration is excluded from conversational model selection unless live chat discovery grants that model on its own. On custom deployments, implicit native inventory is scoped to the endpoint: author the Luna model row explicitly under models.providers.clawrouter.models with api: "openai-responses"; even then, the per-call key grant check still applies.
The shared API and selector semantics are described in Decision models.
Text embeddings for memory
For ClawRouter text embeddings, OpenClaw's existing OpenAI-compatible embedding bridge is used rather than a dedicated ClawRouter embedding adapter. The embedding model must be granted by your key, and your ClawRouter deployment must serve POST /v1/embeddings. A model used only for embeddings does not have to appear in the conversational model list. OpenClaw has no embedding model-picker catalog kind at present, so models list is neither an embedding inventory nor a grant check.
Add these settings to the configuration you already have; leave your conversational models, auth bindings, and primary/fallback model settings as they are. Use the API base that ends in /v1 (the conversational ClawRouter plugin accepts this form as well):
{
models: {
providers: {
clawrouter: {
baseUrl: "https://clawrouter.openclaw.ai/v1",
apiKey: { source: "env", provider: "default", id: "CLAWROUTER_API_KEY" },
},
},
},
memory: {
search: {
provider: "clawrouter",
model: "openai/text-embedding-3-large",
fallback: "none",
remote: { batch: { enabled: false } },
},
},
}
An explicitly configured API key is required by the bridge (a SecretRef or an existing saved-profile binding in models.providers.clawrouter.apiKey also counts); it will not pick a conversational auth profile on its own. Keep an existing managed binding rather than swapping it for the example SecretRef. An upstream OpenAI key must not be used. What the bridge sends to the configured router is openai/text-embedding-3-large unchanged, not text-embedding-3-large to OpenAI.
Check the configured route with the registered CLI:
openclaw infer embedding create --agent <id> \
--model clawrouter/openai/text-embedding-3-large \
--text "A short memory note" --json
openclaw memory status --agent <id> --deep
The outer provider prefix clawrouter/ appears in the CLI reference; the memory model setting holds only the router's qualified model id openai/.... The JSON result names the bridge provider openai-compatible. Routing still goes through ClawRouter; no upstream credential and no alternate provider gets selected.
Requests rely on inline /embeddings calls, including ones with multiple text inputs; ClawRouter does not need to implement the asynchronous OpenAI /files or /batches APIs for them. Keep batch API indexing turned off. If memory.search.outputDimensionality is set, the bridge sends dimensions and rejects vectors of any other size. Leave it out to use the model's native size. A forbidden or unknown model fails with the router's HTTP error; fallback: "none" blocks recovery through another provider. Image and audio embeddings are not added by these settings.
See Memory search and embedding dimensions.
Managed non-interactive deployment
The ClawRouter key belongs in the workload's secret injection, with only a SecretRef kept in openclaw.json. The managed fields are:
| Purpose | Config or environment field |
|---|---|
| Router origin | models.providers.clawrouter.baseUrl |
| Credential | models.providers.clawrouter.apiKey -> env SecretRef |
| Secret value | CLAWROUTER_API_KEY in the gateway process environment |
| Default model | agents.defaults.model.primary -> clawrouter/<provider>/<model> |
| Workload tag | models.providers.clawrouter.headers.X-ClawRouter-Project-Id (optional) |
As an example, this JSON5 patch can be owned by a deployment controller:
{
plugins: {
entries: { clawrouter: { enabled: true } },
},
models: {
providers: {
clawrouter: {
baseUrl: "https://clawrouter.internal.example",
apiKey: {
source: "env",
provider: "default",
id: "CLAWROUTER_API_KEY",
},
headers: {
"X-ClawRouter-Project-Id": "fakeco",
},
},
},
},
agents: {
defaults: {
model: { primary: "clawrouter/openai/gpt-5.5" },
},
},
}
When the deployment already sets plugins.allow, keep its existing entries and add clawrouter. Validation and application can run without an interactive wizard:
openclaw config patch --file ./clawrouter.patch.json5 --dry-run --json
openclaw config patch --file ./clawrouter.patch.json5
The dry run resolves the SecretRef, yet its value is never printed. Rotating the ClawRouter key means updating the external Secret that supplies CLAWROUTER_API_KEY and restarting the gateway workload, so the new process environment gets loaded. Neither the config file nor the model reference changes.
On a source-built standalone Docker gateway, the root runtime already ships ClawRouter. Package separately only the channel plugin that requires it, for instance OPENCLAW_EXTENSIONS=clickclack, slack, or msteams; see source-built images with selected plugins. Archive and appliance deployments must ship the same landed source through their own artifact pipeline instead of pulling the OCI image.
Readiness and live proof
Each of these checks proves a different boundary; none replaces another:
# ClawRouter process health only; no credential or upstream model is exercised.
curl -fsS https://clawrouter.internal.example/v1/health
# OpenClaw gateway startup readiness only; no model call is made.
curl -fsS http://127.0.0.1:18789/readyz
# Credential-scoped catalog discovery.
openclaw models list --all --provider clawrouter --json
# Minimal real inference test through the configured ClawRouter provider.
openclaw models status --probe --probe-provider clawrouter --probe-max-tokens 8 --json
# Workload canary using an exact granted model ref.
openclaw agent --agent main \
--model clawrouter/openai/gpt-5.5 \
--message "Reply exactly: CLAWROUTER_CANARY_OK" \
--json
Rather than copying the example model blindly, pick a model that the scoped catalog returns. A /readyz response that succeeds shows the gateway can serve requests; it makes no claim that ClawRouter, the ClawRouter key, or an upstream provider is ready. The inference proofs are the model check and the agent canary.
For live diagnosis, turn on OPENCLAW_DEBUG_MODEL_TRANSPORT=1 in the gateway process, issue the canary, then read the gateway's logs. The metadata-only model transport diagnostics produce lines like:
[model-fetch] start provider=clawrouter api=openai-responses model=openai/gpt-5.5 method=POST url=https://clawrouter.internal.example/v1/responses
[model-fetch] response provider=clawrouter api=openai-responses model=openai/gpt-5.5 status=200
Absent targeted debug flags, fast successful responses and start records use debug; non-2xx responses and any response taking one second or more remain at info. See model transport diagnostics.
When those identifiers exist, the plugin sends bounded X-ClawRouter-Client, X-ClawRouter-Agent-Id, and X-ClawRouter-Session-Id headers. It also maps the model call's diagnostic callId (<run-id>:model:<n>) to X-Request-ID, which lets an OpenClaw model-call event be joined to ClawRouter's metadata-only audit trail. Values that fit the 128-character request-id budget are identical. Longer values keep the :model:<n> suffix plus a stable hash, so distinct calls stay bounded and joinable. Static deployment metadata such as X-ClawRouter-Project-Id can be set in the provider headers map. Agent and session attribution headers keep their own 256-character limit. Automatic request ids that contain characters outside ClawRouter's ASCII identifier set use the same size-limited hash format. Explicitly configured headers, including any case variant of X-Request-ID, take precedence over automatic values. The transport diagnostic records routing and response metadata; credentials, request ids, prompts, and completions are never logged. The selected upstream provider and content-retention state come from ClawRouter's own audit event.
Model discovery
GET /v1/catalog returns { providers: [...] }, where every provider entry lists its own models[] (upstream id, capabilities, and pricing) along with the request routes it supports. Conversational inventory is credential-scoped instead of relying on a shipped fixed model list. The static Luna decision declaration above describes protocol support only. A catalog model is advertised for chat when:
- the ClawRouter key's policy grants its provider;
- the catalog model advertises a supported LLM capability (
llm.responses,llm.chat,llm.messages, orllm.streamwith a matching streaming route); and - the provider exposes a matching route for one of the transports below.
Optional input modalities (["text"] or ["text", "image"]) may be declared by a model. A valid declaration outranks built-in modality inference: explicit text-only models never gain image support from their names. Malformed declarations are treated as text-only. If input is absent, OpenClaw keeps its existing family inference and recognizes exact known native OpenAI image-capable models; unknown model names do not inherit image support from a new GPT generation prefix.
OpenAI Responses and Anthropic Messages rows also receive the model facts that the bundled OpenAI and Anthropic catalogs declare for the same upstream model id and API: the Code Mode tier (so the default tools.codeMode: "auto" engages for the same models), whether the model accepts temperature (GPT-6 and GPT-5.6 requests drop it instead of failing upstream), and image size limits (for example 2576 px for current Claude models). Those plugins do not need to be enabled for this. Matching is exact; unknown, renamed, or future models inherit nothing. Reasoning efforts still come from the ClawRouter catalog. Requests to Claude with extended thinking drop a trailing assistant prefill, as the native Anthropic provider does.
No OpenClaw release is needed to add a model to a supported ClawRouter provider. Successful catalog responses, including an empty granted-model list, are reused for one hour per endpoint and resolved credential. Ordinary model-list reads serve retained inventory while expired data refreshes in the background. Use Refresh in Models to discover changes immediately; explicit refresh bypasses the response cache. A model that needs a new wire protocol requires plugin support first. Cached inventory is not authorization: ClawRouter checks current grants and budgets when a model request is dispatched.
A model's optional displayName is its picker label; without it, OpenClaw uses the provider display name and catalog id, omitting a repeated <provider>/ prefix from the label (for example, Anthropic · claude-sonnet-4-6). The label never changes model identity. For conversational requests, Responses and Chat Completions send the catalog id unchanged; native Anthropic and Gemini routes use upstream at dispatch. A facade that exposes an alias must return only safe catalog metadata, including that alias in the required upstream field, and keep its private target mapping inside the facade.
Protocol and provider plugins
ClawRouter owns upstream credentials; its catalog tells OpenClaw which transport to use, so you never install every upstream company's auth plugin.
| Catalog capability / route | OpenClaw transport |
|---|---|
llm.responses (OpenAI-compatible provider) | openai-responses |
llm.chat (OpenAI-compatible provider) | openai-completions |
llm.messages + anthropic.messages route | anthropic-messages |
llm.stream + streaming google.generate_content route | google-generative-ai |
For those families, the plugin applies the corresponding replay and tool-schema policies as well (tool-schema compat for OpenAI/DeepSeek/Gemini/Perplexity; native replay policies for Anthropic and Google Gemini). Perplexity models receive a strict schema rewrite: patternProperties and additionalProperties are dropped, and properties is declared on every object schema, since Perplexity rejects tool schemas that lack them. When a catalog provider offers only a request format that is not supported, it is deliberately not advertised as an OpenClaw text model. Instead of sending an incompatible payload, normalize such providers to one of the supported contracts in ClawRouter.
Hosted web search
OpenAI's hosted web_search is usable by OpenClaw on a ClawRouter Responses route only if the credential-scoped catalog explicitly advertises that offer with both support and admission. Hosted search is never turned on by model names alone.
The versioned catalog contract works as follows:
nativeCapabilities.versionon the OpenAI model equalsclawrouter.native-capabilities.v1, andweb_searchappears innativeCapabilities.endpoints.responses.hostedTools.- For its eligible HTTP unified
/v1/responsesoffer,hostedToolAdmission.versionequalsclawrouter.hosted-tool-admission.v1andhostedToolAdmission.web_searchequalsadmitted.
Managed search stays as it is when facts are missing, carry an unknown version, or are unadmitted. Hosted replacement is also blocked if web search is disabled, if web_search is denied in tool policy, or if a different search provider is selected. On an admitted route, { type: "web_search" } is declared in place of the managed search function, and returned URL citations show up as clickable source links.
Admission does not promise that every later request will fit a budget. Current grants and pricing are still validated by ClawRouter at dispatch. In particular, arbitrary reasoning requests under hard-reserve budgets are not qualified by this contract, and no hosted-tool call cap is invented by OpenClaw. A deployment that does not yet produce the versioned facts stays on managed search. Should a route reject hosted search, OpenClaw surfaces that error; it does not retry with a different key, nor does it silently swap out the configured search provider.
Image generation
ClawRouter is also registered by the bundled plugin with the native image runtime, the image_generate tool, and the openclaw infer image generate CLI. Only JSON generation is provided, through /v1/images/generations: edits, masks, variations, and streaming are unsupported. This route must be supported by the ClawRouter deployment. Plugin readiness on its own does not prove that the current key can generate images.
openai/gpt-image-2.5-flare, openai/gpt-image-2.5-sunburst, and their -2026-09-08 snapshots are the supported wire-model IDs. These IDs represent protocol support, not grants. A model is advertised by image discovery only if the live /v1/catalog for the same key contains its image.generation capability and an eligible HTTP offer for the unified /v1/images/generations route. Request-dependent affordability stays selectable; the actual request's grant and budget are decided by the service. When catalogs are missing, unknown, empty, or failed, there is never a fallback to a static list or to an earlier successful image lookup.
ClawRouter has no implicit image default. Pick an entitled image model explicitly, and do not substitute the direct OpenAI provider's default. For example, do this only if your key's image catalog grants this model:
openclaw infer image generate \
--model clawrouter/openai/gpt-image-2.5-flare \
--prompt "A blue square on a white background" \
--size 1024x1024 --output-format png --output ./square.png
The same resolved ClawRouter credential, including a configured auth-profile binding, is used for generation and for the catalog check that immediately precedes it. If the bound profile is missing or rejected, no switch is made to another profile or to an upstream OpenAI key. HTTP failures keep their status, and a paid image request is not retried. Result URLs are fetched without provider credentials, with bounded downloads and private-network checks. The request deadline and cancellation both cover catalog lookup, generation, and result downloads. Prompt, image-count, and explicit size bounds are taken from that model's current catalog generation limits; generation is not authorized when limits are unknown.
Quotas and usage
The normal OpenClaw provider-usage surfaces are fed by ClawRouter's /v1/usage response: request, token, and spend totals, plus a monthly budget window when the key carries a limit. Keys that are unmetered still display aggregate usage, though without a percentage window.
Quota lookup draws on the same ClawRouter key used for model discovery. A quota lookup that fails does not block model execution.
To check the live snapshot, run:
openclaw status --usage
openclaw models status
The same provider snapshot is exposed to /status in chat and in OpenClaw's usage UI. Because the budget is policy-wide, requests from another client on the same ClawRouter policy can shift the remaining percentage.
Pool dashboard
To inspect the subscription pool behind your configured key, open ClawRouter in the Control UI sidebar. When models.providers.clawrouter is configured, the bundled plugin loads at Gateway startup, subject to the usual plugin allowlist and enablement settings. If the entry is not yet available, apply the configuration and restart the Gateway. The bundled copy requires no Custom plugin UI lab setting.
The page is read-only and shows the policy's allowed models, subscriptions with headroom per model, account and plan details, credential status, quota windows (including model-specific windows), reset times, extra-usage spend and limits, and request, token, and API-equivalent usage. API-equivalent value describes metered model usage; it is not necessarily the subscription's actual bill. The paid-fallback summary aggregates the API-key and environment usage lanes; these totals can include direct paid routing as well as fallback requests. Choose Refresh to request a fresh snapshot; the page does not poll. Upstream measurements that are missing appear as Not reported.
The page calls the plugin-owned clawrouter.pool.get Gateway method, which requires operator.read. With the same credential that model requests use, the Gateway requests /v1/pool from the configured ClawRouter origin, so the page shows the pool of the policy your agents route through. The key stays on the Gateway and never appears in the page response.
Pool visibility is opt-in on the ClawRouter policy. When it is hidden, ask your ClawRouter admin to enable pool status for that policy. A deployment too old to have /v1/pool reports that an update is needed; rejected keys and temporary connection failures each have their own next-step messages. None of these states block model calls or the existing /v1/usage snapshot.
Troubleshooting
| Symptom | Check |
|---|---|
| No ClawRouter models | Confirm the plugin is enabled and allowed by plugins.allow, then check that the ClawRouter key is active and grants at least one ready provider. |
| A configured ClawRouter model is missing | Inspect its /v1/catalog capability and route support. Unsupported transport contracts are intentionally filtered. |
| Model override rejected by policy | Add the exact catalog ref or clawrouter/* to agents.defaults.modelPolicy.allow. |
401 or 403 from catalog or usage | Reissue or re-scope the ClawRouter key; OpenClaw does not fall back to upstream provider keys. |
| Model call fails after discovery | Check the provider connection and upstream health in ClawRouter, then retry after its readiness state recovers. |
| Usage has totals but no percentage | The policy is unmetered; add a monthly budget in ClawRouter to expose a percentage window. |
Security behavior
- Catalog discovery is bound to the configured ClawRouter key. Conversational inventory responses are cached per endpoint and resolved credential; a change to either one means the earlier response is not reused. Prepared inventory and dynamic model lookup keep their own agent, workspace, and auth scopes. Every call's decisions consult the selected key's catalog.
- The ClawRouter key is attached only when a request is dispatched; model metadata never stores it.
- Before dispatch, automatic attribution and request-correlation values are trimmed and rejected if they contain control characters. Attribution values are capped at 256 characters; request ids are capped at 128.
- Model transport diagnostics carry metadata only and never include the ClawRouter key or model content.
- Native Anthropic and Gemini model ids are rewritten to their upstream ids only at dispatch.
- Catalog rows that are unsupported or ungranted are not advertised for chat. Static decision support never gives a key permission to execute.
Related
-
Model providers: How providers are configured and how models get selected.
-
Usage tracking: Where OpenClaw usage and status information appears.