> ## Documentation Index
> Fetch the complete documentation index at: https://docs.getbifrost.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Aliasing Models

> Map arbitrary model names to any target identifier using static key-level aliases or dynamic routing rules.

## Overview

Model aliasing lets you decouple the model name your application sends from the identifier Bifrost actually uses when calling a provider. You can:

* Send `"best-model"` and have Bifrost resolve it to whatever model you've decided is best - without touching your application code
* Map a single logical name like `"gpt-4o"` to a provider-specific deployment name, inference profile ARN, or fine-tuned model ID
* Give different teams different underlying models behind the same name

There are two aliasing mechanisms, and they operate at different layers:

|                      | Static Aliases                                    | Dynamic Aliases (Routing Rules)                           |
| -------------------- | ------------------------------------------------- | --------------------------------------------------------- |
| **Where configured** | On a provider key                                 | On routing rules, scoped to VK / Team / Customer / Global |
| **When applied**     | After key selection, before the provider API call | At request time, before key selection                     |
| **Scope**            | Per-key                                           | Per-VK, per-team, per-customer, or global                 |
| **Condition-based**  | No - always resolves                              | Yes - CEL expression controls when it fires               |

***

## Static Aliasing

<Info>Static aliasing is available in **Bifrost v1.5.0-prerelease2 and above**.</Info>

Static aliases are configured directly on a provider key. Every request that is served by that key will have its model name resolved through the alias map before the request reaches the provider API.

### How it works

1. Your application sends a request with `model: "best-model"`
2. Bifrost selects a key that supports `"best-model"` (alias names are treated as model identifiers for key selection and allowlists)
3. Before calling the provider, Bifrost resolves `"best-model"` → `"gpt-4o-2024-11-20"` using that key's `aliases` map
4. The provider receives `"gpt-4o-2024-11-20"` - your application never needs to know

### Configuration

Add an `aliases` object to any key in `config.json`:

```json theme={null}
{
  "providers": {
    "openai": {
      "keys": [
        {
          "value": "env.OPENAI_API_KEY",
          "models": ["*"],
          "aliases": {
            "best-model": "gpt-4o-2024-11-20",
            "fast-model": "gpt-4o-mini",
            "embedder": "text-embedding-3-large"
          }
        }
      ]
    }
  }
}
```

You can also add aliases via the provider keys API:

```bash theme={null}
curl -X POST http://localhost:8080/api/providers/openai/keys \
  -H "Content-Type: application/json" \
  -d '{
    "value": "env.OPENAI_API_KEY",
    "models": ["*"],
    "aliases": {
      "best-model": "gpt-4o-2024-11-20",
      "fast-model": "gpt-4o-mini"
    }
  }'
```

Each alias maps the name your application sends to either a plain target string (the simplest form) or an object that additionally tags the alias with the canonical name used for pricing/logs, the model family used for provider routing, and any provider-specific overrides. The shorthand and the rich object form are interchangeable - both are accepted on the wire.

```json theme={null}
{
  "aliases": {
    "fast-model": "gpt-4o-mini",
    "best-model": {
      "model_id": "12345-azure-deployment",
      "model_name": "claude-sonnet-4-5",
      "model_family": "anthropic",
      "description": "Claude Sonnet 4.5 on our Azure tenant",
      "api_version": "2024-10-21",
      "endpoint": "env.AZURE_SECONDARY_ENDPOINT"
    }
  }
}
```

| Field          | Type            | Description                                                                                                                                                                                                                                                                                                                          |
| -------------- | --------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `model_id`     | string          | **Required.** The wire identifier forwarded to the provider — deployment name, inference profile ARN, fine-tune ID, anything.                                                                                                                                                                                                        |
| `model_name`   | string          | Canonical model name used by pricing and logs. Set this when `model_id` is opaque (e.g. an Azure deployment ID) so cost attribution still hits the catalog.                                                                                                                                                                          |
| `model_family` | enum            | Forces the family used for provider routing decisions (request shape, response parsing, etc.). One of: `anthropic`, `openai`, `mistral`, `cohere`, `gemini`, `gemma`, `llama`, `imagen`, `veo`, `nova`, `titan`. When unset, the family is auto-detected by substring matching against `model_name`, `model_id`, and the alias name. |
| `description`  | string          | Free-form note. Surfaced in the UI; not used for routing.                                                                                                                                                                                                                                                                            |
| `region`       | string / EnvVar | Per-alias region override (Bedrock + Vertex). Falls back to the key-level region when unset.                                                                                                                                                                                                                                         |

