Skip to content

extract

Offload — lossy, reversible

Projects a large tool output down to what's relevant to the most recent user query; optionally an LLM writes the filter.

How it works

extract projects a large tool output down to what's relevant to the most recent user query. v1 ships the deterministic strategy: keep head/tail context, every line overlapping the query's keywords, and every line carrying an error word; collapse the gaps with . It stashes the original behind a <<cg:HASH>> marker.

The relevance signal is the full conversational context (the task in the first user turn + the most recent assistant/user turns), not just one trailing sentence — so it keeps what the agent actually needs on any agent/benchmark.

With code, a cheap LLM writes a Starlark filter run in a sandbox (no imports/IO, step + 2s limits). It sees the full tool output (bounded to ~32k chars) so it writes code specific to that content — deleting the exact irrelevant lines/records AND words/sentences/parts within lines — not a blind generic filter. It has regex helpers (re_sub/re_findall/re_split/re_match, RE2, pure-Go). Guarantee (default): deletion-only — the result is accepted only if it is an in-order character subsequence of the input (obtainable by deleting characters), so the model can trim anything but provably cannot fabricate, reorder, or reword; else it falls back to deterministic. JSON bodies are decoded and filtered structurally. rlm currently maps to code.

rewrite (opt-in, code only) drops the containment proof so the model may reword / summarize / rewrite freely (lossy, unverified — only sanity + strictly-smaller apply). Pair it with a non-full marker_mode. Default false keeps the verified deletion-only guarantee.

The LLM strategies (code/rlm) call a model chosen by model.source: incoming (default — reuse the proxied request's own model + key) or config (a dedicated cheap model set via CHEAP_MODEL* env / the gateway's CheapModel). When no model is available, extract degrades to its deterministic projection.

Gating + reuse (LLM strategies): a trigger decides whether to spend a model call — min_output_tokens (per tool output; folds in legacy min_tokens), min_request_tokens, min_messages — so code fires only on a large output in a large request, not every turn. A reduced output is cached per session by content hash, so the same output re-sent on a later turn reuses the prior compaction (no new model call, byte-identical result → prefix stays KV-cache stable).

Before → After

before:  <300-line API dump>   (query mentions "auth timeout")
after:   <head> … lines mentioning auth/timeout + any error lines … <tail>
         <<cg:…>> [full output: call context_guru_expand]

Lossiness

Lossy but reversible — the original is stashed and recovered via context_guru_expand / GET /expand. The default code guarantee is deletion-only (a verified character subsequence); rewrite mode is unverified and lossier.

Configuration

Key Default Meaning
min_tokens 300 Output floor before extraction runs.
head_lines / tail_lines 5 Context lines kept at start/end.
strategy deterministic deterministic | code | rlm (rlm maps to code).
model.source incoming LLM source for code/rlm: incoming (proxied model+key) or config (cheap model).
trigger Gates a model call: min_output_tokens, min_request_tokens, min_messages.
marker_mode How the recovery marker is emitted; pair a non-full mode with rewrite.
rewrite false Opt-in (code only): drop the containment proof for free rewording (lossy, unverified).

When it shines

Big query-focused MCP/API outputs, logs and file reads; structured JSON where a filter selects records precisely.

When it's inert

No user query, output below floor, request below trigger, projection not smaller, or (for code) no model available → deterministic.

See also: Components overview · Choose a preset