Compression tiers
A safety taxonomy for prompt compression — off by default, evidence-qualified transforms, honest savings.
ultrarouter can compress prompts on the hot path to cut token cost. Any change to model-visible tokens can change an LLM result, so ultrarouter never calls prompt compression "lossless" — the word lossless is reserved for byte-preserving transport/storage. Compression is classified by a safety taxonomy, and it is fail-safe: any error dispatches the original, uncompressed payload.
Set compression on the request or per call type: "off" (default),
"semantic_safe", or "adaptive".
The safety taxonomy
| Tier | What it does | When it runs |
|---|---|---|
off | No model-visible rewrite — byte-identical dispatch. The default. | Always available; the initial mode for an unseen call type. |
semantic_safe | Deterministic, bounded transforms: whitespace normalization + exact-context dedupe. Code and JSON are preserved byte-for-byte. | Opt-in, and (going forward) earned per call type by shadow evidence. |
adaptive | History windowing, boilerplate removal, and extractive pruning under a strict safety net. Deletes model-visible information. | Opt-in, always guarded, canaried and rollback-protected. |
A new workspace performs no model-visible rewrite until a transform has earned
activation for its call type. History deletion and substring boilerplate removal are
never in a "safe without evidence" tier — they are always adaptive.
The ur.compression block on each response reports the applied tier and its provenance:
{ "applied": "off", "source": "off" }{ "applied": "semantic_safe", "source": "unqualified-legacy", "deprecated_alias": "lossless",
"tokens_saved": 84, "est_saved_usd": 0.0002, "savings_basis": "provider_reported" }source is unqualified-legacy when a tier ran without shadow qualification (the
qualification engine is being built); deprecated_alias is set when the request used a
legacy value.
Legacy values
The legacy compression: "lossless" and compression: "auto" values remain parseable
during migration, but they are not semantic-identity guarantees:
"lossless"maps tosemantic_safeand emits a deprecation marker."auto"maps toadaptive.
Prefer the taxonomy values in new code.
Adaptive tier (opt-in, guarded)
compression: "adaptive" prunes eligible context under a strict safety net. It never
fails a request — every gate below falls back to the semantic_safe subset:
- Never-touch rules — code, JSON/tables, numbers, dates, IDs, URLs, emails, currency, citations, and named entities are pinned and survive byte-identical.
- Verbatim-intent guard — if the instructions ask to quote/cite/translate exactly (en/pt/es), pruning is bypassed for all eligible context.
- Verify-and-retry — after an adaptive response, quotes, citations, and JSON schemas are validated against the original context; on any failure the request is retried once with the uncompressed payload (a quality retry, not a model switch).
- 40 ms budget — the pruner races a timeout; an overrun falls back to
semantic_safe. - Circuit breaker — a per-call-type breaker auto-disables adaptive if the verify failure rate exceeds a small threshold over 24 hours.
Only reference_context and history are eligible for pruning; everything else is
protected.
Honest savings
Compression savings are based on provider-reported / invoice-reconciled usage.
Estimated removed tokens (a chars/4 diagnostic) are shown as a diagnostic only. The
ur.compression.savings_basis field says which:
provider_reported— the request's usage was provider-reported and a real savings line was recorded in the savings ledger.estimated_diagnostic— the figure is a diagnostic; no ledger line was recorded.
Configuring compression
Per call type you can set the adaptive prune ratio (max_quality_risk),
keep_last_n_turns, a no_compress_fields list (JSONPath messages.<i>), and the
whitespace/dedupe toggles.
Segment hints (ur.segments)
You can label how the gateway segments a request by attaching ur.segments to the body.
Each hint names a message index and its kind
(system_instructions · user_question · reference_context · few_shot_examples ·
tool_results · history). A hint overrides the gateway's role/delimiter heuristics for
that message; only reference_context and history are eligible for the adaptive tier —
every other kind explicitly protects the message from any model-visible rewrite.
{
"messages": [
{ "role": "system", "content": "..." },
{ "role": "user", "content": "<retrieved passage>\n\nQuestion: ..." }
],
"ur": {
"segments": [{ "index": 1, "kind": "reference_context", "start": 0, "end": 512 }]
}
}The optional start / end character offsets refine a hint to a span within the
message: the gateway splits the message at the boundary and applies the kind (and its
eligibility) to [start, end) only — everything outside the span stays protected. Omit the
offsets for a whole-message label (fully backward compatible). Span offsets never change how
a request is grouped into a call type.
These offsets are raw character offsets into your request's own message content. A span boundary that would split an emoji / surrogate pair is snapped outward toward protection, and an invalid, inverted, or out-of-range span fails closed: the hint is ignored, the message keeps its default classification (no content becomes lossy-eligible on a bad offset), and the request still succeeds. The learned segment maps described below use a different coordinate system (masked-template offsets), so a client must never copy a learned map's offsets into a request span.
Learned segments are suggestions, never automatic
ultrarouter observes how your prompts decompose across many requests and learns which
segments are byte-stable (a cacheable instruction prefix) versus which vary per call. These
learned segment maps are evidence and suggestions only — surfaced in your
audit readiness view. A learned hint is never applied to
compression automatically: applying a model-visible transform without your consent would
break the safety contract above. The only way a learned suggestion becomes an active
declaration is an explicit, audited action you take to accept it, which writes whole-message
declared hints for that call type. (Accepting is whole-message only — the learned map is in
masked-template coordinates, which do not translate to raw request offsets, so declared span
hints are intentionally not supported; use a per-request ur.segments span if you need one.)
An accepted declaration only applies to a request whose message count matches the learned
shape, so a positional hint never misfires when your prompt shape changes. Learning is
passive; applying is always your call.