**Provider-specific overrides** (only set on aliases whose owning key matches the provider; validation rejects mismatches):

| Provider  | Field                      | Description                                                                                                       |
| --------- | -------------------------- | ----------------------------------------------------------------------------------------------------------------- |
| Azure     | `api_version`              | Overrides the `api-version` query parameter                                                                       |
| Azure     | `anthropic_version`        | Overrides the `anthropic-version` header for Claude-on-Azure deployments                                          |
| Azure     | `endpoint`                 | Overrides the key-level Azure endpoint — useful when one credential spans deployments on multiple Azure resources |
| Vertex    | `project_id`               | Per-alias GCP project ID                                                                                          |
| Vertex    | `project_number`           | Per-alias GCP project number (required for fine-tuned models)                                                     |
| Bedrock   | `inference_profile_arn`    | Cross-region inference profile ARN invoked instead of the model ID                                                |
| Replicate | `use_deployments_endpoint` | Routes the alias through Replicate's deployments endpoint                                                         |

### Validation rules

Bifrost rejects an aliases map that violates any of these:

* **No empty strings** - both the alias name and `model_id` must be non-empty
* **No leading or trailing whitespace** on either side
* **No duplicate alias names** (checked case-insensitively) - `"GPT-4o"` and `"gpt-4o"` cannot both be keys in the same map
* **No provider mismatch on sub-configs** - an Azure-specific override (`api_version`, `endpoint`, …) can only appear on an alias whose owning key is an Azure key, and likewise for Vertex / Bedrock / Replicate

### Case-insensitive matching

Alias lookup is case-insensitive. If your map has `"GPT-4O": "gpt-4o-2024-11-20"` and a request comes in with `model: "gpt-4o"`, it resolves correctly. Aliases are stored as-is but matched without regard to case.

### Tracking in responses

Every response includes a `routing_info` block in `extra_fields` describing the routing decisions Bifrost made:

```json theme={null}
{
  "extra_fields": {
    "routing_info": {
      "provider": "openai",
      "model": "best-model",
      "key": "production-key",
      "resolved_key_alias": {
        "model_id": "gpt-4o-2024-11-20",
        "model_name": "gpt-4o"
      }
    }
  }
}
```

| Field                                                          | Description                                                                                                                                     |
| -------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------- |
| `routing_info.provider`                                        | Provider that handled the request                                                                                                               |
| `routing_info.model`                                           | Model name the caller sent (the LHS of the alias map when an alias matched)                                                                     |
| `routing_info.key`                                             | Human-friendly name of the key used                                                                                                             |
| `routing_info.resolved_key_alias`                              | Present only when an alias matched. Carries the wire `model_id`, the canonical `model_name` (if set), and the resolved `model_family` (if set). |
| `routing_info.is_fallback`                                     | `true` when the request was served by a fallback attempt rather than the primary                                                                |
| `routing_info.primary_provider` / `routing_info.primary_model` | Populated on fallback attempts with the primary attempt's provider/model                                                                        |

When no alias matches, `resolved_key_alias` is omitted and `model` carries the wire identifier directly.

<Note>
  `extra_fields.provider`, `extra_fields.original_model_requested`, and `extra_fields.resolved_model_used` are deprecated but still populated for backward compatibility. New consumers should read from `routing_info`.
</Note>

***

## Dynamic Aliasing

Dynamic aliasing uses [Routing Rules](/providers/routing-rules) to rewrite the model at request time based on a CEL expression. Unlike static aliases (which are fixed to a key), dynamic aliases fire conditionally and are scoped - so the same model name can resolve differently depending on who is making the request.

### How scopes make it dynamic

