Channels and fidelity
Route selection uses the provider, model, dialect, and capabilities in the request. A provider can expose several channels with different support levels.
Why per-provider routing stopped working
Section titled “Why per-provider routing stopped working”Providers now host each other’s dialects. Gemini serves an OpenAI-compatible endpoint. Azure serves one. Anthropic serves one, and says in its own documentation that it is not production-grade, because it drops strict tools, response formats, prompt caching and extended thinking, and returns empty usage details. Bedrock’s support varies per model.
The provider name alone is not enough. Select an endpoint and dialect that preserve the capabilities the request uses.
A channel is that answer: one way a provider is reachable, with a
dialect, a tier (native or provider_compat), an optional model gate,
and, for compat channels, an explicit list of what it preserves.
Preference order
Section titled “Preference order”- Native passthrough, the provider’s own dialect. Preserves everything by definition. A native channel is forbidden from declaring capabilities at all, because a list there would imply it was exhaustive.
- Provider-hosted compat, their compatibility endpoint. Preserves what it claims, and the claim is dated and cites the page it was read from.
- Vendored translation, ours, and last. Translation is a boundary feature, not the product identity. It is not a declared tier either. It rides a native channel when no channel matches the inbound dialect. Translation lists which pairs are carried and what each costs.
The guard
Section titled “The guard”Before a request is forwarded, pistra reads which capabilities it uses.
That read is a bytes.Contains prefilter, then a gjson structural
confirm, memoized, and never run on native traffic because there is
nothing to decide. If every channel that could serve it would drop
something it uses, on_fidelity_loss decides:
reject(default) refuses with a structured error naming every capability the channel costs, and citing the page the claim came from.allowforwards on the best candidate and counts the downgrade inpistra_channel_downgrade_total{provider,channel,cap,action}.
The refusal names every affected capability. You can fix the request in one pass instead of discovering losses through repeated retries.
Why claims are dated
Section titled “Why claims are dated”A capability claim is a fact about somebody else’s service, read off
their documentation or observed live on a particular day. It has an
expiry nobody tells you about. So a claim carries verified_at and
verified_by. GET /admin/v1/catalog/report shows every routable
channel with its provenance, and each routing decision records which
overlay’s claim it acted on as pistra.channel_origin.
The report records the claim, its source, and its verification date.
Where policy lives instead
Section titled “Where policy lives instead”Overlays carry facts. They cannot invent a capability, a dialect or a
translator pair, because those ship with code, a probe and a coverage
fixture. Policy, require_caps on a
profile, on_fidelity_loss, stays in your config, where you own it.
require_caps: [usage_details] is the one place the two meet. It pins
a budget-metered profile off any channel that hides cache and reasoning
token splits. allow never overrides it. A fidelity probe cannot see
what a profile requires, so anything a profile required is policy, not
a probe result.