Connect a model provider

Choose model aliases

Use an alias when the tenant should choose the provider. The edge records its choice when the job starts.

For: tenant administrators and cost owners.

Use an alias when the tenant should choose the provider. The edge records its choice when the job starts.

Name the model, or ask for an alias

An agent names its models as <provider>/<model>, with fallbacks tried in order:

agents/reviewer.yaml
model:
  primary: anthropic/claude-sonnet-5-5
  fallback: [anthropic/claude-haiku-4-5]

Or it asks for one of the tenant's aliases, with what it needs of the model, so the plugin carries no vendor to the tenants that install it:

agents/reviewer.yaml
model:
  use: smart
  needs: [tools, structured_output]   # tools, vision, structured_output, thinking, pdf, audio, web_search, prompt_cache
  min_context: 128k                   # 128000, 128k or 1m

The tenant maps smart to models of its providers, in order of preference. When a job starts, the edge picks the first that has what the agent needs and that the tenant's data rules allow; the others that do become its fallbacks. The answer goes into the job's history, so a replay, or a retry on another node, keeps the same model even if the alias changes meanwhile. An alias with nothing that fits fails the job at once, with ModelUnresolved and the reason for each model it left out.

Terminal
oz0 model alias set smart anthropic/claude-sonnet-5-5 mistral/mistral-large
oz0 model resolve smart --needs tools --min-context 128k
Output
model     anthropic/claude-sonnet-5-5  anthropic-messages
fallback  mistral/mistral-large        openai-chat

A model matches needs and min_context only as its provider record describes it, so describe the models your aliases point at (see below); for the models the standard aliases name, the release's own description stands in when the record has none. oz0 plugin lint suggests an alias where an agent names a vendor's model. Agents that rely on one vendor's own features, such as Anthropic's server tools, keep naming that vendor, and say why in model.vendor_reason (agent definition).

The standard aliases

Every tenant has three aliases once a provider is set up: default, fast and smart. OZ's own plugins, its examples and the templates of oz0 plugin new ask for them, with what they need, so they run on whichever provider the tenant pays for:

agents/oz0-web-research.yaml
model:
  use: default
  needs: [tools]

Setup seeds them from the provider a tenant adds first: a record of its own (oz0 provider set mistral --preset mistral), or the key of a built-in provider (oz0 secret set ANTHROPIC_API_KEY, which oz0 dev, oz0 plugin test and the quickstart do from your environment). For each provider it knows, the release names the model that stands for each alias:

Providerdefaultfastsmart
anthropic (built in)claude-sonnet-5-5claude-haiku-5-5claude-opus-5-5
openai (built in)gpt-6.1-solgpt-6-lunagpt-6-astra
googlegemini-3.8-flashgemini-3.5-flash-litegemini-4-argon
vertex, vertex-federatedclaude-sonnet-5-5claude-haiku-5-5claude-opus-5-5
mistralmistral-medium-latestmistral-small-latestmistral-large-latest

The names are the vendors' own model IDs at the time of this release; check them against the vendor's documentation before you rely on one. Providers whose model names are your own, or depend on your account (Bedrock's inference profiles, Azure's deployment names, a vLLM server, local models), and providers that serve many vendors' models (OpenRouter, Groq, Together) name none: map the aliases to their models yourself with oz0 model alias set. A record seeds only under its preset's ID: one you call eu-claude names nothing.

What seeding does, exactly:

  • it never replaces an alias the tenant has: yours stay as they are;
  • it takes each provider's model, the tenant's own records first, then the built-in ones whose key the tenant has set, so a tenant with two providers gets the second as each alias's fallback;
  • an alias you delete stays deleted when the server restarts; adding a provider or a key, or oz0 model alias seed, seeds the names the tenant lacks again;
  • each alias it writes is in the audit log as model_alias.set by system, with who set the provider or key and why.

Tenants set up before the standard aliases existed are seeded once when the server starts. To seed the ones a tenant lacks now, or to see what it has, run oz0 model alias seed (the Models page has the same button when one is missing):

Terminal
oz0 model alias seed
Output
default: seeded, openai/gpt-6.1-sol
fast: kept as it is, mistral/mistral-small-latest
smart: seeded, openai/gpt-6-astra

Map an alias at install

A plugin may ask for an alias the tenant does not have, such as one of its own (reviewer) or a standard one in a tenant whose providers name no models. The install says which, and its agents' jobs cannot start their model until each is mapped:

Output
The plugin's agents ask for model aliases the tenant lacks: smart. Their jobs cannot start their model until each is mapped:

Map it in place, to another of the tenant's aliases or to a <provider>/<model> that resolves for the tenant:

Terminal
oz0 plugin install https://github.com/acme/oz-review --map smart=default
oz0 plugin install https://github.com/acme/oz-review --map reviewer=eu-gw/claude-sonnet-5-5

Each mapping becomes a tenant alias, so other plugins that ask for it use it too; an alias the tenant has is never replaced (change it with oz0 model alias set). The target must have what every agent that asks for the alias needs (needs, min_context, and the model API of the agent's harness), or nothing is mapped and the install says why.

A target that does not exist for the tenant is refused before anything is installed. Mapping aliases changes them, so it needs the models.manage permission besides plugins.install. The console's install dialog takes the same mappings, one alias=target a line.

A harness checks the provider record the alias resolves to, never the provider's name: the Claude Code harness runs any record that takes Anthropic's Messages API, such as a gateway of your own or Bedrock, and refuses one that takes only chat completions.

No model is replaced silently

The following mechanisms can change the selected model or its effort. Each change shows in the job:

WhereWhat happensWhat the job shows
An agent's fallback: listThe runtime tries the next model when one fails or is refusedThe model step names the model that answered; the job's trace and summary get the finding model_fallback: "anthropic/claude-sonnet-5-5 answered 529, and anthropic/claude-haiku-4-5 answered instead"
An alias (use:)When the job starts, the edge picks the first of the alias's models that fits and leaves out the others, each with whyThe resolution step names the model it picked; when it left any out, the finding model_fallback names them with the reason
A mapping ruleWhen the job starts, the tenant's rule decides the model instead of the agent's definitionThe resolution step names the model; the finding model_override (info) names the rule and what it gave
A local model's queueA call that waits longer than model.wait for a slot falls back to the agent's model.fallbackThe cost log counts the local call as refused, with why; the model step names the model that answered, and the finding names both
A reasoning effortWhen the job starts, the tenant's ceiling lowers the effort asked for, or a model lacks the level and gets the nearest it hasThe resolution step and each model step name the effort; the finding effort_adjusted (info) says what changed and why

The gateway itself never replaces a model or a provider: it forwards a call to the one asked for, or refuses it. A finding never stops a job; it says what happened, in oz0 job findings and oz0 job trace and on the job's page, so a cheaper or weaker model answering for a stronger one is never a surprise in the bill or the results.

Copyright © 2026