Routing rules are organized into four scopes, evaluated in priority order:

```
Virtual Key scope  →  Team scope  →  Customer scope  →  Global scope
```

This means you can configure aliasing at any level of your org hierarchy. For example:

* **Global scope** aliases `"best-model"` → `"gpt-4o-mini"` (cost-effective default for everyone)
* **Team scope** for the AI team overrides `"best-model"` → `"claude-3-5-sonnet-20241022"` (more capable)
* **Virtual Key scope** for a specific VK overrides `"best-model"` → `"o1"` (highest capability, specific use case)

Each requester gets the right model behind the same name, with zero changes to the application.

### Example: alias based on request type

```json theme={null}
{
  "name": "route-embeddings-to-fast-model",
  "cel_expression": "request_type == 'embedding' && model == 'embedder'",
  "targets": [
    { "model": "text-embedding-3-small", "weight": 1.0 }
  ],
  "scope": "global"
}
```

Any request with `model: "embedder"` that is an embedding request gets routed to `"text-embedding-3-small"`.

### Example: alias with provider switch

```json theme={null}
{
  "name": "premium-tier-routing",
  "cel_expression": "headers['x-tier'] == 'premium'",
  "targets": [
    { "provider": "anthropic", "model": "claude-3-5-sonnet-20241022", "weight": 1.0 }
  ],
  "scope": "global"
}
```

Premium-tier requests get routed to Anthropic's Sonnet regardless of what model the client sent.

### Multi-step rewrites with chaining

Setting `chain_rule: true` on a rule causes Bifrost to re-evaluate the full scope chain with the new provider/model as the new context. This lets you build layered alias resolution where a global rule establishes provider intent and a VK-scoped rule applies the final key selection.

**Scenario:** All clients send `model: "best-model"`. Premium VKs should get `gpt-5` via a high-tier key; standard VKs should get `gpt-4.1` via a lower-tier key.

**Rule 1 - Global scope (`chain_rule: true`):**

```json theme={null}
{
  "name": "resolve-best-model-provider",
  "cel_expression": "model == 'best-model'",
  "targets": [
    { "provider": "openai", "model": "best-model", "weight": 1.0 }
  ],
  "scope": "global",
  "chain_rule": true
}
```

This establishes that `best-model` resolves to OpenAI and re-evaluates the scope chain with `provider="openai", model="best-model"`.

**Rule 2a - VK scope on `premium-vk` (`chain_rule: false`):**

```json theme={null}
{
  "name": "premium-model-selection",
  "cel_expression": "provider == 'openai' && model == 'best-model'",
  "targets": [
    { "provider": "openai", "model": "gpt-5", "weight": 1.0 }
  ],
  "scope": "virtual_key",
  "scope_id": "premium-vk"
}
```

**Rule 2b - VK scope on `standard-vk` (`chain_rule: false`):**

```json theme={null}
{
  "name": "standard-model-selection",
  "cel_expression": "provider == 'openai' && model == 'best-model'",
  "targets": [
    { "provider": "openai", "model": "gpt-4.1", "weight": 1.0 }
  ],
  "scope": "virtual_key",
  "scope_id": "standard-vk"
}
```

**What happens for a `premium-vk` request:**

```
model="best-model" via premium-vk
  ↓ Rule 1 (global, chain_rule: true)
provider="openai", model="best-model" - re-evaluate scope chain
  ↓ Rule 2a (premium-vk scope, chain_rule: false)
provider="openai", model="gpt-5" - done
OpenAI receives model="gpt-5"
```

**What happens for a `standard-vk` request:**

```
model="best-model" via standard-vk
  ↓ Rule 1 (global, chain_rule: true)
provider="openai", model="best-model" - re-evaluate scope chain
  ↓ Rule 2b (standard-vk scope, chain_rule: false)
provider="openai", model="gpt-4.1" - done
OpenAI receives model="gpt-4.1"
```

Each step in the chain can change provider, model, or both. Cycle detection prevents infinite loops.

See the [Routing Rules](/providers/routing-rules) documentation for the full CEL expression reference, priority configuration, and chaining details.

