OpenClaw custom model integration, done properly.

Updated 2026-07-16

OpenClaw takes any endpoint that speaks the OpenAI completions or Anthropic messages dialect: define a provider under models.providers with a baseUrl and key, list the model ids, and reference them as provider/model-id in your agent defaults. This guide walks the exact config shape from the current OpenClaw docs, with APIsRouter as the worked example.

Quick answer: one provider block, two model refs.

OpenClaw's configuration lives at ~/.openclaw/openclaw.json (JSON5, so comments and trailing commas are fine). Custom endpoints go under models.providers: each provider gets a baseUrl, an apiKey (use ${ENV_VAR} substitution rather than pasting the key), an api protocol type, and a models array declaring the ids you want addressable. You then reference those models anywhere OpenClaw takes a model as provider/model-id, most importantly agents.defaults.model.primary and its fallbacks list. The gateway watches the config file and hot-applies model and provider changes, so there is no restart dance: save the file, and openclaw models list should show the new entries. If startup validation fails instead, OpenClaw is strict about unknown keys, run openclaw doctor to pinpoint the offending line.

{
  models: {
    providers: {
      apisrouter: {
        baseUrl: "https://api.apisrouter.com/v1",
        apiKey: "${APISROUTER_API_KEY}",
        api: "openai-completions",
        models: [
          { id: "claude-sonnet-4-6", name: "Claude Sonnet 4.6",
            contextWindow: 200000, maxTokens: 8192 },
          { id: "deepseek-v4-flash", name: "DeepSeek V4 Flash",
            contextWindow: 128000, maxTokens: 8192 },
        ],
      },
    },
  },
  agents: {
    defaults: {
      model: {
        primary: "apisrouter/claude-sonnet-4-6",
        fallbacks: ["apisrouter/deepseek-v4-flash"],
      },
    },
  },
}

How OpenClaw talks to a custom provider.

OpenClaw is the self-hosted assistant runtime that connects one agent to WhatsApp, Telegram, Discord, and other channels through a local gateway process. Every reply, tool decision, and skill invocation in that loop is an LLM call, and the provider config decides where those calls go. The api field is the load-bearing choice. "openai-completions" sends standard chat-completions requests to baseUrl, which is the dialect APIsRouter and most gateways speak; "anthropic-messages" targets Anthropic's messages shape instead. One documented subtlety worth knowing: OpenClaw deliberately skips OpenAI-only request shaping on proxy-style routes, no service_tier, no Responses-API store field, no vendor attribution headers, so what reaches the gateway is clean, portable chat completions. Because the gateway serves many vendors' models behind one baseUrl, a single provider block makes the whole catalog addressable: Claude, GPT, DeepSeek, Kimi, and GLM ids all resolve through the same key, and mixing vendors between the primary and fallback slots becomes a config choice rather than a second integration.

The model entry fields, and which ones matter.

Two operational notes from the docs. Keys resolve from the environment via ${VAR} syntax, so the secret lives in your shell profile or service unit, not in the JSON. And endpoints on loopback or LAN addresses require an explicit opt-in (allowPrivateNetwork) as a safety default, which does not apply to a public gateway URL but explains a confusing error if you ever test against localhost.

  • id is the exact string sent upstream: it must match the gateway catalog byte for byte. Copy ids from the /v1/models listing, not from memory.
  • contextWindow and maxTokens shape OpenClaw's budgeting: they default to 200000 and 8192 when omitted. Set contextWindow to the real window of each model so session compaction triggers at the right size.
  • reasoning (default false) marks models that emit thinking output; set it true for reasoning-tier ids so the runtime handles their output shape correctly.
  • cost (input/output/cacheRead/cacheWrite, per token) feeds OpenClaw's own usage accounting; defaults are zero, so fill them in if you want /status-style cost readouts to mean anything. The authoritative spend number is still the gateway console.
  • input declares modalities (default ["text"]); add "image" for vision-capable ids if your channels forward images.

Per-agent and per-session model selection.

Model choice in OpenClaw has three layers. The primary/fallbacks pair under agents.defaults.model is the routing policy: primary serves the traffic, and the fallbacks list is what the runtime walks when the primary errors, which is your availability story during any one vendor's bad hour. The agents.defaults.models map is the catalog layer: entries there act as the allowlist for interactive model switching and can carry an alias, so "apisrouter/claude-sonnet-4-6" can surface as plain "Sonnet" in chat. From any connected channel, the /model command switches the session among allowlisted entries, which is how you A/B a new id on one conversation without touching the config. For multi-agent installs, agents are defined in agents.list with per-agent overrides of the defaults, and channel bindings decide which agent answers which account. The full override matrix is version-dependent, so treat openclaw models status as the ground truth for what each agent resolves to after your edits, and consult the current docs for the per-agent keys your build supports.

