Gateway

Configuration — tools and custom providers

tools.* config keys and custom provider / base-URL setup. For agents, channels, and other top-level config keys, see Configuration reference.

Tools

Tool profiles

tools.profile sets a base allowlist before tools.allow/tools.deny:

Profile Includes
minimal session_status only
coding group:fs, group:runtime, group:web, group:sessions, group:memory, cron, image, image_generate, video_generate
messaging group:messaging, sessions_list, sessions_history, sessions_send, session_status
full No restriction (same as unset)

Tool groups

Group Tools
group:runtime exec, process, code_execution (bash is accepted as an alias for exec)
group:fs read, write, edit, apply_patch
group:sessions sessions_list, sessions_history, sessions_send, sessions_spawn, sessions_yield, subagents, session_status
group:memory memory_search, memory_get
group:web web_search, x_search, web_fetch
group:ui browser, canvas
group:automation heartbeat_respond, cron, gateway
group:messaging message
group:nodes nodes
group:agents agents_list, update_plan
group:media image, image_generate, music_generate, video_generate, tts
group:openclaw All built-in tools (excludes provider plugins)
group:plugins Tools owned by loaded plugins, including configured MCP servers exposed through bundle-mcp

MCP and plugin tools inside sandbox tool policy

Configured MCP servers are exposed as plugin-owned tools under the bundle-mcp plugin id. Normal tool profiles can allow them, but tools.sandbox.tools is an additional gate for sandboxed sessions. If sandbox mode is "all" or "non-main", include one of these entries in the sandbox tool allowlist when MCP/plugin tools should be visible:

  • bundle-mcp for OpenClaw-managed MCP servers from mcp.servers
  • the plugin id for a specific native plugin
  • group:plugins for all loaded plugin-owned tools
  • exact MCP server tool names or server globs such as outlook__send_mail or outlook__* when you only want one server

Server globs use the provider-safe MCP server prefix, not necessarily the raw mcp.servers key. Non-[A-Za-z0-9_-] characters become -, names that do not start with a letter get an mcp- prefix, and long or duplicate prefixes may be truncated or suffixed; for example, mcp.servers["Outlook Graph"] uses a glob like outlook-graph__*.

json5
{  agents: { defaults: { sandbox: { mode: "all" } } },  mcp: {    servers: {      outlook: { command: "node", args: ["./outlook-mcp.js"] },    },  },  tools: {    sandbox: {      tools: {        alsoAllow: ["web_search", "web_fetch", "memory_search", "memory_get", "bundle-mcp"],      },    },  },}

Without that sandbox-layer entry, the MCP server can still load successfully while its tools are filtered before the provider request. Use openclaw doctor to catch this shape for OpenClaw-managed servers in mcp.servers. MCP servers loaded from bundled plugin manifests or Claude .mcp.json use the same sandbox gate, but this diagnostic does not enumerate those sources yet; use the same allowlist entries if their tools disappear in sandboxed turns.

tools.codeMode

tools.codeMode enables the generic OpenClaw code-mode surface. When enabled for a run with tools, the model sees only exec and wait; normal OpenClaw tools move behind the in-sandbox tools.* catalog bridge, and MCP tools are available through the generated MCP namespace.

json5
{  tools: {    codeMode: {      enabled: true,    },  },}

The shorthand is also accepted:

json5
{  tools: { codeMode: true },}

MCP declarations are exposed through the read-only virtual API file surface in code mode. Guest code can call API.list("mcp") and API.read("mcp/<server>.d.ts") to inspect TypeScript-style signatures before calling MCP.<server>.<tool>(). See Code mode for the runtime contract, limits, and debugging steps.

tools.allow / tools.deny

Global tool allow/deny policy (deny wins). Case-insensitive, supports * wildcards. Applied even when Docker sandbox is off.

json5
{  tools: { deny: ["browser", "canvas"] },}

write and apply_patch are separate tool ids. allow: ["write"] also enables apply_patch for compatible models, but deny: ["write"] does not deny apply_patch. To block all file mutation, deny group:fs or list each mutating tool explicitly:

