Skip to content

LLM Gateway Routing

Document ID: LLM-003
File Path: docs/05-llm-gateway/routing.md
Version: 1.0.0
Status: Draft
Owner: AI Platform Team
Last Updated: 2026-06-27


This document defines how the LLM Gateway selects a concrete provider and model for each request. Routing turns a capability-level request (e.g. “a chat model”) into a specific dispatch (e.g. anthropic / claude-opus-4-8).

Routing builds on the Provider SDK selection logic but adds fleet-wide concerns: tenant policy, live health, budgets, and quotas.


Request model_selector
Tenant / project routing policy
Model registry (capabilities, pricing, context window)
Live provider health (from Resilience Engine)
Current budget / quota state (from Token Manager)
Region / data-residency constraints

ModeBehavior
pinnedCaller specifies model; Gateway uses it (or fails over if down)
selectorCaller specifies capability/class/strategy; Gateway chooses
policyTenant policy fully dictates the model; caller hints ignored

Precedence: policy (if tenant enforces) → pinnedselector.


When in selector mode, the strategy field chooses how candidates are ranked:

StrategyOptimizes for
lowest_costCheapest model meeting the capability
lowest_latencyFastest historical p95
highest_qualityHighest configured quality score
highest_availabilityMost healthy provider right now
balancedWeighted blend of cost, latency, quality
round_robinEven distribution across candidates
stickySame model for a session/conversation

The default strategy is balanced. Weights are configurable per tenant.


model_selector.class lets callers request a tier without naming a model:

ClassIntent
frontierMost capable models
balancedGood capability/cost tradeoff
fastLow-latency, lower-cost models
embeddingEmbedding-optimized models
localOn-prem / self-hosted models only

Classes map to concrete models via the registry and tenant configuration, so a class can be re-pointed to newer models without changing caller code.


1. Filter by capability (must support requested capability)
2. Filter by class (if specified)
3. Filter by constraints (region, residency, local-only, allow/deny list)
4. Filter by health (drop providers with open circuit breakers)
5. Filter by budget (drop models that would exceed budget)
6. Rank by strategy (cost / latency / quality / balanced)
7. Select primary + ordered failover list

The output is a primary choice plus an ordered failover list, which the Resilience Engine walks on failure.


routing:
default_strategy: balanced
weights:
cost: 0.4
latency: 0.4
quality: 0.2
class_map:
frontier: [claude-opus-4-8, gpt-5]
balanced: [claude-sonnet-4-6, gpt-5-mini]
fast: [claude-haiku-4-5, gpt-5-mini]
allow_providers: [anthropic, openai, azure]
deny_models: []
region: us
data_residency: strict
local_only: false

Policies are validated and enforced via the Policy Engine. A tenant may forbid certain providers entirely (e.g. for data-residency reasons).


For multi-turn conversations, sticky routing keeps the same model across turns to preserve behavior consistency. Stickiness is keyed by conversation_id and stored in Redis with a TTL. If the sticky model becomes unhealthy, routing falls back to the normal pipeline and updates the sticky binding.


Before ranking, the Router asks the Token Manager for the remaining budget. Models whose estimated cost would exceed the remaining budget are filtered out. If no model fits, the request is rejected with budget_exceeded rather than silently downgraded — unless the tenant enables auto_downgrade, in which case the cheapest viable model is selected.


The Router consults live health signals maintained by the Resilience Engine:

  • Providers with an open circuit breaker are excluded.
  • Providers in half-open state are deprioritized but eligible.
  • Recent error rate and latency feed the availability and latency strategies.

Each routing decision records:

  • Candidate set and the chosen primary
  • Strategy and effective weights
  • Reason codes for any exclusions (health, budget, residency)
  • Number of failovers ultimately used

These appear in the response routing block (see Provider API §6) and in traces.


Cheapest chat model in-region:

{ "model_selector": { "capability": "chat", "strategy": "lowest_cost" } }

Frontier class, pinned with failover:

{ "model": "claude-opus-4-8", "model_selector": { "class": "frontier" } }

Local-only embeddings (data residency):

{ "model_selector": { "capability": "embeddings", "class": "local" } }



VersionDateDescription
1.0.02026-06-27Initial LLM Gateway Routing specification