Choose a preset¶
A preset is a named, ordered pipeline. Set it once (--preset / PRESET, or preset: in
YAML) and every explicit field you add overrides it. This guide maps workloads to presets and
names the caveats before you commit.
Presets are just defaults
A preset expands to a default pipeline: list. Explicit pipeline: / components: blocks
always win, so start from the closest preset and tune from there. See
Architecture.
Which preset?¶
| Your workload | Preset |
|---|---|
| Nothing — A/B baseline / passthrough control | off |
| Any traffic, want a guaranteed-safe win only | safe |
| General agent traffic, good default | balanced |
| Squeeze harder, tolerate LLM/structural offload | aggressive |
| Coding agent reading big source files | coding |
| MCP / list-endpoint JSON arrays | mcp |
| Long agentic sessions (SWE-bench-style, re-sent transcripts) | agent |
| One long transcript to compress, run standalone | summarize |
The presets¶
Every preset below is exactly the list in config/config.go;
per-component behavior is in Components.
off — []¶
No components. Passthrough. Use it as the A/B control when you measure savings — the baseline in Benchmarks is this preset.
safe — [format, cacheinject]¶
Two lossless Reformat components only: compact JSON
(format) and an Anthropic cache breakpoint (cacheinject). Nothing is ever dropped, so there is
nothing to expand.
- Fits: any traffic where you want a zero-risk win and no reversibility surface.
- Caveat:
cacheinject's savings are provider-side cache hits, invisible to/statstoken counts — it will show up undertop_passthrough. That's expected, not dead weight.
balanced — [format, dedup, failed_run, cmdfilter, cacheinject]¶
The default. Adds three cheap, high-precision offloaders: exact-dup removal (dedup), superseded
test/build runs (failed_run), and DSL command-log filtering (cmdfilter).
- Fits: general agent traffic; the safe everyday choice.
- Caveat:
cmdfilteronly fires when ≥1 filter is loaded and the output's first line matches one. Its builtins cover pytest / npm-install / make; author more with a custom DSL filter.
aggressive — [format, dedup, failed_run, cmdfilter, smartcrush, extract, cacheinject]¶
balanced plus JSON-array crushing (smartcrush) and query-relevance projection (extract).
- Fits: you want more savings and accept structural/LLM offload with expand recovery.
- Caveat:
extractwithstrategy: code/rlmspends a model call (gated by itstrigger); the defaultdeterministicstrategy is free. Keep the store on so the extra offloads stay recoverable.
coding — [format, skeleton, cmdfilter, cacheinject]¶
Swaps in skeleton, which tree-sitter-parses fenced code blocks and replaces function bodies with
{ … }, keeping signatures/imports/types.
- Fits: a coding agent that reads large source files but mostly needs the shape.
- Caveat:
skeletonis inert on unfenced file reads, unknown languages, or when the skeleton isn't smaller than the body.
mcp — [format, smartcrush, cacheinject]¶
Targets homogeneous JSON arrays (list endpoints, search hits): keep keep_first + keep_last
items plus any item carrying an error signal, drop the middle.
- Fits: MCP tools and REST list endpoints returning long uniform arrays.
- Caveat: inert on non-array output or arrays below
min_items.
agent — [format, dedup, failed_run, mask, extract, cacheinject]¶
Tuned for long agentic sessions (e.g. Claude Code on SWE-bench) where the dominant cost is the transcript of old tool outputs re-sent every turn.
- Fits: long-running agents with a growing transcript.
- Caveat:
maskis the biggest lever here — age-based GC of tool outputs older thankeep_recent. In the SWE-bench sweep it delivered ~27% mean content-token savings (up to 93.5% on a long session) with no reward loss (Benchmarks). Order matters: lossless first, then offload old-then-large, cache last.
summarize — [summarize]¶
One LLM component that collapses the middle of the transcript into a single
=== History Summary === message, keeping the head + last few turns.
- Fits: long agentic sessions where the stale middle is the token cost.
- Caveat: run it alone. It changes the message count and restructures the whole transcript,
so
apply.Bodyrebuilds the body — no other component's in-place edits can race that rebuild. It needs a model; with none it no-ops.
LLM presets cost model calls
aggressive (via extract code/rlm) and summarize call a model. Both are gated by a
trigger and reuse prior compactions per session, so they don't fire every turn. Pick the
model with model.source (incoming reuses the request's own model+key; config uses a
dedicated cheap model). See LLM components.