***

## Advanced: Combining Both Layers

Static and dynamic aliasing compose naturally - routing rules fire first (at the HTTP layer), then key-level aliases resolve second (inside the inference worker, after key selection). This lets you separate concerns across two distinct layers:

* **Routing rules** decide *which provider* and *which key tier* to use, based on who is making the request
* **Key aliases** handle *the final model identifier* forwarded to the provider

### Example

**Setup:** Two OpenAI keys with different tiers, each with their own `best-model` alias:

```json theme={null}
{
  "providers": {
    "openai": {
      "keys": [
        {
          "id": "high-tier-key",
          "value": "env.OPENAI_HIGH_TIER_KEY",
          "models": ["*"],
          "aliases": { "best-model": "gpt-5" }
        },
        {
          "id": "low-tier-key",
          "value": "env.OPENAI_LOW_TIER_KEY",
          "models": ["*"],
          "aliases": { "best-model": "gpt-4o" }
        }
      ]
    },
    "anthropic": {
      "keys": [
        {
          "id": "anthropic-key",
          "value": "env.ANTHROPIC_KEY",
          "models": ["*"],
          "aliases": { "best-model": "claude-3-5-sonnet-20241022" }
        }
      ]
    }
  }
}
```

**Routing rules:** Two team-scoped rules handle provider selection, and two VK-scoped rules handle key tier selection.

```json theme={null}
[
  {
    "name": "tech-team-provider",
    "cel_expression": "model == 'best-model'",
    "targets": [{ "provider": "openai", "model": "best-model", "weight": 1.0 }],
    "scope": "team",
    "scope_id": "tech-team",
    "chain_rule": true
  },
  {
    "name": "ml-team-provider",
    "cel_expression": "model == 'best-model'",
    "targets": [{ "provider": "anthropic", "model": "best-model", "weight": 1.0 }],
    "scope": "team",
    "scope_id": "ml-team",
    "chain_rule": true
  },
  {
    "name": "premium-vk-key-selection",
    "cel_expression": "provider == 'openai' && model == 'best-model'",
    "targets": [{ "provider": "openai", "model": "best-model", "key_id": "high-tier-key", "weight": 1.0 }],
    "scope": "virtual_key",
    "scope_id": "premium-vk"
  },
  {
    "name": "standard-vk-key-selection",
    "cel_expression": "provider == 'openai' && model == 'best-model'",
    "targets": [{ "provider": "openai", "model": "best-model", "key_id": "low-tier-key", "weight": 1.0 }],
    "scope": "virtual_key",
    "scope_id": "standard-vk"
  }
]
```

**Resolution paths:**

```
tech-team + premium-vk → model="best-model"
  ↓ Team rule: provider="openai", model="best-model" (chain)
  ↓ VK rule: key=high-tier-key
  ↓ Alias: "best-model" → "gpt-5"
  → OpenAI receives model="gpt-5"

tech-team + standard-vk → model="best-model"
  ↓ Team rule: provider="openai", model="best-model" (chain)
  ↓ VK rule: key=low-tier-key
  ↓ Alias: "best-model" → "gpt-4o"
  → OpenAI receives model="gpt-4o"

ml-team → model="best-model"
  ↓ Team rule: provider="anthropic", model="best-model" (chain)
  ↓ No VK rule matches anthropic - chain terminates
  ↓ Alias: "best-model" → "claude-3-5-sonnet-20241022"
  → Anthropic receives model="claude-3-5-sonnet-20241022"
```

**Response `extra_fields.routing_info` for tech-team + premium-vk:**

```json theme={null}
{
  "routing_info": {
    "provider": "openai",
    "model": "best-model",
    "key": "high-tier-key",
    "resolved_key_alias": {
      "model_id": "gpt-5"
    }
  }
}
```

`routing_info.model` is what the client sent (after any routing rule rewrites). `routing_info.resolved_key_alias.model_id` is the final identifier that reached the provider API - after both routing and key-level alias resolution. When no key-level alias matches, `resolved_key_alias` is omitted and the wire model equals `routing_info.model`.
