Performance

This page publishes what we have measured about speed and answer quality, the arithmetic that turns those measurements into a claim, and the places where we do not yet have a number. Every figure names the run that produced it.

Retrieval quality gain

+71 pts

strict correctness, base 8B, 100 development questions

Less text to read

4.1×

median context vs shell search over the same corpus

Gold source found

28/29

shell search 26/29

Answer, end to end

19.5s

median round trip on the deployed service, 150 questions · 95th percentile 27.7s

The decision this evidence supports. Retrieval is the component doing the work. It moved strict correctness from 15% to 86% on the development matrix. Fine-tuning did not beat the base model in either mode and is not the default offer.

The deployed system, measured. On August 4 we put 150 development questions through the system a customer would use. It scored 107 strictly correct under the first grading rubric and 100 under the second. Neither rubric is validated. It answered 8.7% of questions wrongly under the first and 16% under the second. It declined to answer only 4 questions, because the control that makes it decline unsupported questions is not switched on. The median answer took 19.5 seconds round trip.

An earlier local run. On August 3 we stopped modelling the agent comparison and ran it, on a local development setup rather than the deployed system. Thirty questions went through a real LLM-driven file-search loop and through retrieval, with the same answer model on both sides. Retrieval was faster on every single pair, found the gold document on 29 of 30 questions against the agent's 20, and cost less. Answer correctness was statistically tied. The details are in the sections below.

The things to fix. The deployed service is slow: the median service time is 9.7s and the median round trip is 19.5s. The re-ranking stage averaged 1.6s of that. It cannot simply be switched off, because it also supplies the signal for declining unsupported questions. And the control that uses that signal is not yet switched on.

What this is not. No number here comes from a sealed benchmark. These are visible development sets and live smoke runs. They are honest about direction and not yet strong enough to be an acceptance claim.

Newest evidence

The deployed system

This is the only run on this page that answered through the system a customer would use. The questions are a visible development set, not a sealed test. Graded by an automated judge that has not been validated, under two versions of the rubric.

Strictly correct, rubric 1

107/150

same answers, first rubric

Strictly correct, rubric 2

100/150

same answers, second rubric

Wrong answers

8.7% / 16%

share of all questions, rubric 1 / rubric 2

Declined to answer

4/150

the decline control is switched off

No request failed in 150. The right document was cited on 122 of 150 questions. Service time was 9.7s median and 13.8s at the 95th percentile. The full round trip was 19.5s median and 27.7s at the 95th percentile, with a slowest request of 29.9s. Source: docs/verification/2026-08-04-eval150-deployed-system.md.

Plain language

The short version

What you get

A question goes in and a source-backed answer comes out. On the deployed system the median is about 20 seconds round trip. It cited the right document on 122 of 150 development questions. In an earlier local test it handed the model 4.1× less text than a shell search that reads whole files. A real search agent reads less text than that, but pays for it in extra model turns. When we ran one locally, it was slower on every single question and found the right document a third less often. The system does not yet reliably decline when the answer is not in your documents. The control for that exists and is switched off.

What it costs

Time. Searching adds seconds to every answer, and the deployed service is slow today: 9.7s median service time. The re-ranking stage averaged 1.6s of that. Cost per answer in GPU-seconds is not yet measured, and we say so rather than estimating it.

Why not just let an agent grep the folder?

It is a fair question and we measured it rather than arguing about it. Grep is genuinely faster than our retrieval call — about 18× faster on the search step alone. But a shell-search agent has to think three times to get one answer: pick search terms, pick files, then answer. Generating text is the slow part of a language model, roughly 485× slower than reading it. So the extra thinking costs far more than the extra reading, and the two approaches finish within a fifth of a second of each other today.

That near-tie comes from the August 2 development run. The deployed service measured later is much slower than that run, so the speed comparison has not been shown to hold on the production path. The arithmetic for the August 2 run is in bench notes.

High level

Where the time goes

A user waits for two things: finding the evidence, then writing the answer. Both arms below run the same model on the same deployment.

Question in, finished answer out

Median over 29 questions · qwen3-4b-tuned — Qwen3-4B base + LoRA adapter on Modal L4

Search stageModel generation
0s2s4s6s8sCorpusAegis retrievalCorpusAegis retrieval — search 4.40sCorpusAegis retrieval — generation 4.17s8.57sShell search agentShell search agent — search 0.24sShell search agent — generation 8.49s8.73s
Light segment is the search stage; dark segment is model generation. The shell arm generates three times.

The reranker

The cross-encoder rerank stage measured 4.0–5.3s across the production smoke, against a 4.4s median retrieval call in the search-leg benchmark. Those are different runs, so they do not subtract cleanly. A later run on the deployed service (150 questions, August 4) measured the stage at 1.6s on average, of a 9.7s median service time. Treat the earlier range as superseded. The stage cannot simply be removed, because the control for declining unsupported questions depends on it.

