LowRouterBeta

Routing

Every request goes through the router. For an explicit model the router’s job is small — resolve it to a healthy upstream that serves it. For an auto-routed model it also chooses which provider and region serve it. This page describes both.

Three modes

  • Explicit model. You send a full model ID (see available models); the router resolves it to the provider and region encoded in that ID and sends it upstream.
  • Auto-routed model (auto/<creator>/<model>). You name the model; the router picks which provider serves it and from where. See auto-routing a model below.
  • Alias (alias/<name>). You send the name of one of your account’s model aliases; the router resolves it to the stored route and continues exactly like an explicit model. The alias/ prefix (like auto/) is a reserved namespace — no provider can ever be named that.

The model field is required. There is no per-request route object and no separate routing parameters — everything the router needs comes from the model ID you send and the model catalogue. To constrain provider or region, encode it in the model ID (below).

lowrouter/auto has been removed. It used to let the router pick the model as well as the route, ranked on carbon per token — which meant the greenest answer was always the smallest model in the catalogue, a capability downgrade you had not asked for and could not see. Choosing the model is your decision; choosing the route is ours. Requests naming it now return 400 and point here.

Auto-routing a model

The same model is often served by several providers, in several regions, at different prices and on very different electricity grids. auto/<creator>/<model> lets you name the model and leave that choice to the router:

Text
auto/mistralai/mistral-large-2512

You get the same canonical model — same weights, same output. Only the route is decided for you. Auto-routed IDs appear in GET /v1/models alongside the explicit ones (see available models) for every model served by more than one route, so they are selectable in any OpenAI-compatible client. They are omitted when you filter that listing with ?jurisdiction= — auto ranking is global and cannot promise to stay inside a facet, so a filtered catalogue lists only explicit IDs, which name their provider and region outright.

The priority order

The order is fixed and identical for every account — there is no policy to select. Each step only breaks ties left by the previous one:

  1. EU-sovereign routes first. A route counts as sovereign only when both halves hold: the provider is an EU-sovereign company and the serving region is in the EU/EEA. An EU-sovereign company serving from a US datacenter does not qualify, and neither does a US-controlled provider serving from Frankfurt.
  2. Lowest grid carbon intensity. A region whose grid intensity we have no data for ranks below every region we do — an unknown is treated as unknown, never as the greenest.
  3. Lowest price. Because carbon is decided first, two identically-priced routes can never resolve to the dirtier grid. A route with no published price ranks below every priced one.
  4. Round-robin across whatever is still tied.

Routes a provider has taken out of service are excluded outright, at every step.

Sovereignty here is a preference, not a guarantee

If a model has no sovereign route at all, an auto request does not fail — it falls through to the greenest, then cheapest route available anywhere. auto/anthropic/claude-sonnet-5 routes, to a non-EU provider.

The response is what keeps this honest. lowrouter_metadata.eu_sovereign tells you whether the route you got was sovereign, alongside provider and region, and the model field carries the fully resolved four-segment ID. If you need sovereignty as a hard constraint rather than a preference, use an explicit ID — it fails loudly instead of falling back outside your constraint.

lowrouter_metadata.routing_reason names the step that decided: eu_sovereign_preferred, lowest_carbon_intensity, lowest_cost, round_robin, or only_route when the model has just one route.

What auto-routing does not do

  • It never changes which model you get — that is your choice, and the whole point of naming it.
  • It does not score latency or answer quality.
  • It does not consult your aliases: auto/ is its own namespace and always applies the order above.
  • A version shorthand still works — auto/mistralai/mistral-large resolves to the latest version — but a region does not: there is no 4th segment to write, because choosing the region is the point.

Pinning a provider or region

Region and provider are part of the model ID, not a separate field. The public ID has the form {provider}/{creator}/{model}[/{locode}]:

GoalHow
Pin the providerUse an explicit model ID — the first segment is the provider, e.g. vertex/anthropic/claude-opus-4.6.
Pin the regionAppend a UN/LOCODE as the 4th segment, e.g. vertex/anthropic/claude-opus-4.6/sg-sin.
Default regionOmit the 4th segment; see how IDs resolve below.

