Routing transparency
Every response records which model actually served it. The routing_info object, field by field.
ModelBeat may serve your request with a different model than the one you named. That is the product. The corollary is an obligation: you can always establish which model actually answered, from the response itself, without asking us.
That record is extra_fields.routing_info, and it is present on every successful response.
"extra_fields": {
"request_type": "chat_completion",
"latency": 842,
"chunk_index": 0,
"routing_info": {
"provider": "bedrock",
"model": "claude-haiku-4-5",
"is_fallback": true,
"primary_provider": "bedrock",
"primary_model": "claude-sonnet-4-5"
}
}Read that as: you asked for bedrock/claude-sonnet-4-5, that target failed, and
bedrock/claude-haiku-4-5 served the request instead.
Fields
| Field | Meaning |
|---|---|
provider | The provider that served this attempt. |
model | The model name sent to that provider. This is what answered you. |
key | Name of the ModelBeat-side provider key used. Useful when diagnosing a provider-account issue with us. |
is_fallback | true when the primary target failed and a fallback served the request. |
primary_provider | The provider originally targeted. Present only when a fallback occurred. |
primary_model | The model originally targeted. Present only when a fallback occurred. |
resolved_key_alias | Present only when the model you named matched an alias on the serving key. Carries model_id (the wire identifier actually sent), and optionally model_name and model_family. |
Log the served model
If you keep one thing from this page: record routing_info.model alongside every
completion you store.
raw = client.chat.completions.with_raw_response.create(model="auto", messages=[...])
r = raw.parse()
# routing_info is a field the OpenAI client does not know about, so it arrives as a
# plain dict, so it is subscripted, not dotted. `r.extra_fields.routing_info` raises
# AttributeError.
routing = r.extra_fields["routing_info"]
log.info(
"completion served",
extra={
"requested_model": "auto",
"served_model": routing["model"],
"served_provider": routing["provider"],
"was_fallback": routing.get("is_fallback", False),
"request_id": raw.headers.get("x-request-id"),
},
)Two reasons this matters beyond curiosity:
- Debugging. Output quality changed and you cannot explain it? Check whether a fallback silently moved you to a different model.
- Compliance. If you operate under the EU AI Act or an equivalent regime, you are
likely required to know which model produced a given output.
routing_infois how you evidence that, per request, without trusting us to reconstruct it later.
Detecting fallbacks
routing = r.extra_fields["routing_info"]
# .get(), not [], for both: is_fallback may be absent, and primary_model is present
# ONLY on a fallback, so indexing it on a normal response raises KeyError.
if routing.get("is_fallback"):
log.warning(
"primary target unavailable: wanted %s, served by %s",
routing.get("primary_model"),
routing["model"],
)A fallback is not an error, because the request succeeded. A rising fallback rate is still worth an alert: it usually means a provider is degraded.
When your pinned model was overridden
A fallback is one way you can end up on a model you did not name. The other is a silent override. You pinned a model the router dropped, because it was retired, unrecognised, or not eligible for your account, and it served the request with something else.
That case sets a response header:
x-modelbeat-routing-notice: requested_ineligibleIt is present only when an override happened, and the value is a closed enum.
requested_ineligible is the only member today. Absence means your pin was honoured.
if raw.headers.get("x-modelbeat-routing-notice") == "requested_ineligible":
log.warning("pinned model was not eligible; served %s instead", routing["model"])routing_info.model still tells you what actually answered. The header exists so you can
distinguish "I asked for auto and got a choice" from "I pinned a model and did not get
it". Those are the same response body and very different facts.