# Provider Catalog Every model-provider family ZeroClaw ships with. For each: config shape, notes on auth and endpoint behavior, and the slot key to use under `[providers.models..]`. See [Configuration](./configuration.md) for universal fields (`api_key`, `uri`, `model`, ...) and resolution order. > Examples below use `home` as the alias to underline that the alias half is operator-chosen, pick whatever name fits (`work`, `personal`, `cn`, `prod`, ...). Reference it from an agent via `model_provider = "."`. --- ## Native ### Anthropic / Claude: slot `anthropic` Supports Console API keys and tokens generated by `claude setup-token` for Claude Max. Both credential forms live on the canonical `anthropic` slot's `api_key` field; Quickstart exposes them as `api_key` and `setup_token` choices. Streaming, tool calls, vision, and reasoning all supported. Custom endpoints (Anthropic-compatible proxies, e.g. Z.AI's Anthropic API) go on this slot too: set `uri` to override. ### OpenAI: slot `openai` GPT-4o, GPT-5, o-series reasoning models. When reasoning is streamed, it is carried in the optional `reasoning` field of a `StreamChunk` wrapped by `TextDelta`; see [Streaming](./streaming.md). ### OpenAI Codex: `openai` slot with `requires_openai_auth = true` OpenAI Codex subscription auth lives on the `openai` slot. Set `wire_api = "responses"` to route through `POST /v1/responses` and `requires_openai_auth = true` to use the Codex subscription login (from the Codex CLI's own `~/.codex/auth.json`) instead of an `api_key` field on the entry. The subscription path does not read `OPENAI_API_KEY`; that variable applies only to the metered `openai` API-key mode. See [Provider Configuration → OAuth and subscription auth](./configuration.md#oauth-and-subscription-auth) for the credential model. ### Ollama: slot `ollama` Local inference via Ollama's native `/api/chat`. Schema-based structured output via `format`. No API key. ### Bedrock: slot `bedrock` ### Gemini: slot `gemini` Google's Gemini API. Supports vision and pre-executed grounded search (see [Streaming](./streaming.md) for `PreExecutedToolCall` events). ### Gemini CLI: slot `gemini_cli` Shells out to the `gemini` CLI; uses the CLI's existing auth. ### Grok Build CLI: slot `grok_cli` Shells out to the Grok Build CLI through the documented **`grok agent stdio`** ACP surface and uses the CLI's login cache by default. Run `grok login`, or use the explicit API-key bridge shown below. The typed alias `api_key` is not used, and ambient `XAI_API_KEY` is not inherited unless the alias opts in, so the Grok CLI remains the authentication owner. This is the only transport: initialize → authenticate → session/new → session/prompt over newline-delimited JSON-RPC. Small and large prompts both travel on stdin and never appear in argv or a prompt file. The documented ACP integration and default argument profile are validated against Grok Build CLI `0.2.118` (ACP advertise/live probes) with earlier baseline `0.2.111`. Treat upgrades of the external CLI as a compatibility change and revalidate `grok agent stdio` before deploying them. #### ACP vision / image input (current Grok Build behavior) Grok Build CLI (checked through `0.2.118`) still advertises `promptCapabilities.image = false` on ACP `initialize`. That is not an env-var override on either side: ZeroClaw never rewrites Grok's advertisement. The only ZeroClaw control is the shared per-alias config field `vision`. | Layer | Behavior on `0.2.118` | | ----- | --------------------- | | ACP advertise | `promptCapabilities.image = false` | | Default `grok_cli` | `vision` unset → ZeroClaw treats the alias as non-vision; image markers stay text | | `vision = true` | ZeroClaw reports vision on the alias and **sends** ACP `{type: image, data, mimeType}` blocks (does not change Grok's advertise) | | Model recognition | Live probe: image blocks are accepted by `session/prompt` (no protocol error) but the agent answered as if **no image was received** | ```toml [providers.models.grok_cli.default] model = "grok-4.5" working_directory = "/srv/zeroclaw/grok-workspace" # Optional experiment only: send ACP image blocks despite image=false advertise. # Does not make Grok Build 0.2.118 reliably see or describe the image. # vision = true ``` Leave `vision` unset for production `grok_cli` aliases. Do not route channel attachments that require real image understanding to `grok_cli` until a deployed CLI both advertises `image = true` and a live smoke shows the model using the image content. When that holds, drop any temporary `vision = true` opt-in and revisit whether ZeroClaw should follow the advertise bit instead of a local override (`GrokCliModelProvider::acp_prompt_content`). #### Ubuntu 24.04: keep the Grok sandbox when `bwrap` needs user namespaces When deploying Grok Build `0.2.112` or later, verify ACP initialization on the target host. On Ubuntu 24.04 hosts with `kernel.apparmor_restrict_unprivileged_userns=1`, Grok can exit before ACP initialization with `bwrap: setting up uid map: Permission denied`. This is a host sandbox setup failure, not an ACP, stdout, or authentication failure. Keep the ZeroClaw default `--sandbox strict` (or an explicit `workspace` profile) and grant only the actual Grok executable permission to create a user namespace. This is a host-administrator change; it preserves the global user namespace restriction and does not turn off Grok's sandbox. ```sh readlink -f "$(command -v grok)" ``` Create `/etc/apparmor.d/grok-build-userns`, replacing the placeholder with that absolute path: ```text abi , include profile grok-build-userns /absolute/path/to/grok flags=(unconfined) { userns, } ``` Then load it and verify the profile is active: ```sh sudo apparmor_parser -r /etc/apparmor.d/grok-build-userns sudo aa-status | grep grok-build-userns ``` `flags=(unconfined)` is Ubuntu's per-executable AppArmor exception mechanism: it grants `userns` to the named Grok binary but does not add AppArmor file rules to it. Grok's own requested sandbox remains enabled, and the host-wide user-namespace restriction remains enabled. Use a fully confined organization-specific profile if Grok also needs AppArmor file restrictions. Because self-updates can change the downloaded executable path, resolve the path and reload this profile after each Grok update. Do not use `--sandbox off` merely to avoid this error: it disables Grok's sandbox. Do not disable `kernel.apparmor_restrict_unprivileged_userns` system-wide. [xAI documents Landlock for normal Linux sandboxing](https://docs.x.ai/build/features/sandbox) and documents [`bubblewrap` only for custom read-deny profiles](https://docs.x.ai/build/settings/reference); if this occurs without a custom non-empty `deny` list, report the version, exact error, sandbox profile, and non-secret host/AppArmor diagnostics to xAI. `max_acp_stdout_bytes` bounds all stdout read from the Grok ACP child during one request, including protocol frames and native-tool updates. It defaults to 4 MiB; set it per alias when a reviewed tool-enabled workload needs a larger bounded budget. ```toml [providers.models.grok_cli.default] model = "grok-4.5" working_directory = "/srv/zeroclaw/grok-workspace" env_passthrough = ["XAI_API_KEY"] # Optional: 4 MiB by default; accepted range is 1-64 MiB. max_acp_stdout_bytes = 8388608 ``` Export `XAI_API_KEY` into the daemon environment before starting ZeroClaw. The ACP client selects `xai.api_key` only when that name is listed in `env_passthrough` and a non-empty value is present in the process environment at **child spawn** (not snapshotted into the long-lived provider handle). Otherwise it falls back to the CLI login cache. Typed alias `api_key` remains rejected: this is an intentional process-env bridge rather than a second Config secret field. Values are not written to provider TOML; a future typed Config bridge may load the same name at config time without changing the operator surface. An existing absolute `working_directory` is required. It is canonicalized and used for both the child cwd and ACP session boundary, so the provider never falls back to the daemon cwd. Optional `binary_path` selects a non-`PATH` binary. Alias `timeout_secs` bounds protocol reads and writes (default 600s). The child environment is cleared before spawn. Process-runtime, locale, proxy, and CA variables on the built-in allowlist remain available; all other names are blocked unless that provider alias lists them in `env_passthrough`. This field is for the explicit `XAI_API_KEY` authentication bridge and environment variables required by explicitly enabled Grok tools, such as cloud CLI credentials. Values are read from the ZeroClaw process environment at spawn time and are not stored in provider config. The default list is empty. Keep it narrow because every listed secret is exposed to Grok and any tools enabled for that alias. Other provider-owned `XAI_*` names and all `GROK_*` names are rejected. Grok's discovered user and project configuration, together with alias `extra_args`, owns Grok tool policy. The default argv adds `--no-auto-update`, `--no-plan`, `--sandbox strict`, `--permission-mode dontAsk`, and `--tools ""`. By default, the ACP client fails permission requests closed. When the request supplies a `reject_once` option, the client selects it instead of cancelling the complete agent turn; otherwise it cancels the request. The requested tool still fails closed, while Grok can consume the rejection and produce a final answer or retry with an operation its policy allows. An alias explicitly configured with `--always-approve`, `--dangerously-skip-permissions`, `--yolo`, or `--permission-mode=bypassPermissions` changes the headless ACP response policy: the client selects the request's `allow_once` option. It never substitutes `allow_always`, and cancels when the requested `allow_once` option is absent. This approval applies only to the current permission request; Grok's permission rules and active OS sandbox can still reject or confine the operation. ```toml [providers.models.grok_cli.ops] working_directory = "/path/to/agents/ops/workspace" extra_args = [ "--tools=run_terminal_cmd", "--permission-mode=bypassPermissions", ] ``` Treat these bypass flags as authorization for Grok to execute every request-supported tool on that alias without a human approval round trip. Other permission modes, including `acceptEdits`, do not enable ACP auto-approval. Grok evaluates CLI `--allow` / `--deny` rules and discovered user/project permission configuration before asking the ACP client. Those surfaces are trusted operator policy: a matching allow rule may pre-authorize a tool so the ACP client never sees a permission request, and project MCP servers, plugins, or hooks may add capabilities. Use a dedicated, reviewed `working_directory` for channel agents. When an allow rule does **not** pre-authorize the tool, Grok still sends `session/request_permission` and ZeroClaw's default reject-once policy fails the tool closed. In practice this matters for shell/`execute` tools under the default `--sandbox strict`: a CLI `--allow=Bash(...)` rule can still escalate to the ACP host on current Grok Build, so a tool-enabled shell alias should either set an explicit bypass flag (`--always-approve` / `--permission-mode=bypassPermissions`) or pair allow rules with a sandbox profile that Grok will pre-authorize without host approval (for example `--sandbox=workspace`). Read-only tool grants such as `--tools=Read,Grep` with matching `--allow` remain the narrower opt-in. Operators can also grant tools or relax sandbox/permission policy with alias `extra_args`; both surfaces are explicit opt-ins to a wider subprocess boundary. Transport, prompt, model, session, cwd, and update flags remain provider-owned and are rejected in `extra_args`. Positional and short arguments are also rejected. Known value-taking options accept either `["--flag", "value"]` or `--flag=value`; unknown option shapes require the inline form so they cannot consume the trailing ACP command. Grok may emit progress as an `agent_message_chunk` before a plan, tool call, or permission request. The provider discards the preceding message segment at those ACP boundaries and returns only the latest answer segment, so planning or tool-gathering narration is not delivered as the channel reply. Explicit `--no-plan` also keeps the default one-shot channel alias out of Grok's plan mode; tool/MCP configuration remains an operator-controlled capability. ACP stdout frames, aggregate stdout, assistant text, and stderr processing are bounded while the child is running. Stderr is drained but its content is never stored, logged, or returned. Public provider errors stay stable and do not echo child-controlled protocol free-text. After every one-shot request (success, timeout, cancellation, or protocol error), ZeroClaw terminates the child **process group** on Unix or the **Job Object** on Windows and reaps the direct child. That covers ordinary descendants; a process that creates a new session or process group can escape group kill on Unix. Windows Job Object coverage is compile-covered in CI and not fully executed on every Linux developer host. #### Recommended pattern: default channel chatbot Use a **dedicated provider alias** for the messaging agent (for example `agents.default`). The default alias grants no Grok built-in tools. Grok still loads its normal user and project configuration, so use a dedicated workspace whose permission rules, MCP servers, plugins, and hooks have been reviewed for the channel trust boundary. Use a separate alias and workspace for an operator-approved coding/ops agent. **Reply-intent precheck (classifier):** ZeroClaw runs a short REPLY / `NO_REPLY[*]` classification before the full agent loop. Prefer a **stable chat-completions API** for that precheck (for example the HTTP/OAuth `xai` slot, or any other non-CLI model alias), and keep **`grok_cli` only for `model_provider`** (the full answer). CLI agent backends often emit planning prose instead of a single sentinel token; that prose can be delivered as the channel message (“staying silent” / “no Slack reply”). Empty `classifier_provider` reuses `model_provider`: fine for API models, not for CLI channel bots. ACP channels skip the classifier entirely. ```toml # Full answers: ACP, strict sandbox, no built-in tools, reviewed Grok config [providers.models.grok_cli.default] model = "grok-4.5" binary_path = "/home/you/.grok/bin/grok" working_directory = "/path/to/agents/default/workspace" # REPLY / NO_REPLY precheck - API (format-stable). Reuse an existing xAI # HTTP alias if you already have one; do not point this at grok_cli. [providers.models.xai.default] model = "grok-4.5" # uri / auth as for the normal xAI provider (OAuth session or api_key) # Ops / coding agents: explicit policy and tool opt-in [providers.models.grok_cli.ops] model = "grok-4.5" binary_path = "/home/you/.grok/bin/grok" working_directory = "/path/to/agents/ops/workspace" env_passthrough = ["AWS_ACCESS_KEY_ID", "AWS_SECRET_ACCESS_KEY"] # Read-only tools: matching --allow can pre-authorize without ACP approval. extra_args = ["--tools=Read,Grep", "--allow=Read", "--allow=Grep"] # Shell-capable ops alias: either bypass ACP approval, or pair allow with a # sandbox profile that Grok pre-authorizes (workspace is the common choice). [providers.models.grok_cli.ops_shell] model = "grok-4.5" binary_path = "/home/you/.grok/bin/grok" working_directory = "/path/to/agents/ops/workspace" extra_args = [ "--tools=run_terminal_cmd", "--allow=Bash(printf *)", "--sandbox=workspace", ] [agents.default] model_provider = "grok_cli.default" classifier_provider = "xai.default" channels = ["slack.default"] # example [agents.dependabot] model_provider = "grok_cli.ops" ``` | Layer | Where | Purpose | | ----- | ----- | ------- | | Reply precheck | `classifier_provider` → API alias (e.g. `xai.default`) | REPLY / `NO_REPLY[*]` only; avoids CLI thinking text as the message body | | Full answer | `model_provider` → `grok_cli.default` | Grok Build ACP; prompt only on stdin | | OS sandbox | Default `--sandbox strict` (or `extra_args` override) | Read CWD + system paths; write CWD + `~/.grok` + tmp; child network blocked on Linux. Built-ins are not a permanent credential boundary - use custom `deny` for secrets | | App permissions | Empty built-in tool set + fail-closed ACP default | Explicit bypass flags select `allow_once`; discovered Grok rules may also pre-authorize configured tools | | Channel delivery | ZeroClaw `thread_replies` / channel config | Single in-thread reply path | | Optional gate | Slack `mention_only` + `strict_mention_in_thread` | Drop unmentioned group/thread traffic before the agent (see [Slack](../channels/slack.md)); independent of the classifier | Keep channel-facing aliases at the defaults and give them dedicated, reviewed workspaces. Permission rules, MCP servers, plugins, and hooks discovered by Grok, along with permission/sandbox/tool flags in `extra_args`, are trusted operator policy and can widen the subprocess boundary. #### Grok CLI OS sandbox (how to use it from ZeroClaw) This is **Grok Build’s process sandbox** (Landlock / Seatbelt / seccomp on the `grok` subprocess). It is **not** ZeroClaw’s tool sandbox on `[risk_profiles.*.sandbox_*]`: that wraps ZeroClaw tools after native tool calls. If an operator opts a provider alias into Grok tools, Grok's `--sandbox` is the effective confinement for that work. See also [Sandboxing](../security/sandboxing.md) for ZeroClaw’s risk-profile sandbox. ZeroClaw always supplies an explicit sandbox flag. The default is `strict`. Set `--sandbox=` in that provider alias's `extra_args` to choose a different profile; ambient Grok config or `GROK_SANDBOX` cannot silently relax the provider-owned default. Project `.grok/config.toml` can hold MCP / plugins / **`[permission]`**. Grok loads that file as trusted operator policy; matching allow rules may authorize tools without an ACP permission request. It does **not** select the active sandbox profile by itself. Profile **names** and custom profile **bodies** can live in project `/.grok/sandbox.toml`; pass `--sandbox=` through `extra_args` to turn that profile on. **Built-in profiles** (from Grok’s sandbox docs): | Profile | FS read | FS write | Child process network (Linux) | Typical use | | ------- | ------- | -------- | ----------------------------- | ----------- | | `off` (default) | unrestricted | unrestricted | unrestricted | Full access | | `workspace` | everywhere | CWD + `~/.grok` + tmp | allowed | Everyday coding | | `read-only` | everywhere | `~/.grok` + tmp only | blocked | Review when broad reads are OK | | `strict` | CWD + system paths | CWD + `~/.grok` + tmp | blocked | **Default channel chatbot (recommended)** | | `devbox` | everywhere | most of the tree | allowed | Disposable VMs | Child-network blocking applies to **shell children** on Linux only; in-process Grok tools (LLM, built-in web search) still need network. Prefer **`strict`** for messaging bots to narrow the default filesystem write surface to the agent workspace plus Grok runtime paths. Built-in profiles are **not** a permanent credential boundary: [xAI's sandbox docs](https://docs.x.ai/build/features/sandbox) warn that paths such as `~/.ssh` are not guaranteed protected by built-ins, and recommend a custom profile with a kernel-enforced `deny` list for secrets. Use `read-only` only when the agent must read outside the workspace without writing project files. **Custom profile example** (define in workspace, select from ZeroClaw): ```toml # /.grok/sandbox.toml [profiles.channel-bot] extends = "strict" # Optional kernel deny paths (needs bubblewrap on Linux when non-empty): # deny = ["**/.env", "**/*.pem"] ``` ```toml # ZeroClaw config.toml [providers.models.grok_cli.default] working_directory = "/path/to/agents/default/workspace" extra_args = ["--sandbox=channel-bot"] ``` **Per-agent sandbox:** use **separate provider aliases** with different, explicit `extra_args` and dedicated working directories. Keep channel aliases on the strict/no-built-in-tools default, review the Grok configuration discovered for each workspace, and point each agent at the matching `model_provider` alias. ### Azure OpenAI: slot `azure` `resource`, `deployment`, and `api_version` live in this typed config, they are not read from environment variables. ### Copilot: slot `copilot` Uses a GitHub Copilot subscription for agent inference. Authentication uses a Copilot OAuth token obtained from GitHub. ### Telnyx: slot `telnyx` Voice-oriented AI endpoint. Pair with the `clawdtalk` channel for real-time SIP calls. ### KiloCLI: slot `kilocli` Local inference via KiloCLI. ### Kilo AI Gateway: slot `kilo` ```toml [providers.models.kilo.home] model = "anthropic/claude-sonnet-4-6" api_key = "..." # endpoint = "gateway" # default → https://api.kilo.ai/api/gateway ``` Cloud API via Kilo AI Gateway. Bearer-token auth with multiple model tiers (free, balanced, pro). The `/models` endpoint is public (`PUBLIC_MODEL_LISTING`), so model listing works without a credential. Because it is queried live, it is the source that carries pricing into the cost-rates editor. The shared models.dev catalog (`kilo` key) is only a fallback for when the live endpoint is unreachable, and it does not include pricing. > **Naming migration:** `kilo` now refers to this gateway provider. The KiloCLI > subprocess provider keeps its `kilocli` slot (synonym `kilo-cli`). If you > previously configured the CLI provider under the `kilo` shorthand, switch to > `kilocli`. ### ZeroRouter: slot `zerorouter` ```toml [providers.models.zerorouter.gateway] model = "anthropic/claude-sonnet-5" api_key = "..." # a ZeroRouter key (prefix `zcr_`); or inject from the env # uri = "http://localhost:8080/v1" # a self-hosted or local router; omit for the hosted default ``` OpenAI-compatible LLM gateway; Bearer-token auth. ZeroRouter is currently in beta. The slot defaults to the public hosted deployment at `https://zerorouter.ai/v1`, so model discovery works with no configuration at all. ZeroRouter is also self-hostable (AGPL); to reach your own router, locally at `http://localhost:8080/v1` or anywhere else, set `uri` explicitly. A key minted on one router does not authenticate on another, so `api_key` must come from the deployment `uri` points at. Beyond the chat-completions wire this slot speaks, ZeroRouter also serves the OpenAI Responses API inbound (`POST /v1/responses`), so Responses-wire clients, such as a Codex CLI `model_provider` with `wire_api = "responses"`, can point at the same deployment and key directly. The `/v1/models` endpoint is public (`PUBLIC_MODEL_LISTING`), so model listing and its prompt/completion pricing come live from the router itself without a credential; because it is queried live, it is the source that carries pricing into the cost-rates editor (this family has no models.dev or OpenRouter fallback). Inference does require a key: set `api_key` directly, or inject it from the environment the same way as any other provider key (see [Configuration](./configuration.md) for `api_key` resolution order). > **No built-in login.** This preset configures the provider through the > standard typed `api_key` path only; it does not add a device-flow login, > OAuth, or provider-specific credential storage. Set `api_key` (or its env > injection) to run inference. --- ## All slots Every canonical slot, its default endpoint, whether it runs locally, and its full config field set, generated from the provider registry and the config schema. Click a slot to expand its fields; click a field to see how to set it. Fixed entries show canonical defaults. `operator required` means the alias needs endpoint input, such as an Azure resource and deployment or a `custom` `uri`. `dynamic / resolved at runtime` endpoints may depend on credentials, region, discovery, or runtime state and do not necessarily require `uri`. CLI-backed providers use their local command. {{#model-provider-fields}} For a worked example per family, see [Configuration](./configuration.md). If your vendor isn't listed, use the `custom` slot ([Custom providers](./custom.md)). ### Worked examples: Morph, GitHub Models, Upstage, Featherless, Arcee, Lambda AI, Inception Each of these is a standard OpenAI-compatible slot: set `model` and `api_key`, leave `uri` off (the typed endpoint supplies it). None of them ship a public model index, so the model picker stays empty until you paste a credential. Once a key is set, ZeroClaw lists models from the provider's live `/models` endpoint. The model IDs below are illustrative; confirm the current catalog in the vendor dashboard. **Morph**: slot `morph`. Fast apply-edits models (`morph-v3-large`, `morph-v3-fast`, or `auto`). Key from the [Morph dashboard](https://morphllm.com). **GitHub Models**: slot `github_models` (alias `github-models`). OpenAI / Meta / Microsoft models behind a single GitHub Personal Access Token. Create a PAT with the **`models`** permission (fine-grained); a Copilot token is *not* the same credential. Model IDs are publisher-prefixed (e.g. `openai/gpt-4o`). **Upstage**: slot `upstage`. Solar Pro / Solar Mini (e.g. `solar-pro2`). Key from the [Upstage console](https://console.upstage.ai/api-keys). **Featherless**: slot `featherless`. Serverless open-weight models, addressed by their Hugging Face repo IDs (e.g. `meta-llama/Meta-Llama-3.1-8B-Instruct`). Key from [featherless.ai](https://featherless.ai). **Arcee**: slot `arcee`. Native models include `conductor`, `maestro`, `virtuoso-large`, `coder-large`, and `blitz`. Key from the [Arcee platform](https://www.arcee.ai). Arcee's Platform API uses the non-standard `/api/v1` base path; the typed endpoint already accounts for this, so still leave `uri` off. **Lambda AI**: slot `lambda_ai` (alias `lambda-ai`). Lambda's hosted inference (e.g. `hermes3-405b`). Key from the [Lambda Cloud](https://cloud.lambda.ai) API-keys page. **Inception**: slot `inception`. The Mercury diffusion-LLM family (`mercury-coder` and the newer `mercury-2`). Key from the [Inception platform](https://platform.inceptionlabs.ai). **Atlas Cloud**: slot `atlascloud`. OpenAI-compatible endpoint `https://api.atlascloud.ai/v1` with bearer-token auth. Use the canonical `atlascloud` slot only; `atlas`, `atlas-cloud`, and `atlas_cloud` are not runtime aliases. ```toml [providers.models.atlascloud.home] model = "..." api_key = "..." ``` > Credentials come only from config (`api_key`) or the `--credential` override at run > time, these slots do **not** read a per-provider `*_API_KEY` environment variable. NEAR AI Cloud example: ```toml [providers.models.nearai.tee] model = "..." # pick a modelId from https://cloud-api.near.ai/v1/model/list api_key = "..." ``` The `nearai` slot uses `https://cloud-api.near.ai/v1` by default and sends `Authorization: Bearer `. To bridge an existing `NEARAI_API_KEY` shell variable into ZeroClaw's schema-mirror env surface, set `ZEROCLAW_providers__models__nearai__tee__api_key="$NEARAI_API_KEY"`. --- ## Multi-region families Several Chinese vendors expose distinct regional endpoints with different default models. Use one canonical slot and pick the region with the typed `endpoint` field on the alias entry. ### Moonshot: slot `moonshot` Variants: `cn`, `intl`, `code`. ### Qwen / DashScope: slot `qwen` OAuth-backed Qwen accounts use the same slot with `auth_mode = "o_auth"`. ### GLM: slot `glm` ### MiniMax: slot `minimax` ```toml [providers.models.minimax.intl] model = "MiniMax-M3" # or MiniMax-M2.7, MiniMax-M2.7-highspeed api_key = "..." endpoint = "intl" # variants: cn, intl ``` For MiniMax's Anthropic-compatible API, use `[providers.models.anthropic.minimax]` with `uri = "https://api.minimax.io/anthropic"` (Global) or `uri = "https://api.minimaxi.com/anthropic"` (China) instead. ### Z.AI: slot `zai` For Z.AI's Anthropic-compatible API, use `[providers.models.anthropic.zai]` with `uri = "https://api.z.ai/api/anthropic"` instead. ### Doubao / Volcengine: slot `doubao` The remaining Chinese-region slots (`yi`, `hunyuan`, `qianfan`, `baichuan`) appear in the all-slots table above; select the region with the typed `endpoint` field on the alias entry. --- ## Routing layers OpenRouter is treated as a single first-class provider, not a meta-router. The runtime sees one endpoint; OpenRouter handles vendor fan-out behind that endpoint. For per-task routing, run multiple agents and let channels pick which agent handles which traffic, see [Routing](./routing.md). For a narrower in-config hint mechanism, use `[[model_routes]]`. --- ## Something missing? - If the endpoint is OpenAI-compatible, use the `custom` slot with `uri` set. - If it has its own canonical slot above, use that, even if you only see one of its regions, the slot's `endpoint` enum covers the rest. - If it speaks a non-OpenAI wire format and needs its own implementation, see [Custom providers](./custom.md).