If you request a region a model isn’t served in, the request is rejected rather than silently served elsewhere — the region you pin is the region you get.

How IDs resolve

You do not have to write the full four-segment ID. What you leave out is filled in from the catalogue, most-specific first, and the response always tells you what you actually got.

You sendWhat happens
mistral/mistralai/mistral-large-2512/euUsed exactly as written.
mistral/mistralai/mistral-large-2512Region defaulted — resolves to /eu.
mistral/mistralai/mistral-largeVersion and region defaulted — resolves to mistral-large-2512/eu.
anthropic/anthropic/claude-sonnetResolves to the latest sonnet at /global.

Missing version resolves to the most recent version of that same model. The version is the only thing that moves: claude-sonnet resolves to the newest sonnet, never to an opus, and mistral-large never to a mistral-small. A shorthand that would be ambiguous between genuinely different models — openai/openai/gpt-oss, where gpt-oss-20b and gpt-oss-120b are separate models rather than two versions of one — is rejected, not guessed.

Missing region resolves to global when the model has a global endpoint. When it doesn’t, it resolves to the model’s only region, or, where several exist, to the lowest-carbon one. A region whose grid intensity we don’t have data for is never chosen over one we do — an unknown is treated as unknown, not as zero.

The response’s model field always carries the fully resolved four-segment ID, so a request is reproducible from its own response — copy it back and you pin exactly what ran. lowrouter_metadata.region reports the region independently.

Pinning still fails loudly

Resolution only ever fills in what you left out. It never overrides what you wrote:

  • A version that doesn’t exist is an error, not a nudge to the nearest one. mistral/mistralai/mistral-large-9999404.
  • A region the model isn’t served in is an error, not a reroute. mistral/mistralai/mistral-large-2512/us-iad503.
  • An explicit /global on a model with no global endpoint is an error, not a silent switch to a regional row.

That asymmetry is deliberate. Defaults exist so the IDs in our own docs and model list are callable as printed; pins exist so that when you name a version or a jurisdiction, the thing you named is the thing that ran. Aliases are stricter still: an alias target must be a full, concrete {provider}/{creator}/{model}/{locode} triple, so a stored route can never drift under you.

Worked scenario: EU-only first, lowest carbon second

Say a data-residency commitment requires EU inference, and within that constraint you want the lowest carbon available. The order matters: sovereignty is a constraint, carbon is an optimisation, and the two are handled by different mechanisms.

  1. Encode the constraint. Filter the providers page to EU providers, then compare per-token carbon across the models that remain in the catalogue.
  2. Pin the winner with an explicit ID, e.g. mistral/mistralai/mistral-large-2512/eu — or better, point an alias at it, so you can re-run the comparison next quarter and repoint without touching client code.
  3. Verify, don’t trust. Check lowrouter_metadata.region on the responses; the pin is proven on every call.

Note what you did not do: ask the router for “EU only”. Auto-routing does not treat a jurisdiction as a hard constraint. auto/<creator>/<model> does prefer EU-sovereign routes above everything else, and reports whether it got one — but when a model has no sovereign route it falls back rather than failing, so it is an optimisation, not a commitment. Per-key jurisdiction restrictions are coming; until then the honest tool for a hard constraint is the explicit ID, which fails loudly rather than falling back outside it.

What happens on failure

LowRouter does not silently move your request to a different provider: an explicit ID is a pin, and an auto-routed request commits to the winner of the ranking. If that route fails, the request returns 503 naming the provider that failed rather than reporting a different one you never asked for. Substituting a provider would bill against another pricing row and serve from another jurisdiction than the ID promised.

Which providers were attempted is reported on the response in lowrouter_metadata.providers_attempted, alongside lowrouter_metadata.fallback_occurred.

What the router does not do

  • It does not choose the model — that is what naming it is for.
  • It does not benchmark output quality — it optimises for sovereignty, then carbon, then cost, not “is the answer good”.
  • It does not accept a per-request route object or a prefer_low_carbon flag. Low carbon is already ranked ahead of price, so there is nothing to opt into.