Cache-aware, causally-pruned context compression for agentic runtimes — gated by a statistical non-inferiority test. Same potency, less volume.
Reproducible from the bundled multi-domain corpus
(distil bench / certify / verify) with an offline
heuristic tokenizer. Ratios are robust; absolute dollars depend on the tokenizer. No vanity metrics.
Most compressors optimize bytes. In an agent loop the money is somewhere else.
You re-send the growing context every turn. With prompt caching a cache read is ~10× cheaper than fresh input — so the dominant cost is cache misses, not context size. Distil keeps the prefix byte-stable and compresses only the volatile tail. Naive recompression sends fewer tokens yet costs more, because it rewrites the cached prefix every turn.
The eval engine isn't a ruler — it's a discovery engine. Remove a context block, replay, did any decision change? Blocks that never change a decision are provably free to drop: speculative retrievals, stale history. The measurement produces the compression policy.
A strategy ships only if a pre-registered TOST non-inferiority test certifies it. Lossless passes; quality-degrading compression is rejected.
$ distil savings --pricing claude-opus-4-8 strategy $ / run vs baseline cache hits ------------------------------------------------------------------------ baseline (no cache, no compress) 0.01524 0.0% 0 cache only 0.01115 26.8% 1,028 naive compress + cache 0.01691 -11.0% 0 ← busts cache distil (cache-aware lossless) 0.01019 33.1% 1,028 $ distil certify --strategy distil decision-equivalence match rate: 100.0% VERDICT: PASS (certified non-inferior) $ distil certify --strategy aggressive decision-equivalence match rate: 0.0% VERDICT: FAIL (would degrade quality — blocked)
A strategy isn't trustworthy because it works once. distil bench certifies
every domain — ops, coding, support, research, data, devops, finance — or it doesn't ship.
Apply the provably-safe ones everywhere; gate the rest on evidence.
Reconstructable transforms — JSON minify, reversible run-length encoding. Always on.
Decision-aware digest + a handle; the full original stays local and re-expands on demand.
Pruning & summarization allowed only at ratios the non-inferiority gate certifies.
| Capability | What it does | Loss profile |
|---|---|---|
| Priced cache-aware engine | Models the multi-turn loop and proves naive recompression busts the cache | — |
| Schema canonicalization | Recursively key-sorts JSON/tool payloads so the prefix is byte-stable | lossless |
| Volatile-field extraction | Lifts dates/UUIDs/JWTs out of the cached prefix so it stops churning | lossless · reversible |
| Reversible digest + handles | Originals stay local and re-expand on demand | reversible |
| Reject-if-bigger invariant | Never emits a block larger than its original | safety |
| Causal / counterfactual pruning | Ablation discovers context that never changes a decision | certified |
| TOST non-inferiority gate | A strategy ships only if it passes the quality contract | the moat |
| Savings ledger + leaderboard | Local-first, privacy-preserving cumulative savings | opt-in |
Point any base_url-honoring client at the proxy — Python, TypeScript, any language —
and get cache-aware lossless compression. See integrations →
The stdlib-only core makes the packaging clean: zero runtime deps, corpus bundled.
uvx --from distil-llm distil bench
pipx install distil-llm distil certify
brew install dshakes/tap/distil distil bench
docker build -t distil . docker run distil bench
make pyz python dist/distil.pyz bench
Needs Python 3.11+. Install isolated (pipx/uv/brew/Docker) — system pip install is blocked by PEP 668 on modern macOS/Linux. Node/other stacks: point your SDK baseURL at distil proxy.
from distil.adapters.anthropic import wrap client = wrap(anthropic.Anthropic()) # compresses + keeps the cache warm
--tokenizer anthropic and
--runner anthropic make it billing-grade against the real model.