json5
{  tools: { deny: ["write", "edit", "apply_patch"] },}

tools.byProvider

Further restrict tools for specific providers or models. Order: base profile → provider profile → allow/deny.

json5
{  tools: {    profile: "coding",    byProvider: {      "google-antigravity": { profile: "minimal" },      "openai/gpt-5.4": { allow: ["group:fs", "sessions_list"] },    },  },}

tools.toolsBySender

Restricts tools for a specific requester identity. This is defense-in-depth on top of channel access control; sender values must come from the channel adapter, not message text.

json5
{  tools: {    toolsBySender: {      "channel:discord:1234567890123": { alsoAllow: ["group:fs"] },      "id:guest-user-id": { deny: ["group:runtime", "group:fs"] },      "*": { deny: ["exec", "process", "write", "edit", "apply_patch"] },    },  },}

Keys use explicit prefixes: channel:<channelId>:<senderId>, id:<senderId>, e164:<phone>, username:<handle>, name:<displayName>, or "*". Channel ids are canonical OpenClaw ids; aliases such as teams normalize to msteams. Legacy unprefixed keys are accepted as id: only. Matching order is channel+id, id, e164, username, name, then wildcard.

Per-agent agents.list[].tools.toolsBySender overrides the global sender match when it matches, even with an empty {} policy.

tools.elevated

Controls elevated exec access outside the sandbox:

json5
{  tools: {    elevated: {      enabled: true,      allowFrom: {        whatsapp: ["+15555550123"],        discord: ["1234567890123", "987654321098765432"],      },    },  },}
  • Per-agent override (agents.list[].tools.elevated) can only further restrict.
  • /elevated on|off|ask|full stores state per session; inline directives apply to single message.
  • Elevated exec bypasses sandboxing and uses the configured escape path (gateway by default, or node when the exec target is node).

tools.exec

json5
{  tools: {    exec: {      backgroundMs: 10000,      timeoutSec: 1800,      cleanupMs: 1800000,      notifyOnExit: true,      notifyOnExitEmptySuccess: false,      commandHighlighting: false,      applyPatch: {        enabled: false,        allowModels: ["gpt-5.5"],      },    },  },}

tools.loopDetection

Tool-loop safety checks are disabled by default. Set enabled: true to activate detection. Settings can be defined globally in tools.loopDetection and overridden per-agent at agents.list[].tools.loopDetection.

json5
{  tools: {    loopDetection: {      enabled: true,      historySize: 30,      warningThreshold: 10,      criticalThreshold: 20,      globalCircuitBreakerThreshold: 30,      detectors: {        genericRepeat: true,        knownPollNoProgress: true,        pingPong: true,      },    },  },}
historySizenumber

Max tool-call history retained for loop analysis.

warningThresholdnumber

Repeating no-progress pattern threshold for warnings.

criticalThresholdnumber

Higher repeating threshold for blocking critical loops.

globalCircuitBreakerThresholdnumber

Hard stop threshold for any no-progress run.

detectors.genericRepeatboolean

Warn on repeated same-tool/same-args calls.

detectors.knownPollNoProgressboolean

Warn/block on known poll tools (process.poll, command_status, etc.).

detectors.pingPongboolean

Warn/block on alternating no-progress pair patterns.

tools.web

