Skip to main content

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 Aliasing

Static aliasing is available in Bifrost v1.5.0-prerelease2 and above.
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:
You can also add aliases via the provider keys API:
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.
Provider-specific overrides (only set on aliases whose owning key matches the provider; validation rejects mismatches):

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:
When no alias matches, resolved_key_alias is omitted and model carries the wire identifier directly.
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.

Dynamic Aliasing

Dynamic aliasing uses 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:
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

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

Example: alias with provider switch

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):
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):
Rule 2b - VK scope on standard-vk (chain_rule: false):
What happens for a premium-vk request:
What happens for a standard-vk request:
Each step in the chain can change provider, model, or both. Cycle detection prevents infinite loops. See the 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:
Routing rules: Two team-scoped rules handle provider selection, and two VK-scoped rules handle key tier selection.
Resolution paths:
Response extra_fields.routing_info for tech-team + premium-vk:
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.