Routing Profiles
The named bundle that decides which model a request gets when it names none -- its fields, its binding ladder, and how the rungs merge.
Routing Profiles
A routing profile is behaviour: which model, which provider order, which fallbacks, how much the gateway may rewrite. A guardrail is protection: who may use what, and how much.
They attach through the same ladder, but they resolve differently -- and that difference is the single most important thing to understand about profiles.
A guardrail resolution picks one whole guardrail, most specific wins. A profile resolution merges every applicable rung field by field, so an issued key can override one setting while inheriting the rest of its team's configuration.
The ladder
| Rung | Bound to |
|---|---|
| 1. Team default | The team, as a fallback for every principal without a more specific binding. |
| 2. Identity | A person. |
| 3. Issued key | One key. |
4. dz_router | One request. See Per-request override. |
Most specific wins per field. The merge happens in the control plane, because only it knows which identity owns a key -- and because one implementation of the precedence rule is the only way it stays one rule.
An owned key is treated as both itself and its owner, so a key belonging to a person inherits that person's identity rung as well as the team default.
The fields
Every field is three-valued: set, or absent meaning inherit.
| Field | Values | Notes |
|---|---|---|
| Default model | An author/slug id | Used when a request names no model. Absent means this rung configures no default. |
| Fallback models | An ordered list, at most 4 | Tried in order, only when the model above cannot be served. |
| Rank providers by | cost, latency, throughput | DevZero's own vocabulary, translated at the connector. |
| Preferred providers | An ordered list | Tried before any other eligible endpoint. |
| Allowed providers | A list | Only these may serve. Blank means no restriction. |
| Denied providers | A list | These never serve. A provider cannot be both allowed and denied. |
| Auto enabled | Yes / no / inherit | See Auto mode. |
| Auto cost/quality dial | 0-10 | 0 leans entirely on quality, 10 always takes the cheapest. When no rung sets one, the resolver supplies the midpoint, 5. 0 is a real value, not "unset". |
| Models auto may pick / may never pick | Patterns, at most 32 each | author/slug exactly, author/prefix*, author/*, or bare *. |
| Optimization | off, lossless, full | See below. Platform default is lossless. |
| Upstream | A connector id | Which upstream serves this scope. Absent means no preference. |
An empty list means inherit, not "explicitly none". There is deliberately no way to express "blank what my team configured" -- if you need a scope with no fallbacks under a team that has some, that is not expressible today.
The optimization setting
This decides how much the gateway may rewrite a scope's requests before forwarding them.
| Value | Meaning |
|---|---|
off | Clean passthrough. No transform runs and no recovery plumbing is injected, so the body reaching the upstream is the one you sent, beyond the connector's own routing translation. |
lossless | Only transforms that remove nothing. The platform default. |
full | Additionally permits the content-dropping ones. |
The setting only ever subtracts. full grants no new permission -- it
merely declines to withdraw one. Every existing gate still decides alone: the
installation-wide transform switch, the holdout arm, the regime's evidence
loop, and each transform's own rollout stage. There is no value here that
reaches machinery the platform is holding back.
An unconfigured scope, and a scope whose profile could not be resolved, both get
lossless. A value a gateway does not recognise degrades to the same default
rather than failing the request.
Because it lives on the profile, it reaches keyed traffic only. Subscription and OAuth coding traffic never resolves a profile, so no value of this setting can change its behaviour.
The upstream field is not a credential field
upstream says where the request egresses. Custody says whose money
pays, and it stays a property of the issued key.
A profile naming an upstream the installation has not enabled is refused with
502 unknown_upstream, with no silent substitution.
The control plane validates this field for shape only. It cannot see which connectors the gateway in front of your team has registered, so a typo is caught at request time rather than at save time.
What the resolver reports back
Alongside the merged fields, the resolution says where the default model came from -- the team default, an identity, or a key. That is what makes "why did I get this model?" answerable.
It also reports every profile that contributed, least specific first, and a version stamp taken from the newest contributor.
There are deliberately no per-field source labels for the four provider fields: they merge independently of each other, so a single source label would be a lie and four more would be noise.
Editing a profile
An update writes every field -- it is a full replace, not a patch. If you drive the API yourself, read-modify-write, or an omitted field is blanked.
How long an edit takes to reach traffic is bounded by the gateway's profile-freshness window. Two things make an edit safe mid-flight:
- The router pins its first decision per session, so a conversation already under way keeps its model.
- Nothing is ever substituted for a model a request named explicitly.
Archiving a profile is a soft delete.
On screen
The Profiles wizard has four zones:
- Name it, attach it. Every routing field starts as inherit.
- Default model and fallbacks. Blank means inherit from the rung above.
- Providers, auto, optimization. All inherit until touched. The copy states the important caveat in place: these are preferences we pass on, not guarantees -- the provider that actually served each request is recorded on it.
- What this profile will do. A pre-flight echo of the server's own rules.
A firing watch on the profile's scope surfaces as a marker inside the wizard.