docs/compression/COMPRESSION_GUIDE.md
Save 15-95% on eligible context automatically. For a quick overview, see the README Compression section.
OmniRoute implements a modular prompt compression pipeline that runs proactively before requests hit upstream providers. This means your token savings happen transparently — no changes needed to your workflow.
Client Request
→ Compression Strategy Selector
→ Combo override? → Use combo setting
→ Auto-trigger threshold? → Use auto mode
→ Default mode? → Use global setting
→ Off? → Skip compression
→ Selected Compression Mode
→ Off: No compression
→ Lite: Safe whitespace/formatting cleanup (~15%)
→ Standard: Caveman-speak filler removal (~30%)
→ Aggressive: History aging + summarization (~50%)
→ Ultra: Heuristic pruning + code-block thinning (~75%)
→ RTK: Command-aware terminal/tool-output filtering (60-90% upstream range)
→ Stacked: Ordered multi-engine pipeline, usually RTK then Caveman (78-95% eligible range)
→ Compressed Request → Provider
No compression applied. All messages pass through unchanged.
The safest mode — zero semantic change, only formatting cleanup:
| Technique | Description |
|---|---|
collapseWhitespace | Merge consecutive blank lines and trailing spaces |
dedupSystemPrompt | Remove duplicate system messages |
compressToolResults | Compress verbose tool/function outputs |
removeRedundantContent | Strip repeated instructions |
replaceImageUrls | Shorten base64 image data URIs |
Best for: Always-on usage, safety-critical workflows.
Inspired by Caveman — removes filler words and verbose phrasing while preserving meaning:
Best for: Daily coding workflows, cost-conscious teams.
Smart history management for long sessions:
tool_use + tool_result pairs stay consistentBest for: Extended debugging sessions, large codebases.
Maximum compression for token-critical scenarios:
Best for: When you're hitting context limits repeatedly.
RTK mode is optimized for verbose tool outputs that appear in coding-agent sessions:
git status, git diff, git log, test runners,
TypeScript/Vite/Webpack builds, ESLint/Biome/Prettier, npm audit/installs, Docker logs, infra
output, and generic shell outputopen-sse/services/compression/engines/rtk/filters/filters.toml files, with inline-test
validation and trust-gating for project filesBest for: Agent sessions with shell, build, test, git, grep, and file-output transcripts.
Stacked mode runs multiple compression engines in a deterministic order. The default pipeline is:
RTK -> Caveman
That order keeps terminal/tool output compact first, then applies Caveman semantic condensation to the remaining natural-language prompt. Stacked pipelines can be configured globally or through compression combos assigned to routing combos.
Best for: Mixed context with large tool logs plus human instructions or assistant summaries.
OmniRoute documents compression savings from two sources: upstream project benchmarks and OmniRoute's own engine composition.
| Source | Upstream README number used here |
|---|---|
| Caveman | ~75% fewer output tokens, 65% benchmark average output savings, 22-87% range, and ~46% input compression tool |
| RTK | 60-90% command-output savings; sample session ~118,000 -> ~23,900 tokens, or 79.7% saved (~80%) |
For overlapping tool/context payloads, the default OmniRoute combo stacks the engines:
RTK -> Caveman
The combined savings are multiplicative, not additive:
combined = 1 - (1 - RTK savings) * (1 - Caveman input savings)
average = 1 - (1 - 0.80) * (1 - 0.46) = 89.2%
range = 1 - (1 - 0.60..0.90) * (1 - 0.46) = 78.4-94.6%
That 78-95% number applies when both RTK and Caveman can reduce the same input/context payload.
Caveman response output mode is separate: when enabled, use Caveman's own output savings (65%
average, ~75% headline, 22-87% range). Total billing savings depend on your prompt/output mix.
The 15-95% headline range is real, but it only applies to redundant or verbose content — repeated
error lines, a build log that spams the same warning, an oversized grep/file-read dump. It does
not mean every request saves that much.
Verified empirically (tests/unit/compression/stacked-compression-tool-result-savings.test.ts): a
stacked (RTK + Caveman) run against an Anthropic-shape tool_result block containing 300 identical
error lines produced 95.93% token savings / 96.26% character savings — squarely in the advertised
range. But the same pipeline run against normal, non-redundant tool output (a clean grep match list,
a short file read, ordinary conversational text) correctly produces near-zero savings, because
there is nothing repetitive to remove and validateCompression() (validation.ts) refuses to ship a
rewrite that would drop or alter code blocks, URLs, headings, versions, or ALL-CAPS constant identifiers.
This is expected, safe behavior, not a bug: a coding session that mostly reads/greps clean files will see modest total savings even with compression fully enabled, while a session that hits a failing loop or a chatty linter will see the full 78-95% range on that traffic. Don't use a single session's low aggregate savings percentage as evidence compression is misconfigured — check whether the underlying tool output was actually redundant first.
Without compression: 47K tokens sent to LLM
With Lite: 40K tokens sent (15% saved — safe, always-on)
With Standard: 33K tokens sent (30% saved — caveman-speak rules)
With Aggressive: 24K tokens sent (50% saved — aging + summarization)
With Ultra: 12K tokens sent (75% saved — heuristic pruning)
With RTK: 19K-5K tokens sent (60-90% saved on command/tool output)
With Stacked: 10K-2.5K tokens sent (78-95% eligible RTK+Caveman range)
Navigate to Dashboard → Context & Cache:
In Dashboard → Context & Cache → Compression Combos, assign a compression combo to a routing
combo:
Combo: "free-tier-fallback"
Compression Combo: "coding-agent-stack"
Pipeline: RTK -> Caveman
Targets:
1. if/kimi-k2.7-code
2. if/qwen3.8-max-preview
This lets you use stacked compression on free/coding providers while keeping lite mode on paid subscriptions.
This "Per-Combo Override" assignment is a different control from the routing-combo compression
mode override (Default/Off/Lite/Standard/Aggressive/Ultra) — that override does not pick a named
compression-combo pipeline; it just sets the compressionMode field consulted by
resolveCompressionPlan. It can be set either on the combo card (Dashboard → Combos) or, since
#6760, per routing combo in the "Assign to routing" list on
Dashboard → Context & Cache → Compression Combos, right next to the pipeline-assignment checkbox
documented above. Both surfaces persist through the same PUT /api/combos/{id} endpoint.
Send the x-omniroute-compression request header to override the compression plan for a single
request. It has the highest precedence — it beats the routing-combo override, the active profile,
auto-trigger, and the panel Default. Unknown values are ignored (the request is never rejected) and
the global master switch still gates everything: when compression is off globally, the header cannot
turn it on. Values:
| Value | Effect |
|---|---|
off | No compression for this request. |
default | The panel-derived Default profile (ignores the active profile). |
engine:<id> | A single engine when enabled, e.g. engine:rtk. |
<combo> | A named combo, matched by name (case-insensitive) first, then by id. |
The applied plan is echoed back in the X-OmniRoute-Compression: <mode>; source=<source> response
header, where <source> is one of request-header, routing-override, active-profile,
auto-trigger, default, or off.
# Get compression settings
curl http://localhost:20128/api/settings/compression
# Update compression settings
curl -X PUT http://localhost:20128/api/settings/compression \
-H "Content-Type: application/json" \
-d '{"defaultMode":"stacked","autoTriggerMode":"stacked","autoTriggerTokens":32000}'
# Preview a specific RTK/stacked payload
curl -X POST http://localhost:20128/api/compression/preview \
-H "Content-Type: application/json" \
-d '{"mode":"rtk","messages":[{"role":"tool","content":"npm test output here"}]}'
# List RTK filter packs
curl http://localhost:20128/api/context/rtk/filters
# Test RTK directly with optional command metadata
curl -X POST http://localhost:20128/api/context/rtk/test \
-H "Content-Type: application/json" \
-d '{"command":"npm test","text":"FAIL tests/example.test.ts\nError: boom"}'
The compression engine always preserves:
RTK raw-output recovery redacts common API keys, bearer tokens, Slack tokens, AWS access keys, passwords, tokens, and secrets before anything is persisted.
Every compressed request includes stats in the server logs:
{
"originalTokens": 47200,
"compressedTokens": 40120,
"savingsPercent": 15.0,
"techniquesUsed": ["collapseWhitespace", "dedupSystemPrompt"],
"mode": "lite",
"engine": "caveman",
"compressionComboId": "coding-agent-stack",
"durationMs": 0.8,
"rtkRawOutputPointers": []
}
| Phase | Modes | Status |
|---|---|---|
| Phase 1 | Off, Lite | ✅ Shipped |
| Phase 2 | Standard, Aggressive, Ultra | ✅ Shipped |
| Phase 3 | RTK, Stacked, Compression Combos | ✅ Shipped |
| Phase 4 | Output Styles, SLM-tier Ultra, eval harness | ✅ Shipped |
| Phase 4C | Adaptive context-budget ("dial") — compute engine + API (contextBudget on PUT /api/settings/compression) | ✅ Shipped (API-configurable; dashboard controls not yet built, #7005) |
Standard mode compression rules are inspired by Caveman by JuliusBrussee (⭐ 51K+) — the viral "why use many token when few token do trick" project. Caveman reports ~75% fewer output tokens, 65% benchmark average output savings, a 22-87% output range, and a ~46% input-compression tool.
RTK mode is inspired by RTK - Rust Token Killer by RTK AI — the high-performance command-output compression project for terminal, build, test, git, and tool-output filtering. RTK reports 60-90% savings, with its README sample session showing ~80% saved.
Beyond the 7 standard modes, OmniRoute includes several advanced compression systems that work automatically based on context.
Some providers (like Anthropic with prompt caching) support prompt caching, which lets them cache parts of the prompt to reduce costs and latency. When caching is enabled, aggressive compression can actually hurt performance because it changes the cached tokens, invalidating the cache.
The cachingAware.ts module solves this by detecting caching context and
adjusting the compression strategy accordingly.
cache_control markersaggressive/ultra to standard for caching providersimport {
detectCachingContext,
getCacheAwareStrategy,
} from "@omniroute/open-sse/services/compression/cachingAware";
const body = {
model: "anthropic/claude-sonnet-4.5",
messages: [{ role: "user", content: "Hello" }],
cache_control: { type: "ephemeral" }, // ← Cache marker
};
const ctx = detectCachingContext(body, { provider: "anthropic" });
// → { hasCacheControl: true, provider: "anthropic", isCachingProvider: true }
const strategy = getCacheAwareStrategy("aggressive", ctx);
// → { strategy: "standard", skipSystemPrompt: true, deterministicOnly: true }
Cache-aware compression is always on — no configuration needed. It only kicks in when:
cache_control markersLong conversations accumulate many message turns, but older turns become less
relevant. The progressiveAging.ts module degrades messages by turn distance:
import { applyAging } from "@omniroute/open-sse/services/compression/progressiveAging";
const messages = [
{ role: "system", content: "You are a helpful assistant" },
{ role: "user", content: "What is 2+2?" },
{ role: "assistant", content: "4" },
// ... 50 more turns ...
];
const { messages: aged, saved } = applyAging(messages, {
verbatim: 3, // First 3 turns: verbatim
light: 8, // Turns 4-8: lite compression
moderate: 20, // Turns 9-20: caveman compression
// Turns 21+: heavy summarization
});
// saved = number of tokens saved
Progressive aging is always on for aggressive and ultra modes. It's
particularly effective for:
The outputMode.ts module injects system prompt instructions to make the
model itself produce compressed, terse output (a "caveman" style).
Instead of compressing the input, this mode adds a system prompt like:
"Reply in minimal words. Skip pleasantries. Use short sentences."
This works particularly well for:
Caveman output mode is opt-in — set it via the combo config:
{
"strategy": "auto",
"config": {
"auto": {
"outputMode": "caveman"
}
}
}
The toolResultCompressor.ts module provides 5 specialized compression strategies
for tool results (function calls, agent outputs, search results, etc.):
Tool result compression is always on when tool calls are present. No configuration needed.
The stacked mode runs multiple engines in sequence — usually RTK first (60-90% savings on tool output), then Caveman (30% additional savings on the remaining text). This achieves 78-95% total savings.
Input (1000 tokens)
→ RTK (command-aware filter) → 200 tokens
→ Caveman (filler removal) → 140 tokens
→ Output (140 tokens, 86% savings)
Use stacked mode for:
Configure via combo:
{
"strategy": "auto",
"config": {
"auto": {
"modePack": "stacked"
}
}
}
You can override the global compression mode per combo to fine-tune behavior for different use cases:
{
"id": "coding-combo",
"strategy": "priority",
"config": {
"auto": {
"weights": { "taskFit": 0.5 },
"modePack": "quality-first"
}
},
"compressionOverride": {
"mode": "aggressive",
"stackedPipelines": ["rtk", "caveman"],
"preserveToolDefinitions": true
}
}
This is useful for:
aggressive mode for long sessionslite mode for fast responsesstacked mode for max savingscache-aware mode for caching providers