colonizer
install
docs Model providers

#Model providers: connections and backends

A connection is one entry in Model providers (providers.json on the mothership): a base_url, a credential, and a wire — anthropic (the default) or openai. Model traffic reaches a connection through the provider gateway at /providers/<id>/ (docs/protocol.md §6.5), which presents the Anthropic Messages wire to the colony and translates an openai-wire connection in both directions. This page is the compatibility map between those connections and the shipped agent backends, the two switches that take tools away from a colony, and the settings that decide what a connection may spend and carry. Every field and route is in docs/protocol.md §6.5.

#Connection → backends

Backendanthropic wireopenai wireHarness-level disabled_tools
claude-codeyes — unrouted models go straight to Anthropic; <provider>/<model> rides the gateway's Anthropic Messages routeyes — same route; the gateway translates the openai wireyes — the disabled_tools setting (COLONIZER_DISABLED_TOOLS) becomes the SDK session's disallowedTools
acpnono — talks to the agent's own API host (Gemini: generativelanguage.googleapis.com, grok: api.x.ai) with the colony's own secret; the runner passes model ids to session/set_model and reads no model routesno — ACP names no per-tool switch, so the module declares no disabled_tools setting
codexno — an anthropic-wire route is refused (CODEX_MODEL_PROVIDER): codex speaks the OpenAI wire onlyyes — a <provider>/<model> whose prefix matches a route rides the gateway's OpenAI passthrough (/v1/responses) via a codex model_provider override; bare ids and openai/ with no route go straight to api.openai.com with CODEX_API_KEYyes — native names (shell, web_search, view_image) become -c features.shell_tool=false, -c web_search="disabled" and -c features.view_image=false, and the runner passes --strict-config so a key codex stops recognising fails the turn instead of silently keeping the tool; apply_patch (how codex writes files) and MCP tools cannot be turned off
grok-buildno — an anthropic-wire route is refused (GROK_MODEL_PROVIDER): grok speaks the OpenAI wire onlyyes — same passthrough, via GROK_MODELS_BASE_URL and the colony token as the bearer key; bare ids and xai-grok/ with no route go straight to api.x.ai with XAI_API_KEYyes — native tool ids (run_terminal_cmd, read_file, write_file, search_replace, grep, list_dir, web_fetch, Agent) go to --disallowed-tools; web_search is always off already
hermesyes — one config provider per gateway route, transport: anthropic_messagesyes — same route; the gateway translatesyes, toolset-granular — the names are Hermes toolsets (terminal, file, web, browser, vision, code_execution, todo, session_search, image_gen, …) added to agent.disabled_toolsets; single tools inside a toolset (only write_file, say) cannot be turned off
opencodeyes — one @ai-sdk/anthropic provider per gateway route at <base_url>/v1yes — same route; the gateway translatesyes — native tool ids become permission: {"*": "allow", <id>: "deny"} entries in the generated inline config; edit covers write/edit/apply_patch (the three share one permission)
piyes — the runner writes models.json from the routes, api: anthropic-messagesyes — same; the gateway presents anthropic-messages to every guestyes — native tool names (read, bash, edit, write, grep, find, ls) go to --exclude-tools

codex and grok-build speak only the OpenAI wire, so a route reaches them when the connection's wire is openai: the gateway forwards their Responses and Chat Completions requests to the connection verbatim and records the usage, so spend accounting and the budgets apply. A connection on the anthropic wire is refused by both runners, named in the model setting's error. A bare model id, or openai/ / xai-grok/ with no route configured, still runs against the vendor API from the colony's own secret, outside the gateway: no spend accounting through the gateway and no connection-level tool strip for those.

#model_map and wire names

A connection's optional model_map maps a canonical model name to the name sent on the wire: {"<canonical>": "<wire_name>"}. An empty wire_name sends the canonical name as-is; a non-empty one is sent verbatim, so a provider that only knows its own branding can be addressed by the canonical name every setting uses. A non-empty model_map is authoritative: the connection serves only the canonicals it lists, and boot refuses a model that is not among them.

Settings → Providers has a Model map editor for this (canonical → wire rows), in the form's Connection policy group; PUT /api/providers/{id} and providers.json take it too. A PUT that leaves a field out keeps its saved value; an explicit empty value clears it.

#Taking tools away: two levels

Boot logs what was taken away, per colony, into harness.jsonl: tool '<name>' disabled (level: connection|harness, …).

#Boot fails fast

A colony that cannot reach the model it was configured with is refused at boot, not left to flail:

backend '<agent id>' has no provider for model '<value>': <fix>

with a fix in the message, when any of these holds:

  1. the model's <provider>/ prefix names no configured connection;
  2. the connection's non-empty model_map does not list the model;
  3. the connection is unreachable at launch and the route has no Claude fallback_model (a <provider>/<model> fallback only covers quota exhaustion). Before refusing, the boot probes the connection again rather than trusting the cached answer, so an outage that ended a moment ago does not block the launch. A connection with a Claude fallback_model only gets a warning in the colony log: its requests go to that Claude model instead.

Only the connections this colony's model settings name (model, subagent_model, background_model, small_model where the agent module has one, and model_low/model_high when per-task routing picks one) are checked, so an unrelated connection that is down blocks nothing.

Two more misconfigurations refuse the launch the same way, before any probe runs:

#Base URLs

The gateway joins the request's own path (/v1/messages, /v1/chat/completions, /v1/responses, and /v1/models for the health probe) to base_url, ignoring any trailing /. Enter the base the provider documents as its API root:

Saving a new provider, or changing its base URL, wire or key, in Settings → Providers sends a one-token test request through the colony's route and shows the URL it hit and the status. An upstream 404 or 405 during a colony's turn is logged with that URL too (no userinfo or query), and names the base URL as the likely cause.

#Plans, quotas and trust

A connection carries a few more settings. pricing and quota are edited in Settings → Providers, as are trusted, model_map and disabled_tools (the form's Connection policy group); the API (PUT /api/providers/{id}) and providers.json hold them all, and GET /api/providers returns them so the form prefills.