---
title: "Choose model aliases"
description: "Use an alias when the tenant should choose the provider. The edge records its choice when the job starts."
canonical_url: "https://docs.oz0.ai/spend/models-and-keys/aliases"
---
# 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:

```yaml [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:

```yaml [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.

```bash [Terminal]
oz0 model alias set smart anthropic/claude-sonnet-5-5 mistral/mistral-large
oz0 model resolve smart --needs tools --min-context 128k
```

```text [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](https://docs.oz0.ai/reference/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:

```yaml [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:

<table>
<thead>
  <tr>
    <th>
      Provider
    </th>
    
    <th>
      <code>
        default
      </code>
    </th>
    
    <th>
      <code>
        fast
      </code>
    </th>
    
    <th>
      <code>
        smart
      </code>
    </th>
  </tr>
</thead>

<tbody>
  <tr>
    <td>
      <code>
        anthropic
      </code>
      
       (built in)
    </td>
    
    <td>
      <code>
        claude-sonnet-5-5
      </code>
    </td>
    
    <td>
      <code>
        claude-haiku-5-5
      </code>
    </td>
    
    <td>
      <code>
        claude-opus-5-5
      </code>
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        openai
      </code>
      
       (built in)
    </td>
    
    <td>
      <code>
        gpt-6.1-sol
      </code>
    </td>
    
    <td>
      <code>
        gpt-6-luna
      </code>
    </td>
    
    <td>
      <code>
        gpt-6-astra
      </code>
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        google
      </code>
    </td>
    
    <td>
      <code>
        gemini-3.8-flash
      </code>
    </td>
    
    <td>
      <code>
        gemini-3.5-flash-lite
      </code>
    </td>
    
    <td>
      <code>
        gemini-4-argon
      </code>
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        vertex
      </code>
      
      , <code>
        vertex-federated
      </code>
    </td>
    
    <td>
      <code>
        claude-sonnet-5-5
      </code>
    </td>
    
    <td>
      <code>
        claude-haiku-5-5
      </code>
    </td>
    
    <td>
      <code>
        claude-opus-5-5
      </code>
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        mistral
      </code>
    </td>
    
    <td>
      <code>
        mistral-medium-latest
      </code>
    </td>
    
    <td>
      <code>
        mistral-small-latest
      </code>
    </td>
    
    <td>
      <code>
        mistral-large-latest
      </code>
    </td>
  </tr>
</tbody>
</table>

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):

```bash [Terminal]
oz0 model alias seed
```

```text [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:

```text [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:

```bash [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:

<table>
<thead>
  <tr>
    <th>
      Where
    </th>
    
    <th>
      What happens
    </th>
    
    <th>
      What the job shows
    </th>
  </tr>
</thead>

<tbody>
  <tr>
    <td>
      An agent's <code>
        fallback:
      </code>
      
       list
    </td>
    
    <td>
      The runtime tries the next model when one fails or is refused
    </td>
    
    <td>
      The model step names the model that answered; the job's trace and summary get the finding <code>
        model_fallback
      </code>
      
      : "anthropic/claude-sonnet-5-5 answered 529, and anthropic/claude-haiku-4-5 answered instead"
    </td>
  </tr>
  
  <tr>
    <td>
      An alias (<code>
        use:
      </code>
      
      )
    </td>
    
    <td>
      When the job starts, the edge picks the first of the alias's models that fits and leaves out the others, each with why
    </td>
    
    <td>
      The resolution step names the model it picked; when it left any out, the finding <code>
        model_fallback
      </code>
      
       names them with the reason
    </td>
  </tr>
  
  <tr>
    <td>
      A <a href="https://docs.oz0.ai/spend/models-and-keys/mapping#map-a-plugins-models">
        mapping rule
      </a>
    </td>
    
    <td>
      When the job starts, the tenant's rule decides the model instead of the agent's definition
    </td>
    
    <td>
      The resolution step names the model; the finding <code>
        model_override
      </code>
      
       (info) names the rule and what it gave
    </td>
  </tr>
  
  <tr>
    <td>
      A <a href="https://docs.oz0.ai/fleet/local-models">
        local model's
      </a>
      
       queue
    </td>
    
    <td>
      A call that waits longer than <code>
        model.wait
      </code>
      
       for a slot falls back to the agent's <code>
        model.fallback
      </code>
    </td>
    
    <td>
      The cost log counts the local call as refused, with why; the model step names the model that answered, and the finding names both
    </td>
  </tr>
  
  <tr>
    <td>
      A <a href="https://docs.oz0.ai/spend/models-and-keys/effort-and-cascades#reasoning-effort">
        reasoning effort
      </a>
    </td>
    
    <td>
      When the job starts, the tenant's ceiling lowers the effort asked for, or a model lacks the level and gets the nearest it has
    </td>
    
    <td>
      The resolution step and each model step name the effort; the finding <code>
        effort_adjusted
      </code>
      
       (info) says what changed and why
    </td>
  </tr>
</tbody>
</table>

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.


## Sitemap

See the full [sitemap](https://docs.oz0.ai/sitemap.md) for all pages.