json5
{  tools: {    web: {      search: {        enabled: true,        apiKey: "brave_api_key", // or BRAVE_API_KEY env        maxResults: 5,        timeoutSeconds: 30,        cacheTtlMinutes: 15,      },      fetch: {        enabled: true,        provider: "firecrawl", // optional; omit for auto-detect        maxChars: 50000,        maxCharsCap: 50000,        maxResponseBytes: 2000000,        timeoutSeconds: 30,        cacheTtlMinutes: 15,        maxRedirects: 3,        readability: true,        userAgent: "custom-ua",      },    },  },}

tools.media

Configures inbound media understanding (image/audio/video):

json5
{  tools: {    media: {      concurrency: 2,      asyncCompletion: {        directSend: false, // deprecated: completions stay agent-mediated      },      audio: {        enabled: true,        maxBytes: 20971520,        scope: {          default: "deny",          rules: [{ action: "allow", match: { chatType: "direct" } }],        },        models: [          { provider: "openai", model: "gpt-4o-mini-transcribe" },          { type: "cli", command: "whisper", args: ["--model", "base", "{{MediaPath}}"] },        ],      },      image: {        enabled: true,        timeoutSeconds: 180,        models: [{ provider: "ollama", model: "gemma4:26b", timeoutSeconds: 300 }],      },      video: {        enabled: true,        maxBytes: 52428800,        models: [{ provider: "google", model: "gemini-3-flash-preview" }],      },    },  },}
Media model entry fields

Provider entry (type: "provider" or omitted):

  • provider: API provider id (openai, anthropic, google/gemini, groq, etc.)
  • model: model id override
  • profile / preferredProfile: auth-profiles.json profile selection

CLI entry (type: "cli"):

  • command: executable to run
  • args: templated args (supports {{MediaPath}}, {{Prompt}}, {{MaxChars}}, etc.; openclaw doctor --fix migrates deprecated {input} placeholders to {{MediaPath}})

Common fields:

  • capabilities: optional list (image, audio, video). Defaults: openai/anthropic/minimax → image, google → image+audio+video, groq → audio.
  • prompt, maxChars, maxBytes, timeoutSeconds, language: per-entry overrides.
  • tools.media.image.timeoutSeconds and matching image model timeoutSeconds entries also apply when the agent calls the explicit image tool.
  • Failures fall back to the next entry.

Provider auth follows standard order: auth-profiles.json → env vars → models.providers.*.apiKey.

Async completion fields:

  • asyncCompletion.directSend: deprecated compatibility flag. Completed async media tasks stay requester-session mediated so the agent receives the result, decides how to tell the user, and uses the message tool when source delivery requires it.

tools.agentToAgent

json5
{  tools: {    agentToAgent: {      enabled: false,      allow: ["home", "work"],    },  },}

tools.sessions

Controls which sessions can be targeted by the session tools (sessions_list, sessions_history, sessions_send).

Default: tree (current session + sessions spawned by it, such as subagents).

json5
{  tools: {    sessions: {      // "self" | "tree" | "agent" | "all"      visibility: "tree",    },  },}
Visibility scopes
  • self: only the current session key.
  • tree: current session + sessions spawned by the current session (subagents).
  • agent: any session belonging to the current agent id (can include other users if you run per-sender sessions under the same agent id).
  • all: any session. Cross-agent targeting still requires tools.agentToAgent.
  • Sandbox clamp: when the current session is sandboxed and agents.defaults.sandbox.sessionToolsVisibility="spawned", visibility is forced to tree even if tools.sessions.visibility="all".
  • When not all, sessions_list includes a compact visibility field describing the effective mode and a warning that some sessions may be omitted outside the current scope.

tools.sessions_spawn

Controls inline attachment support for sessions_spawn.

json5
{  tools: {    sessions_spawn: {      attachments: {        enabled: false, // opt-in: set true to allow inline file attachments        maxTotalBytes: 5242880, // 5 MB total across all files        maxFiles: 50,        maxFileBytes: 1048576, // 1 MB per file        retainOnSessionKeep: false, // keep attachments when cleanup="keep"      },    },  },}
Attachment notes
  • Attachments require enabled: true.
  • Subagent attachments are materialized into the child workspace at .openclaw/attachments/<uuid>/ with a .manifest.json.
  • ACP attachments are image-only and forwarded inline to the ACP runtime after the same file count, per-file byte, and total byte limits pass.
  • Attachment content is automatically redacted from transcript persistence.
  • Base64 inputs are validated with strict alphabet/padding checks and a pre-decode size guard.
  • Subagent attachment file permissions are 0700 for directories and 0600 for files.
  • Subagent cleanup follows the cleanup policy: delete always removes attachments; keep retains them only when retainOnSessionKeep: true.

tools.experimental

Experimental built-in tool flags. Default off unless a strict-agentic GPT-5 auto-enable rule applies.

json5
{  tools: {    experimental: {      planTool: true, // enable experimental update_plan    },  },}
  • planTool: enables the structured update_plan tool for non-trivial multi-step work tracking.
  • Default: false unless agents.defaults.embeddedAgent.executionContract (or a per-agent override) is set to "strict-agentic" for an OpenAI or OpenAI Codex GPT-5-family run. Set true to force the tool on outside that scope, or false to keep it off even for strict-agentic GPT-5 runs.
  • When enabled, the system prompt also adds usage guidance so the model only uses it for substantial work and keeps at most one step in_progress.

agents.defaults.subagents

json5
{  agents: {    defaults: {      subagents: {        allowAgents: ["research"],        model: "minimax/MiniMax-M2.7",        maxConcurrent: 8,        runTimeoutSeconds: 900,        announceTimeoutMs: 120000,        archiveAfterMinutes: 60,      },    },  },}
  • model: default model for spawned sub-agents. If omitted, sub-agents inherit the caller's model.
  • allowAgents: default allowlist of configured target agent ids for sessions_spawn when the requester agent does not set its own subagents.allowAgents (["*"] = any configured target; default: same agent only). Stale entries whose agent config was deleted are rejected by sessions_spawn and omitted from agents_list; run openclaw doctor --fix to clean them up.
  • runTimeoutSeconds: default timeout (seconds) for sessions_spawn. 0 means no timeout.
  • announceTimeoutMs: per-call timeout (milliseconds) for gateway agent announce delivery attempts. Default: 120000. Transient retries can make the total announce wait longer than one configured timeout.
  • Per-subagent tool policy: tools.subagents.tools.allow / tools.subagents.tools.deny.

Custom providers and base URLs

Provider plugins publish their own model catalog rows. Add custom providers via models.providers in config or ~/.openclaw/agents/<agentId>/agent/models.json.

Configuring a custom/local provider baseUrl is also the narrow network trust decision for model HTTP requests: OpenClaw allows that exact scheme://host:port origin through the guarded fetch path, without adding a separate config option or trusting other private origins.

json5
{  models: {    mode: "merge", // merge (default) | replace    providers: {      "custom-proxy": {        baseUrl: "http://localhost:4000/v1",        apiKey: "LITELLM_KEY",        api: "openai-completions", // openai-completions | openai-responses | anthropic-messages | google-generative-ai        models: [          {            id: "llama-3.1-8b",            name: "Llama 3.1 8B",            reasoning: false,            input: ["text"],            cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },            contextWindow: 128000,            contextTokens: 96000,            maxTokens: 32000,          },        ],      },    },  },}
Auth and merge precedence
  • Use authHeader: true + headers for custom auth needs.
  • Override agent config root with OPENCLAW_AGENT_DIR.
  • Merge precedence for matching provider IDs:
    • Non-empty agent models.json baseUrl values win.
    • Non-empty agent apiKey values win only when that provider is not SecretRef-managed in current config/auth-profile context.
    • SecretRef-managed provider apiKey values are refreshed from source markers (ENV_VAR_NAME for env refs, secretref-managed for file/exec refs) instead of persisting resolved secrets.
    • SecretRef-managed provider header values are refreshed from source markers (secretref-env:ENV_VAR_NAME for env refs, secretref-managed for file/exec refs).
    • Empty or missing agent apiKey/baseUrl fall back to models.providers in config.
    • Matching model contextWindow/maxTokens use the higher value between explicit config and implicit catalog values.
    • Matching model contextTokens preserves an explicit runtime cap when present; use it to limit effective context without changing native model metadata.
    • Provider-plugin catalogs are stored as generated plugin-owned catalog shards under the agent's plugin state.
    • Use models.mode: "replace" when you want config to fully rewrite models.json and active plugin catalog shards.
    • Marker persistence is source-authoritative: markers are written from the active source config snapshot (pre-resolution), not from resolved runtime secret values.

Provider field details

Top-level catalog
  • models.mode: provider catalog behavior (merge or replace).
  • models.providers: custom provider map keyed by provider id.
    • Safe edits: use openclaw config set models.providers.<id> '<json>' --strict-json --merge or openclaw config set models.providers.<id>.models '<json-array>' --strict-json --merge for additive updates. config set refuses destructive replacements unless you pass --replace.
Provider connection and auth
  • models.providers.*.api: request adapter (openai-completions, openai-responses, anthropic-messages, google-generative-ai, etc). For self-hosted /v1/chat/completions backends such as MLX, vLLM, SGLang, and most OpenAI-compatible local servers, use openai-completions. A custom provider with baseUrl but no api defaults to openai-completions; set openai-responses only when the backend supports /v1/responses.
  • models.providers.*.apiKey: provider credential (prefer SecretRef/env substitution).
  • models.providers.*.auth: auth strategy (api-key, token, oauth, aws-sdk).
  • models.providers.*.contextWindow: default native context window for models under this provider when the model entry does not set contextWindow.
  • models.providers.*.contextTokens: default effective runtime context cap for models under this provider when the model entry does not set contextTokens.
  • models.providers.*.maxTokens: default output-token cap for models under this provider when the model entry does not set maxTokens.
  • models.providers.*.timeoutSeconds: optional per-provider model HTTP request timeout in seconds, including connect, headers, body, and total request abort handling.
  • models.providers.*.injectNumCtxForOpenAICompat: for Ollama + openai-completions, inject options.num_ctx into requests (default: true).
  • models.providers.*.authHeader: force credential transport in the Authorization header when required.
  • models.providers.*.baseUrl: upstream API base URL.
  • models.providers.*.headers: extra static headers for proxy/tenant routing.
Request transport overrides

models.providers.*.request: transport overrides for model-provider HTTP requests.

  • request.headers: extra headers (merged with provider defaults). Values accept SecretRef.
  • request.auth: auth strategy override. Modes: "provider-default" (use provider's built-in auth), "authorization-bearer" (with token), "header" (with headerName, value, optional prefix).
  • request.proxy: HTTP proxy override. Modes: "env-proxy" (use HTTP_PROXY/HTTPS_PROXY env vars), "explicit-proxy" (with url). Both modes accept an optional tls sub-object.
  • request.tls: TLS override for direct connections. Fields: ca, cert, key, passphrase (all accept SecretRef), serverName, insecureSkipVerify.
  • request.allowPrivateNetwork: when true, allow model-provider HTTP requests to private, CGNAT, or similar ranges through the provider HTTP fetch guard. Custom/local provider base URLs already trust the exact configured origin, except metadata/link-local origins, which remain blocked without explicit opt-in. Set this to false to opt out of exact-origin trust. WebSocket uses the same request for headers/TLS but not that fetch SSRF gate. Default false.
Model catalog entries
  • models.providers.*.models: explicit provider model catalog entries.
  • models.providers.*.models.*.input: model input modalities. Use ["text"] for text-only models and ["text", "image"] for native image/vision models. Image attachments are only injected into agent turns when the selected model is marked image-capable.
  • models.providers.*.models.*.contextWindow: native model context window metadata. This overrides provider-level contextWindow for that model.
  • models.providers.*.models.*.contextTokens: optional runtime context cap. This overrides provider-level contextTokens; use it when you want a smaller effective context budget than the model's native contextWindow; openclaw models list shows both values when they differ.
  • models.providers.*.models.*.compat.supportsDeveloperRole: optional compatibility hint. For api: "openai-completions" with a non-empty non-native baseUrl (host not api.openai.com), OpenClaw forces this to false at runtime. Empty/omitted baseUrl keeps default OpenAI behavior.
  • models.providers.*.models.*.compat.requiresStringContent: optional compatibility hint for string-only OpenAI-compatible chat endpoints. When true, OpenClaw flattens pure text messages[].content arrays into plain strings before sending the request.
  • models.providers.*.models.*.compat.strictMessageKeys: optional compatibility hint for strict OpenAI-compatible chat endpoints. When true, OpenClaw strips outgoing Chat Completions message objects to role and content before sending the request.
  • models.providers.*.models.*.compat.thinkingFormat: optional thinking payload hint. Use "together" for Together-style reasoning.enabled, "qwen" for top-level enable_thinking, or "qwen-chat-template" for chat_template_kwargs.enable_thinking on Qwen-family OpenAI-compatible servers that support request-level chat-template kwargs, such as vLLM. Configured vLLM Qwen models expose binary /think choices (off, on) for these formats.
  • models.providers.*.models.*.compat.requiresReasoningContentOnAssistantMessages: optional compatibility hint for DeepSeek-style Chat Completions backends that require prior assistant messages to keep reasoning_content on replay. When true, OpenClaw preserves that field on outgoing assistant messages. Use this when wiring a custom DeepSeek-compatible proxy that rejects requests after stripped reasoning. Default false.
Amazon Bedrock discovery
  • plugins.entries.amazon-bedrock.config.discovery: Bedrock auto-discovery settings root.
  • plugins.entries.amazon-bedrock.config.discovery.enabled: turn implicit discovery on/off.
  • plugins.entries.amazon-bedrock.config.discovery.region: AWS region for discovery.
  • plugins.entries.amazon-bedrock.config.discovery.providerFilter: optional provider-id filter for targeted discovery.
  • plugins.entries.amazon-bedrock.config.discovery.refreshInterval: polling interval for discovery refresh.
  • plugins.entries.amazon-bedrock.config.discovery.defaultContextWindow: fallback context window for discovered models.
  • plugins.entries.amazon-bedrock.config.discovery.defaultMaxTokens: fallback max output tokens for discovered models.

Interactive custom-provider onboarding infers image input for common vision model IDs such as GPT-4o, Claude, Gemini, Qwen-VL, LLaVA, Pixtral, InternVL, Mllama, MiniCPM-V, and GLM-4V, and skips the extra question for known text-only families. Unknown model IDs still prompt for image support. Non-interactive onboarding uses the same inference; pass --custom-image-input to force image-capable metadata or --custom-text-input to force text-only metadata.

Provider examples

Cerebras (GLM 4.7 / GPT OSS)

The bundled cerebras provider plugin can configure this via openclaw onboard --auth-choice cerebras-api-key. Use explicit provider config only when overriding defaults.

json5
{  env: { CEREBRAS_API_KEY: "sk-..." },  agents: {    defaults: {      model: {        primary: "cerebras/zai-glm-4.7",        fallbacks: ["cerebras/gpt-oss-120b"],      },      models: {        "cerebras/zai-glm-4.7": { alias: "GLM 4.7 (Cerebras)" },        "cerebras/gpt-oss-120b": { alias: "GPT OSS 120B (Cerebras)" },      },    },  },  models: {    mode: "merge",    providers: {      cerebras: {        baseUrl: "https://api.cerebras.ai/v1",        apiKey: "${CEREBRAS_API_KEY}",        api: "openai-completions",        models: [          { id: "zai-glm-4.7", name: "GLM 4.7 (Cerebras)" },          { id: "gpt-oss-120b", name: "GPT OSS 120B (Cerebras)" },        ],      },    },  },}

Use cerebras/zai-glm-4.7 for Cerebras; zai/glm-4.7 for Z.AI direct.

Kimi Coding
json5
{  env: { KIMI_API_KEY: "sk-..." },  agents: {    defaults: {      model: { primary: "kimi/kimi-for-coding" },      models: { "kimi/kimi-for-coding": { alias: "Kimi Code" } },    },  },}

Anthropic-compatible, built-in provider. Shortcut: openclaw onboard --auth-choice kimi-code-api-key.

Local models (LM Studio)

See Local Models. TL;DR: run a large local model via LM Studio Responses API on serious hardware; keep hosted models merged for fallback.

MiniMax M3 (direct)
json5
{  agents: {    defaults: {      model: { primary: "minimax/MiniMax-M3" },      models: {        "minimax/MiniMax-M3": { alias: "Minimax" },      },    },  },  models: {    mode: "merge",    providers: {      minimax: {        baseUrl: "https://api.minimax.io/anthropic",        apiKey: "${MINIMAX_API_KEY}",        api: "anthropic-messages",        models: [          {            id: "MiniMax-M3",            name: "MiniMax M3",            reasoning: true,            input: ["text", "image"],            cost: { input: 0.6, output: 2.4, cacheRead: 0.12, cacheWrite: 0 },            contextWindow: 1000000,            maxTokens: 131072,          },        ],      },    },  },}

Set MINIMAX_API_KEY. Shortcuts: openclaw onboard --auth-choice minimax-global-api or openclaw onboard --auth-choice minimax-cn-api. The model catalog defaults to M3 and also includes the M2.7 variants. On the Anthropic-compatible streaming path, OpenClaw disables MiniMax M2.x thinking by default unless you explicitly set thinking yourself; MiniMax-M3 (and M3.x) stays on the provider's omitted/adaptive thinking path by default. /fast on or params.fastMode: true rewrites MiniMax-M2.7 to MiniMax-M2.7-highspeed.

Moonshot AI (Kimi)
json5
{  env: { MOONSHOT_API_KEY: "sk-..." },  agents: {    defaults: {      model: { primary: "moonshot/kimi-k2.6" },      models: { "moonshot/kimi-k2.6": { alias: "Kimi K2.6" } },    },  },  models: {    mode: "merge",    providers: {      moonshot: {        baseUrl: "https://api.moonshot.ai/v1",        apiKey: "${MOONSHOT_API_KEY}",        api: "openai-completions",        models: [          {            id: "kimi-k2.6",            name: "Kimi K2.6",            reasoning: false,            input: ["text", "image"],            cost: { input: 0.95, output: 4, cacheRead: 0.16, cacheWrite: 0 },            contextWindow: 262144,            maxTokens: 262144,          },        ],      },    },  },}

For the China endpoint: baseUrl: "https://api.moonshot.cn/v1" or openclaw onboard --auth-choice moonshot-api-key-cn.

Native Moonshot endpoints advertise streaming usage compatibility on the shared openai-completions transport, and OpenClaw keys that off endpoint capabilities rather than the built-in provider id alone.

OpenCode
json5
{  agents: {    defaults: {      model: { primary: "opencode/claude-opus-4-6" },      models: { "opencode/claude-opus-4-6": { alias: "Opus" } },    },  },}

Set OPENCODE_API_KEY (or OPENCODE_ZEN_API_KEY). Use opencode/... refs for the Zen catalog or opencode-go/... refs for the Go catalog. Shortcut: openclaw onboard --auth-choice opencode-zen or openclaw onboard --auth-choice opencode-go.

Synthetic (Anthropic-compatible)
json5
{  env: { SYNTHETIC_API_KEY: "sk-..." },  agents: {    defaults: {      model: { primary: "synthetic/hf:MiniMaxAI/MiniMax-M2.5" },      models: { "synthetic/hf:MiniMaxAI/MiniMax-M2.5": { alias: "MiniMax M2.5" } },    },  },  models: {    mode: "merge",    providers: {      synthetic: {        baseUrl: "https://api.synthetic.new/anthropic",        apiKey: "${SYNTHETIC_API_KEY}",        api: "anthropic-messages",        models: [          {            id: "hf:MiniMaxAI/MiniMax-M2.5",            name: "MiniMax M2.5",            reasoning: true,            input: ["text"],            cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },            contextWindow: 192000,            maxTokens: 65536,          },        ],      },    },  },}

Base URL should omit /v1 (Anthropic client appends it). Shortcut: openclaw onboard --auth-choice synthetic-api-key.

Z.AI (GLM-4.7)
json5
{  agents: {    defaults: {      model: { primary: "zai/glm-4.7" },      models: { "zai/glm-4.7": {} },    },  },}

Set ZAI_API_KEY. Model refs use the canonical zai/* provider ID. Shortcut: openclaw onboard --auth-choice zai-api-key.

  • General endpoint: https://api.z.ai/api/paas/v4
  • Coding endpoint (default): https://api.z.ai/api/coding/paas/v4
  • For the general endpoint, define a custom provider with the base URL override.

Was this useful?
On this page

On this page