# what the runtime can address
openclaw models list --provider apisrouter

# what primary/fallback resolution looks like right now
openclaw models status

# set the default interactively instead of editing JSON
openclaw models set apisrouter/claude-sonnet-4-6

# config sanity check after hand edits
openclaw doctor

Pay-as-you-go · transparent per-model pricing

Selected models are priced below official list prices. Exact input, output, cache, and per-request prices are shown for each model.

ModelOfficial PriceOur Price
Claude Sonnet 4.6$3.00 / $15.00 per M$2.40 / $12.00 per M
Claude Opus 4.7$5.00 / $25.00 per M$4.00 / $20.00 per M
GPT-5.5$5.00 / $30.00 per M$4.00 / $24.00 per M
DeepSeek V4 Flash$0.14 / $0.28 per M$0.13 / $0.25 per M
Kimi K2.7 Code$0.95 / $4.00 per M$0.85 / $3.60 per M

A routing policy that fits how OpenClaw spends tokens.

An always-on assistant produces a very lopsided token distribution: a long tail of routine turns, acknowledgements, quick lookups, small tool calls, and a short head of genuinely hard requests. Paying flagship rates for the tail is the classic OpenClaw budget mistake. The catalog above maps onto that distribution directly. claude-sonnet-4-6 is a strong primary for a personal assistant: capable enough for real work, priced for daily traffic. deepseek-v4-flash is the volume slot, worth testing as primary for high-message installs or as the fallback that keeps service up. claude-opus-4-7 and gpt-5.5 are escalation models: allowlist them so /model can pull them into a session when a task deserves it, rather than making them the default. kimi-k2.7-code earns a slot when your OpenClaw does real coding work through its tools. Because every id bills through one key, the console's per-model breakdown shows exactly how your distribution landed, and rebalancing is an edit to two strings.

Failure modes specific to this integration.

The debugging order that saves the most time: prove the endpoint with curl first (models listing, then one chat completion with the exact id), and only then debug OpenClaw's side. That splits gateway problems from config problems in two commands.

  • Startup validation failure after editing: OpenClaw rejects unknown keys and malformed types outright. Run openclaw doctor and fix the reported path; do not guess.
  • Model not found from the gateway: the id in your models array does not match the catalog. Diff it against the /v1/models output with your key.
  • 401 upstream: the ${APISROUTER_API_KEY} substitution resolved empty. Env vars must be visible to the gateway process, a daemon does not read your interactive shell profile.
  • Doubled /v1 in request paths: baseUrl already includes /v1; if logs show /v1/v1, something appended a second one, so check the baseUrl string exactly.
  • Fallbacks never firing: fallback refs must also exist in the provider's models array; a ref to an undeclared id fails resolution rather than routing.
  • Silent model drift in long sessions: after config edits, hot reload applies to new sessions; confirm with openclaw models status rather than assuming the running session moved.

FAQ

How do I point OpenClaw at a custom OpenAI-compatible endpoint?

Add a provider under models.providers in ~/.openclaw/openclaw.json with baseUrl https://api.apisrouter.com/v1, apiKey via ${ENV_VAR}, api set to "openai-completions", and a models array with the exact ids. Then set agents.defaults.model.primary to provider/model-id. The gateway hot-reloads the change.

What does the api field in an OpenClaw provider do?

It selects the wire protocol: "openai-completions" for OpenAI-shape chat completions endpoints, "anthropic-messages" for Anthropic's messages shape. APIsRouter serves both surfaces, but "openai-completions" is the standard choice and gets clean, portable requests without OpenAI-only fields.

Can OpenClaw fall back to a second model automatically?

Yes. agents.defaults.model takes a primary plus a fallbacks array of provider/model refs, and the runtime walks the list on errors. Both refs can live behind the same gateway provider, so a Claude primary with a DeepSeek fallback needs one key and one provider block.

How do I switch models per conversation in OpenClaw?

Allowlist the ids in agents.defaults.models (optionally with aliases), then use the /model command in any connected channel to switch that session. openclaw models set changes the default from the CLI without hand-editing JSON.

Do I need one provider block per vendor?

Not through a gateway. Because APIsRouter serves Claude, GPT, DeepSeek, Kimi, and GLM ids on one baseUrl, a single provider block with one key makes all of them addressable as apisrouter/<id>, and cross-vendor primary/fallback pairs are just two refs.

Why does OpenClaw ignore my config change?

Three usual causes: validation failed and the reload was rejected (run openclaw doctor), the change requires a restart-class reload (gateway port and auth settings do; model settings do not), or you edited a different file than the gateway watches, check OPENCLAW_CONFIG_PATH.