Warm median wall time by arm and model size

Production smoke · 16 requests total, 2 per cell

4B8B
04812Base · 4B: 3.8sBase · 8B: 3.8sBaseBase + search · 4B: 8sBase + search · 8B: 11.5sBase + searchTuned · 4B: 2.9sTuned · 8B: 4.7sTunedTuned + search · 4B: 8.4sTuned + search · 8B: 12.1sTuned + search
Two requests per cell. This proves routing and behaviour, not performance. Read the shape, not the values.

Retrieval costs 4.2s at 4B and 7.7s at 8B in this smoke. The 4B retrieval arm matched the 8B retrieval arms on both behaviour checks while running about 30% faster. That makes the 4B base model with search the leading production candidate — as a hypothesis for the next run, not a launch claim.

Mid level

What retrieval buys

Speed only matters if the answer is right. On the 8B development matrix, retrieval is the only component with a large within-model quality signal.

Strict correctness · 100 development questions per arm · Wilson 95%

Base 8B, closed book

15% (15/100)

Base 8B, retrieval

86% (86/100)

Tuned 8B, closed book · overlap

7% (7/100)

Tuned 8B, retrieval · overlap

81% (81/100)

Retrieval moved the base 8B model from 15% to 86% — a 71-point difference on this set. The tuned rows are marked overlap because the development set overlaps tuning exposure, so they cannot support a generalisation claim. They are published to guide experiment design, not to sell fine-tuning. Tuning did not beat the base model in either mode.

A separate leakage-free rescore on a fresh 49-question draw is published with its confidence intervals and a paired significance note on the evaluation screen.

Mid level

Retrieval versus shell search

The comparison people ask for is grep against vector search. That is the wrong unit. The right unit is the whole path to an answer, because a shell-search agent pays for its search again on every extra model turn.

Below, each line is one cost term, measured as shell search minus retrieval. Bars to the right are where retrieval is ahead.

Which term costs what

Shell search minus retrieval, seconds

Favours retrievalFavours shell search
-4s-2s0s+2s+4sExtra model turnsExtra model turns: +3.71s — 3 decode phases and 3 fixed overheads instead of 1+3.71sExtra contextExtra context: +0.60s — 4.1× the tokens, but prefill is cheap+0.60sSearch legSearch leg: -4.16s — the only line shell search wins-4.16sNetNet: +0.16s — shell search minus retrieval+0.16s
The net is a tie. The story is that extra turns cost six times what extra context costs.

Prefill rate

13,585

tokens per second — reading the prompt

Decode rate

28

tokens per second — writing the answer

Ratio

485×

why extra turns cost more than extra context

Reading is nearly free; writing is not. That is why handing the model 4.1× more text costs only 0.6s, while making it generate two more times costs 3.7s. Any estimate that prices context at a decode rate overstates it by two orders of magnitude.

Executed, not modelled · 2026-08-03 · development evidence

Everything above this line is a model built from measured rates. On August 3 the comparison itself was executed: 30 paired questions through a real agent that chooses its own rg searches and file reads, against the same retrieval pipeline, all three arms answering with one equalized hosted model.

MetricFile-tool agentRetrieval + rerankerRetrieval, no reranker
Median answer latency2.219s1.369s0.784s
Gold document found20/3029/3029/30
Strictly correct answers17/3017/3019/30
Declined an answerable question10/305/304/30
Median model calls411
Answer-model cost, 30 questions$0.01454$0.00926$0.00908
Completed without protocol failure28/3030/3030/30

The paired result is one-sided: the agent was slower than non-reranked retrieval on 28 of 28 usable pairs, a median 1.418s behind. Its retrieval-recall deficit is statistically significant (exact McNemar p = 0.0117); final correctness is not — and the mechanism matters. The file-tool agent's failure mode was silence, not wrong answers: it declined to answer a third of answerable questions, almost always after failing to find the gold document. The reranker was slower on every question, a paired median 0.552s, and bought no measured recall or quality — which is the modelled conclusion above, confirmed by a second, independent method.

Two honest limits. The agent arm is a floor, not a ceiling: a small model under tight turn caps; a stronger agent would buy recall back by paying more per turn. And this ran on local hardware with a hosted answer model — it has not been repeated on the production serving path.

Tables

The data

Search leg · 29 usable of 30 attempted

MetricCorpusAegisShell searchNote
Gold-document recall28/2926/29descriptive; visible development set
Median context8,602 ch35,035 ch4.1× less text
Median context tokens~2,150~8,7594-chars-per-token proxy
Search-stage latency4.4s0.24snot like-for-like: network vs local
Round trips before generation1 model turn3+ model turnsstructural, not an executed agent loop
End to end8.57s8.73smeasured rates, declared turn structure

