Passthrough
When the client and the provider speak the same dialect, pistra
forwards the request body unmodified. The model field is read with a
gjson scan. If an alias applies, that one field is patched in place
with sjson, and credentials are swapped in the headers. One more patch
exists. A metered stream to an OpenAI-dialect provider gets
stream_options.include_usage set when the client left it out, so the
provider reports tokens. The usage chunk that produces is dropped
before it reaches the client (see metering). Every other
byte reaches the provider exactly as the client sent it.
The failure this avoids
Section titled “The failure this avoids”Providers add request and response fields constantly. A gateway that unmarshals into its own structs and re-serializes silently drops whatever its structs do not model.
That failure has a particular shape worth naming. It is not an error. No status code changes, no log line appears, nothing retries. The request succeeds, it just quietly does less than the client asked for, and the client has no way to tell. A new sampling parameter is ignored. A cache control block vanishes and the bill goes up. A field that arrived last Tuesday in a provider release is dropped until somebody upgrades the gateway. Anybody who finds out does so by noticing the output is worse.
Keeping the bytes intact removes the failure mode rather than reducing it. There is no list to maintain and no release to wait for, because the gateway never had an opinion about the fields it does not use.
It is also fast, which is not the argument
Section titled “It is also fast, which is not the argument”Passthrough costs about 7 µs of pistra’s own work on top of the HTTP hop, and unary translation measures within run-to-run noise of it. A full parse and re-serialize barely registers against a network hop. If speed were the argument, translation would be an equally good answer.
Fidelity is the argument. Speed is a side effect of not doing work, and worth having, but it is not why the design is this way.
What it costs
Section titled “What it costs”Passthrough means the gateway cannot normalize. A client sending an OpenAI request to an OpenAI provider gets that provider’s exact behaviour, including its quirks. Some gateways sell normalization as the feature. This one sells the opposite, and the fidelity guard exists to make the trade explicit rather than silent, see channels and fidelity.
Translation still runs when dialects differ. The translators are vendored from Envoy AI Gateway with a pinned-commit sync script, because a translation core is behavioural code that belongs to whoever maintains it upstream. Forking it means owning every provider quirk forever. Local patches carry an upstream PR link and are deleted when the PR merges.
Two dialect pairs are carried, and a dialect the gateway could translate is usually better reached through the provider’s own compatibility endpoint instead. See translation for which pairs exist, what each one drops, and why an available translator is not a reason to use one.
Where else the rule applies
Section titled “Where else the rule applies”- MCP requests are validated and policy-checked from a gjson read of the JSON-RPC envelope, then forwarded byte-identical. Redaction rewrites the matched argument and leaves the envelope alone, so the server still answers the call it was sent.
- A2A requests are read the same way, from the JSON-RPC envelope the binding shares with MCP, and forwarded byte-identical. Redaction rewrites the matched part in place, so the peer receives the message it was sent with one span changed. Bytes carried inline in a part are forwarded unread: a base64 blob is not text, and rewriting one would mean re-encoding a payload the gateway does not parse.
- WebSocket sessions are governed at the upgrade handshake and then tunneled verbatim. A passive frame decoder watches the server-to-client copy to meter usage, and if it ever desyncs it turns itself off rather than touch the session.
- Guardrail redaction rewrites exactly the matched span with sjson. A request with one card number in it reaches the provider byte-identical apart from those sixteen digits.
That last one is the same principle applied to a case where the gateway does have an opinion. Even then it changes as little as it can.