DEV Community

J. Gravelle
J. Gravelle

Posted on

You Don't Need an LLM to Route Agent Context: Regex Beats Classifiers by 45 Points

LLM agents burn a ridiculous number of tokens on redundancy: opening the same files again and again, trying a patch, failing, then wandering back through the repo like they’ve never seen it before.

A July 2026 paper, ContextSniper: AntTrail's Token-Efficient Code Memory for Repository-Level Program Repair, puts real numbers behind that waste. In repository-level repair, agents keep dragging in irrelevant code and logs. ContextSniper tackles that with a context layer built around tiered memory and an intention-aware context gate that filters low-value regions before they ever reach the model.

That gate alone cut tokens by 51.5% on one host agent and 38.9% on Claude Code, while submitted-resolution rates stayed basically in the same neighborhood.

The gate is the interesting part, because it is not tied to that paper’s exact system. It is a more general idea, and it is starting to show up across agent architectures.

At heart, the gate is just a classifier. Given a request, it has to decide what kind of retrieval will answer the question cheapest: symbol lookup, semantic search, graph impact, mutation prep, or something else.

That leads to the practical question the paper does not really answer:

Do you need another LLM call just to decide what context to retrieve?

We tested that directly.

Five ways agents get code into context

Before you can gate anything, you need a retrieval strategy. Most current systems fall into one of five rough families:

  • Grounded read-only retrieval: parse the code and return exact symbol source by name. Byte-precise, no synthesis.
  • Graph code intelligence: model calls, imports, entities, and dependencies as a graph, then traverse it.
  • Embedding / RAG search: use vector similarity over chunks.
  • Whole-repo packers: compress or dump the repo into the context window.
  • Mutate / execute runtimes: retrieve context, then modify or run code.

None of these is magic. Graphs are great for relationships, but they can drift away from source. RAG is useful, but fuzzy by design. Packers are simple, but expensive. Mutation runtimes are powerful, but they widen the blast radius.

The important point is that every approach still has to answer the same question:

What should I fetch for this request?

That decision is the gate.

The gate is where the real leverage is

An intention-aware gate looks at a request like:

  • “where is parse_config defined”
  • “how does caching work here”
  • “what breaks if I rename this”
  • “change the timeout to 60s”

Then it chooses the cheapest retrieval path that is likely to work.

That might be a symbol lookup. It might be semantic search. It might be a graph-impact query. It might be mutation prep.

ContextSniper uses a traceback / behavioral / stateful intent split, which is a useful framing. But it leaves an obvious engineering question for anyone building this kind of system:

How heavy does the gate actually need to be?

The default instinct is to reach for an LLM router, because “intent” sounds like a language-understanding problem.

We wanted to know whether that was true.

The setup

We used 140 hand-authored requests, balanced across seven dispatch classes:

  • symbol lookup
  • text search
  • semantic
  • graph impact
  • structure
  • stateful
  • mutate

The label space borrows from ContextSniper’s intent split. We ran five-fold stratified cross-validation and compared three cheap routing tiers:

  • heuristic: about 40 lines of regex over the request text
  • centroid: TF-IDF with nearest class mean
  • logreg: TF-IDF with a linear classifier

The result

Tier What Accuracy Macro-F1
heuristic ~40 lines of regex 94.3% 0.945
centroid TF-IDF nearest-class 47.9% 0.474
logreg TF-IDF linear 48.6% 0.484

The regex tier won by about 45 points.

The two learned models were not terrible for a seven-class problem, but they were nowhere close. Same corpus, same folds, same labels, and the dumb little ruleset walked off with the trophy.

That was surprising enough that we dug into why.

Intent lives in shape, not word frequency

Bag-of-words models care about which words appear and how often. But for these requests, intent usually lives somewhere else. It lives in the shape of the request.

“Where is X defined” and “how does caching work” do not share much useful vocabulary, but both are almost embarrassingly easy to classify from structure alone.

A camelCase or snake_case token usually means symbol lookup.

A leading “how does” or “why” usually means behavioral or semantic exploration.

“What breaks if I” usually means impact analysis.

“Change,” “rename,” or “set ... to” usually means mutation.

A quoted literal or bare number often means text search.

Regex sees those shapes directly.

TF-IDF mostly throws them away, then gets punished again by the tiny dataset. With roughly 16 examples per class, a sparse linear model does not have much signal left to recover.

In this experiment, the cheap learned tier was not merely unnecessary. It was worse than the rules.

The 3% that fights back

Four of the 140 requests resisted both cheap tiers:

Example Request Why it resists cheap classification
what does the parse method look like symbol lookup, but no definitional keyword
find where the timeout value 30000 appears text search phrased like a location query
show me how caching is implemented semantic vs symbol, genuinely ambiguous
what modules depend on the core package graph question that reads structural

These are not really rule failures. They are ambiguity.

And the fix for ambiguity is not always “ask a bigger model.” Often, the fix is to probe reality.

Try the cheapest grounded lookup first. If it misses, fall back to semantic search. That resolves the uncertainty by checking the code, not by paying a language model to make a better guess.

What to build

For an intention-aware gate, the order should be:

  1. Start with regex. It handles most traffic, costs nothing, behaves deterministically, and never rate-limits.
  2. Add probe-and-fallback for the ambiguous cases. When a request could mean two things, cheaply test the first interpretation before escalating.
  3. Use a model call only for what survives both. In our corpus, that was about 3% of requests, and even those had cheaper ways out.

The expensive tier should be the last resort, not the front door.

That is the opposite of the usual reflex, which is to reach for an LLM router because the problem sounds like “understanding.” In practice, a lot of the signal is sitting right there in the punctuation, casing, verbs, and shape of the request.

Honest caveats

Two points that really matter:

First, our corpus and rules share an author. So 94.3% is an in-distribution number. It proves that hand-written rules can separate hand-written requests, which is not exactly a thunderclap from Mount Science.

The number is less important than the shape of the result. Real validation needs real request logs. I would happily rerun this on a public trace.

Second, ContextSniper is convergent evidence, not an endorsement of any specific tool. It is a separate group arriving at the same architecture from the repair-agent direction: tiered memory plus an intent gate, large token savings, and resolution held roughly flat.

To be precise about “roughly,” their official validation reports 24.0% of issues resolved with the gate versus 26.0% for the baseline, which they describe as comparable while also noting a validation-error imbalance.

The important signal is that two independent lines of work are landing in the same place: context gates matter. The exact accuracy of one regex tier is not the point.

Where this leaves the taxonomy

The gate sits above whatever retrieval family you use.

In our stack, it routes into a grounded read-only retriever, jCodeMunch, because byte-exact symbol source is often the cheapest correct answer to the most common kind of request.

But the routing lesson is not specific to jCodeMunch. It applies whether you retrieve by symbol, graph, vector, or whole-repo packing.

The thing deciding what to retrieve should be cheap first, deterministic second, shape-aware third, and “smart” only when it has no cheaper option left.

For the full map of the five families and where different tools fit, there is a running field guide to code-context tools.

Links: ContextSniper (arXiv 2607.01916) · field guide to code-context tools · jCodeMunch

Top comments (0)