Production smoke · 16 requests total, 2 per cell

ArmSizeCited gold sourceDeclined unsupportedMedian latency
Base4Bn/a0/13.8s
Base8Bn/a1/13.8s
Base + search4B1/11/18s
Base + search8B1/11/111.5s
Tuned4Bn/a0/12.9s
Tuned8Bn/a0/14.7s
Tuned + search4B1/11/18.4s
Tuned + search8B1/11/112.1s

Development matrix · 8B · 100 questions per arm

ConfigurationStrict correctWilson 95%Evidence use
Base 8B, closed book15/1009.3–23.3%development evidence
Base 8B, retrieval86/10077.9–91.5%development evidence
Tuned 8B, closed book7/1003.4–13.8%generalisation claim blocked by development overlap
Tuned 8B, retrieval81/10072.2–87.5%generalisation claim blocked by development overlap

Deep detail

Bench notes

Everything above rests on an arithmetic model with two unmeasured inputs. This section states the model, shows how far the conclusion moves when those inputs move, and names what would settle it. It is deliberately text-first: the charts here are for people who intend to check the reasoning.

How the rates were obtained

A calibration sweep asks the live deployment the same question at six increasing context sizes plus six closed-book probes, reads generation milliseconds and token counts off the service meter, and fits three parameters jointly by least squares: fixed per-call overhead, milliseconds per prompt token, and milliseconds per completion token.

An earlier version fitted these in sequence — decode from the closed-book probes, prefill from the residual. It was unstable: the same deployment returned 3,743, then 9,567, then 9,090, then 15,748 tokens per second of prefill on consecutive runs, while decode never moved. Overhead and prefill were absorbing each other. The joint fit that replaced it repeats to within 1.6%. Its solver is covered by unit tests that check it recovers known coefficients exactly, keeps prefill the faster direction under noise, and returns nothing rather than a number when the probes did not vary enough to identify a rate.

Prefill13,585 tok/s
Decode28 tok/s
Fixed cost per call80 ms
Probes12
Calibrated prompt range213–3,552 tokens

The model

Writing shell search minus retrieval, in seconds:

net = search delta + context + 2 × overhead + T / d
    = −4.16 + 0.60 + 0.16 + T / d

T is the number of tokens the agent generates across its two extra turns. d is the decode rate. Everything else is measured. The ledger in the section above is this function at the declared T = 100 and the measured d = 28.

Neither T nor d is a constant of nature. T has never been counted on a real agent loop — the harness does not run one. d is our L4 deployment. Both charts below exist because a single number here would be a guess wearing a decimal point.

Sensitivity to agent verbosity

How far retrieval is ahead, against tokens the agent generates in its extra turns · log scale · at the measured 28 tok/s

0.1s1s10s100s100 tokensraw tool JSON, no reasoning100 tokens (raw tool JSON, no reasoning): retrieval ahead by 0.17s+0.17s200 tokensone sentence of planning per turn200 tokens (one sentence of planning per turn): retrieval ahead by 3.74s+3.74s400 tokens~150 reasoning tokens per tool call400 tokens (~150 reasoning tokens per tool call): retrieval ahead by 10.89s+10.89s1,000 tokensbrief thinking blocks1,000 tokens (brief thinking blocks): retrieval ahead by 32.31s+32.31s4,000 tokensextended thinking4,000 tokens (extended thinking): retrieval ahead by 139.46s+139.46s
Three orders of magnitude between a bare tool call and an extended-thinking loop. This parameter has not been measured.

Sensitivity to serving speed

Net advantage against decode rate, at T = 400 tokens. Above zero, retrieval wins.

TodayReranker removed
-2s0s+4s+8s+12s28100200300decode tokens per secondbreak-even 118 tok/sToday — 28 tok/s: retrieval ahead by 10.89sToday — 50 tok/s: retrieval ahead by 4.60sToday — 80 tok/s: retrieval ahead by 1.60sToday — 118 tok/s: shell search ahead by 0.01sToday — 200 tok/s: shell search ahead by 1.40sToday — 300 tok/s: shell search ahead by 2.07sTodayReranker removed — 28 tok/s: retrieval ahead by 14.89sReranker removed — 50 tok/s: retrieval ahead by 8.60sReranker removed — 80 tok/s: retrieval ahead by 5.60sReranker removed — 118 tok/s: retrieval ahead by 3.99sReranker removed — 200 tok/s: retrieval ahead by 2.60sReranker removed — 300 tok/s: retrieval ahead by 1.93sReranker removed
On the current stack the two arms cross over. With the reranker removed the line never reaches zero, at any decode rate.

The finding that survives both charts

Remove the reranker and retrieval falls to roughly 0.40s. The search-leg term goes from −4.16s to −0.16s and the model reduces to:

net = context + T / d

