hsrakri / sparky · measured results

The data,
graphed honestly.

225 unattended agent tasks, ~3,100 delegated LLM calls, two overnight runs, one real vLLM bug — every chart below is drawn from the CSVs in this repo.

Soak #1 · 150 single‑round tasks

97.3% pass, and a tight
wall‑time distribution.

150 back‑to‑back delegated coding tasks. The bulk lands in 60–90 s; the long tail is the coder thinking harder, not the stack degrading — memory stayed flat all night and the self‑healing never fired.

Wall‑time per task · n=150

avg 104 s · min 49 s · max 300 s (cap)
17
<60s
61
60–90s
36
90–120s
21
120–180s
15
≥180s
All 4 failures were 300 s timeouts on 2 of 24 problem types — never a crash, OOM, or endpoint drop.

Memory over the night · GiB used of 121.7

both models resident · sampled across the run
121.7 (total) 100
Steady 119–120 GiB: vLLM pre‑reserves its pools, so sustained load can’t creep it. Flat is the win.
Stress #2 · 75 correction cycles

How the orchestrator
actually divides labor.

Each cycle: the orchestrator gets an intense coding task, we run the result, then feed the real error back for a revision. The delegation counters tell a story nobody wrote in a model card:

99%
Round 1 · first draft → delegated
74 of 75 drafts sent to the coder, averaging 21.9 coder calls per task. The orchestrator outsources the hard writing.
15%
Round 2 · corrections → delegated
Only 11 of 75 fixes re‑delegated — the orchestrator patches small corrections itself, and still lands a passing solution 79% of the time.
Finding: “delegate the hard first draft, patch corrections inline.” Emergent division of labor — nobody configured it.
Per‑problem pass rate

The coder has
specific kryptonite.

Failures weren’t random: the same few algorithms made the coder over‑iterate past its 600 s budget (17–36 calls instead of ~3), while it aced everything else across both nights.

Stress #2 pass rate by problem · selected from 24 types

green = clean · amber = struggled · red = kryptonite
LRU + TTL cache
4/4
A* pathfinding
3/3
expression evaluator
3/3
circuit breaker
3/3
union–find · KMP · bloom
3/3
COW B‑tree
2/3
interval tree
2/3
min‑max heap
1/3
thread‑safe object pool
1/3
Myers diff
0/4
Myers diff: 0 for 4. Every attempt looped refining past the timeout. Reproducible kryptonite — useful for routing hard tasks differently.
Recipe 02 · dense‑27B acceleration

Free speed exists —
with one sharp edge.

n‑gram speculative decoding needs no draft model: vLLM guesses continuations from patterns already in the context, and code is full of patterns. Acceptance by draft position, measured on 900‑token generations:

Draft‑token acceptance rate by position

k=5 → 22.1 tok/s (1.9×) · k=3 → 19.1 tok/s (1.65×) · baseline 11.6 tok/s
pos 1
pos 2
pos 3
pos 4
pos 5
k = 5 draftsk = 3 drafts
The sharp edge: with spec‑decode on, qwen3_coder tool‑calls came back mangled — the function name absorbed the arguments (reproduced at both k, temp 0; clean without). For an agent coder that writes files via tools, that’s disqualifying — so the final config keeps prefix caching and trades the 1.9× back. Pure codegen? Turn it on.
What actually fought back

Seven challenges,
zero unsolved.

The honest engineering log — each one cost real time, each one is reproducible, each one has a fix in the recipes.

memory semantics

“0.45 + 0.45” is a race, not a partition

vLLM’s --gpu-memory-utilization is a per‑process reservation checked against free memory at startup. Two instances launched together fight the profiler; the loser dies with No available memory for the cache blocks.

Solved: fractions sum ≲ 0.88, sequential startup, coder first — codified in vllm-stack-up.sh.

deadlock

CUDA‑graph capture hangs when co‑located

Nemotron’s torch.compile / graph‑capture path froze at boot every time a second model was resident — banner printed, memory flat, nothing loaded, no error. The nastiest kind of failure: silent.

Solved: --enforce-eager for the orchestrator. Costs decode speed, boots 100% of the time.

found a real bug

Speculative decoding breaks tool‑call parsing

On vLLM v0.26.0, n‑gram spec‑decode + the qwen3_coder parser returns name="get_weather(city=…)" with empty arguments — at temperature 0, reproduced at k=3 and k=5, clean without spec. A genuine serving‑stack interaction bug.

Solved (worked around): agent config ships without spec‑decode; documented as pure‑codegen‑only. 1.9× left on the table until the parser interaction is fixed upstream.

model behavior

The coder over‑iterates on hard algorithms

On Myers diff, min‑max heaps, and thread‑safe pools, the delegated coder loops — 17–36 calls refining instead of converging — and blows its time budget. 100% of both nights’ failures trace to this one behavior.

Mitigable: iteration caps or per‑task budgets; the per‑problem data makes hard tasks routable.

reasoning tax

The orchestrator thinks 169 tokens to say “PONG”

Reasoning models reason — even on trivial prompts. Hidden thinking consumed whole token budgets and made early benchmarks look like empty responses.

Solved: reasoning_effort: none at the agent layer + generous budgets; “detailed thinking off” only trims it.

harness lesson

Delegated agents write files, not stdout

Benchmark harnesses that parse the orchestrator’s chat output see summaries, not code — the sub‑agent wrote solution.py to disk all along. Cost three harness rewrites at 2 a.m.

Solved: make the file the artifact — instruct a canonical path, read the file, keep round‑2 prompts short so the orchestrator delegates instead of over‑reasoning.

physics

Dense 27B ≈ 12 tok/s. That’s the roofline, not a bug.

273 GB/s ÷ ~14 GB of active NVFP4 weights ≈ 20 tok/s ceiling; we measured 11.6 co‑located. No flag fixes bandwidth — only fewer active bytes (MoE) or accepted drafts (speculation) do.

Accepted: the orchestrator fronts the conversation at ~50 tok/s while the strong‑but‑slow coder works in the background — the architecture absorbs the physics.