Both terms are non-negative by construction. Context can only be zero or positive; T / d is positive for any agent that emits anything at all. So with the reranker removed, shell search loses end to end for every value of T, every decode rate, and every prefill rate. No unmeasured parameter can flip it.

In the August 2 run, the near-tie was not evidence that grep competes with retrieval. It was evidence that one stage of our own pipeline cost about as much as an entire agent loop. The August 4 deployed run measured that stage at a much smaller 1.6s, so this argument is unproven for the deployed system.

Measured, declared, unmeasured

Measured. Both token rates. Fixed per-call cost. Context sizes. Question lengths. Grep output size. Search times. Recall.

Declared, and chosen to favour shell search. Three turns. A 400-token system prompt. 400 tokens of tool schemas. 40 tool-call tokens on the first turn, 12 per file read on the second. A real harness carries more of each and usually takes more than three turns, so the shell total is a floor.

Extrapolated. The shell arm’s largest turn prompt is 8,819 tokens. The calibration sweep reaches 3,552. That one line is an extrapolation, and the harness prints a warning where it happens. The conclusion above is deliberately stated in a form that does not use the prefill rate at all.

Prefix caching. The harness computes a cached and an uncached shell total, because caching decides which is real. vLLM caches by default, so the cached — smaller — number is the one quoted. The compounding survives the assumption favourable to shell search. Cache-hit rate was not recorded.

A measured null we paid for

A paired 150-question experiment compared a plain answer prompt against a source-restricted prompt on gemini-2.5-flash-lite (laboratory, not the shipped service). Strict correctness and the absolute number of fully supported answers were identical. It is published because a null result is still evidence, and because the supported-answer “improvement” it appeared to show was an artefact.

Plain prompt versus source-restricted prompt

Paired, same 150 questions · gemini-2.5-flash-lite (laboratory, not the shipped service)

Plain promptSource-restricted prompt
04080120Strict correct · Plain prompt: 108Strict correct · Source-restricted prompt: 108Strict correctFully supported · Plain prompt: 97Fully supported · Source-restricted prompt: 97Fully supportedIncorrect · Plain prompt: 7Incorrect · Source-restricted prompt: 2IncorrectPartial · Plain prompt: 11Partial · Source-restricted prompt: 13PartialMalformed · Plain prompt: 1Malformed · Source-restricted prompt: 3MalformedDeclined an answerable question · Plain prompt: 23Declined an answerable question · Source-restricted prompt: 24Declined an answerable question
The reported share of supported answers rose from 80.2% to 82.2% because the graded population fell from 121 to 118 — not because more answers were supported.

What is not on this page

An omission a reader can see is not a claim. These are the fields a complete proof artifact needs, and how far the runs so far fill them.

FieldStatus
Cost per correct-and-supported answerAnswer-model cost per strict-correct answer was measured on Aug 3 in the development run. Indexing, retrieval compute, and hosting are still not priced in.
Answer quality in the shell-search armGraded on Aug 3 by a reference judge: statistically tied with retrieval. Blinded human adjudication has not happened.
Real agent-loop token countsMeasured on Aug 3: the executed agent used a median 3,370 cumulative prompt tokens over 4 calls — far below the modeled worst case. Unmeasured on the production Qwen path.
Per-request stage timings and prefix-cache hit rateNot recorded. vLLM exposes queue, prefill, time-to-first-token and decode; per-request metrics are off in the current launch command.
Memory use on target hardwareNot published for this run.
Sealed acceptance evidenceNone on this page. Every number here comes from a visible development set or a live smoke.
Request reliability1 of 30 live retrieval requests returned a non-200, undiagnosed. In the Aug 3 run the file-tool agent lost 2 of 30 attempts to its multi-turn protocol; both retrieval arms went 30 for 30.
Declining questions the documents cannot answerThe control that makes the deployed system decline unsupported questions exists and is switched off. In the August 4 run it declined 4 of 150 questions.
Validated gradingAnswers were graded by an automated judge against a written rubric. Neither has been validated by people. The same 150 answers score 107 strict under rubric version 1 and 100 under version 2.
Production replication of the agent-loop resultThe Aug 3 end-to-end win is a local development run on a hosted answer model. It has not been repeated on the Qwen/Modal production path or a customer corpus.

Provenance

Repository evidencebf17de5d1285ae0e99b573d1cdf92db4be9ea5de
Run date2026-08-02
Harnessscripts/search_bench.py
Corpus236 Markdown files (development corpus, artifact1)
Answer modelqwen3-4b-tuned — Qwen3-4B base + LoRA adapter
HardwareModal L4
ServingvLLM, prefix caching at its default
Reproduce.venv/bin/python scripts/search_bench.py --n 30 --top-k 5
Executed agent-loop run2026-08-03 · scripts/agent_search_bench.py · gemini-2.5-flash-lite (equalized across all three arms)