GraphFlow Token-Savings Benchmark

August 4, 2026 · View on GitHub

Auto-generated by npm run benchmark (benchmarks/run-token-benchmark.ts). Last run: 2026-08-04T11:27:56.422Z

如何复现(How to reproduce)

npm install && npm run benchmark   # Node ≥ 20,离线运行,无需 API key
  • 环境:Node ≥ 20(本表由 v22.17.1 / win32 x64 生成);无网络、无 API key。
  • 结果文件:本文件 benchmarks/RESULTS.md(人类可读)+ benchmarks/.cache/token-bench-results.json(机器可读,含 commit hash 与运行日期)。
  • 输入数据、判定标准与第三方复现清单见 docs/benchmark-standards.md

Summary

GraphFlow compresses the context an LLM agent needs for a query into a small summary + anchor package, instead of pushing whole source files into the prompt. Across 8 representative queries against this repository:

  • Baseline total input tokens: 274,434
  • GraphFlow total input tokens: 4,928
  • Overall token savings: 98.2%

The headline GraphFlow tokens column is independently re-tokenized with gpt-tokenizer (summary + anchors), not GraphFlow's self-reported estimate. GraphFlow's own internal estimate is shown separately for transparency and is typically lower.

Results table

QueryBaseline tokensGraphFlow tokens (independent)GraphFlow self-estimateSavings %
orchestrator35,886 (10 files)57032598.4%
context compression34,099 (10 files)67241698.0%
model routing23,400 (10 files)58436297.5%
graph index41,383 (10 files)63135998.5%
token savings35,518 (10 files)74046197.9%
semantic enrichment22,640 (10 files)52426397.7%
preview context31,944 (10 files)54427898.3%
skill flywheel49,564 (10 files)66338398.7%
Total274,4344,9282,84798.2%

Run environment

  • Node: v22.17.1
  • Platform: win32 x64
  • Tokenizer: gpt-tokenizer (gpt-4o encoding) — identical for both sides.
  • Graph nodes in store: 4,076
  • Files (re)indexed this run: 117 (0 = incremental, graph already current)
  • Benchmark wall-clock: 35.2s

Methodology & honest caveats

Baseline (no graph) — emulates a traditional coding agent with no context layer. For each query we grep the src/ tree (extensions: .ts, .tsx), rank files by the number of query-term matches, take the top 10 files, and count the tokens of their full contents. This represents the common "dump the relevant files into the prompt" strategy.

  • This is a simulation, not a capture of a specific real agent. The number of files an agent reads varies; we cap it at 10 per query to keep the baseline bounded and reproducible. A higher cap would only increase the reported savings, so this cap is a conservative choice.
  • We scan only src/ (not tests, build output, or generated graph artifacts), which is the code an agent would realistically read for these queries.
  • We count full-file contents because agents without precise navigation tend to read whole files rather than exact line ranges.

GraphFlow (compressed) — calls the exported previewContext function. The headline number is obtained by independently re-tokenizing the exact text an agent receives (the summary channel + anchor pointer lines) with gpt-tokenizer. We deliberately do not trust GraphFlow's self-reported tokenEstimate for the headline (that estimate is shown in its own column and is typically lower, i.e. our reported savings are the conservative side).

  • Anchors are lightweight pointers (id/type/layer). An agent expands only the anchors it needs via expand_anchor, so the initial context cost is what we measure here. Even if every anchor were later expanded, the upfront budget is what determines whether the task fits in a small context window.
  • Semantic (LLM) compression and network embeddings are disabled for this run so it is offline and deterministic; only zero-cost graph-structure compression is active. Enabling semantic compression would typically improve savings further.

Reproduce

npm install
npm run benchmark

No API key is required. The script builds its own isolated graph under benchmarks/.cache/ and replaces its own section in this file on every run (sections appended by the other benchmark scripts are preserved). The machine-readable numbers land in benchmarks/.cache/token-bench-results.json (per-query results, totals, inputs, environment, commit hash and run date).

Skill-Flywheel End-to-End A/B Benchmark — Results (P1-2)

Appended by npm run benchmark:ab (benchmarks/run-skill-ab.ts). Last run: 2026-08-04T11:46:40.564Z Structured JSON: benchmarks/.cache/skill-ab-results.json

Summary

26 retrieval-golden tasks (10 "indirect": the golden module name is morphologically distinct from the query words, e.g. "orchestrate" vs orchestrator), run end-to-end on an in-memory graph seeded with the golden target, distractors and a decoy. Arm A additionally simulates 27 historical tasks through the real learning paths.

MetricArm A (flywheel ON)Arm B (flywheel OFF)
Success proxy (golden target within Top-5)100.0% (26/26)61.5% (16/26)
Success via package Top-5 only61.5%61.5%
Tasks rescued by flywheel (B miss → A hit)10
Tasks hurt by flywheel (B hit → A miss)0
Hint injection rate100.0%0%
Episode recall rate100.0%0%
Mean prompt-token overhead / task55.10
Total prompt-token overhead14320
Mean package tokens / task63946.2
Decoy contamination (Top-5)3.8%3.8%
Decoy contamination (injection)0.0%0%
Mean wall-clock / task2.5 ms2.0 ms
Total wall-clock0.2 s

Per-task detail

TaskGolden moduleDirectTop-5 (B)Success (A)Pkg Top-5 (A)Injection hit (A)HintsEpisodesOverhead tokens
orchestrate task routingorchestratornomisshitnoyes2390
dag execution enginedag-engineyeshithityesyes2261
triage task classification simple complextriageyeshithityesyes3145
model router provider selectionmodel-routeryeshithityesyes3393
provider health fallback chainprovider-healthyeshithityesyes3385
graph compression pagerank centralitygraph-compressionyeshithityesyes3391
context slicer layered packagecontext-sliceryeshithityesyes2260
skill flywheel hints scoringskill-flywheelyeshithityesyes3134
episodic memory similar episodesepisodic-memoryyeshithityesyes1130
embedding cosine similarity vectorembeddingsnomisshitnoyes2130
file watcher incremental index on savefilewatchernomisshitnoyes3269
sqlite graph storage fts5sqlite-clientyeshithityesyes2389
repo map module overviewrepomapnomisshitnoyes1125
token savings statisticstokensavingsnomisshitnoyes2256
mcp server tool definitionstool-definitionsyeshithityesyes2134
cli output json formattingformatcliresultnomisshitnoyes2134
agent delegation work items bridgeworkitemnomisshitnoyes3132
six hats insight planningbrainstormernomisshitnoyes2131
hnsw approximate nearest neighbor indexhnswyeshithityesyes2268
adaptive token budget estimationestimatecontextbudgetnomisshitnoyes3389
artifact export import graph snapshotartifact-manageryeshithityesyes3389
nightly learning trainernightly-traineryeshithityesyes1129
reflect episodes extract lessonsreflectornomisshitnoyes3134
dag checkpoint recovery taskrundag-checkpointyeshithityesyes3267
cancellation timeout controllercancellationyeshithityesyes2127
language indexers tree sitter wasmlanguage-indexersyeshithityesyes2140

Methodology & honest caveats

  • Task set is duplicated from tests/retrieval-golden.test.ts GOLDEN_SET (that file is owned by another agent and is not modified). Each task's golden node id (file:src/golden/<module>.ts) contains an expectAny alternative verbatim.
  • Success proxy: Top-K = the first 5 ranked anchors of the compressed context package (the retrieval channel); success there means the golden node id is within those 5 anchors (precise id membership — avoids substring false positives from distractor/decoy nodes). For Arm A, the injected hints + episode summaries form an additional channel an agent reads in full; hints/episodes reference modules by name, so injection success is the expectAny substring check. Arm A success = package Top-5 hit or injection hit. The package-only hit rate is reported separately for a like-for-like retrieval comparison.
  • Arm B success is deliberately imperfect: for the 10 indirect tasks the golden file shares zero tokens with the query (realistic: module names are morphologically different from task wording), so pure retrieval cannot find it — prior episodic experience is the only bridge.
  • Both arms run through the real retrieval and learning paths (buildEnhancedContextPackage, applySkillLearning, recordEpisode, suggestSkillHints, findSimilarEpisodes, summarizeEpisodeForPrompt) on isolated in-memory graphs — no mocks, no network, no API key.
  • Token counts use gpt-tokenizer (gpt-4o encoding), identical to the token benchmark. Hashing is the project's DJB2a (FNV-class) — fully deterministic within a run; episode ids embed Date.now() so ids differ across runs, but ranking depends on tokens/scores, not ids.
  • This measures a mechanical success proxy, not LLM task completion. It validates that the flywheel's injected context and graph nodes move the needle on finding the expected target, and quantifies the exact token and wall-clock cost.

Episodic-Memory End-to-End A/B Benchmark — Results (P3)

Appended by npm run benchmark:memory (benchmarks/run-memory-ab.ts). Last run: 2026-08-04T11:27:08.785Z Structured JSON: benchmarks/.cache/memory-ab-results.json

Summary

62 tasks: 26 retrieval-golden queries (duplicated from tests/retrieval-golden.test.ts, same list as the P1-2 skill benchmark) plus 36 HARD-domain tasks (12 cross-module, 12 disambiguation, 12 indirect), run end-to-end on an in-memory graph seeded with the golden target, distractors and a decoy. Hard tasks are constructed so the golden node shares zero query tokens (node ids are not searchable text), so the OFF arm cannot rank them — episodic memory is the only bridge. Arm A additionally simulates 63 historical tasks through the real learning paths (applySkillLearning + recordEpisode).

MetricArm A (memory ON)Arm B (memory OFF)
Success proxy (golden target within Top-5)100.0% (62/62)56.5% (35/62)
Success via package Top-5 only46.8%56.5%
Tasks rescued by memory (B miss → A hit)27
Tasks hurt by memory (B hit → A miss)0
Hint injection rate95.2%0%
Episode recall rate100.0%0%
Distinct memories that rescued tasks26
Mean prompt-token overhead / task70.90
Total prompt-token overhead43970
Mean package tokens / task500.167.8
Decoy contamination (Top-5)3.2%3.2%
Decoy contamination (injection)4.8%0%
Mean wall-clock / task4.5 ms1.6 ms
Total wall-clock0.6 s

Memory-contribution summary (top-3 contributing memories)

Episode idEpisode taskTasks rescuedRescued queriesMean similarity
episode:10s9w7atoken savings numbers audited in tokensavings2token savings statistics, numbers behind the token savings0.481
episode:1arcr65mcp restart stuck vscode-extension panel1editor panel stuck after mcp restart0.671
episode:11q0kisimilar past problems matched by embeddings1find similar past problems0.600

Attribution chain (rescued tasks: which memory carried the rescue)

TaskGolden moduleCarry channelTop episode idTop episode taskSimilarity
orchestrate task routingorchestratorepisodeepisode:wkys9zfixed orchestrator routing deadlock0.267
embedding cosine similarity vectorembeddingsepisodeepisode:cmcjy0embeddings cosine similarity provider0.433
file watcher incremental index on savefilewatcherbothepisode:6q1rsqfilewatcher incremental index invalidation0.386
sqlite graph storage fts5sqlite-clientbothepisode:1yskm3psqlite-client fts5 migration0.267
repo map module overviewrepomapepisodeepisode:18ggy5rrepomap overview generation0.267
token savings statisticstokensavingsbothepisode:10s9w7atoken savings numbers audited in tokensavings0.433
cli output json formattingformatcliresultepisodeepisode:1yi5b5cformatcliresult json output handling0.433
agent delegation work items bridgeworkitemepisodeepisode:1eu8wz0workitem bridge delegation0.433
six hats insight planningbrainstormerepisodeepisode:1266q47brainstormer insight planning0.500
adaptive token budget estimationestimatecontextbudgetepisodeepisode:mj7beuestimatecontextbudget token sizing0.267
reflect episodes extract lessonsreflectorepisodeepisode:gnni0qreflector episode lessons0.267
provider adapter crash kills routingmodel-routerepisodeepisode:1js4gvzprovider adapter crash killed model-router dispatch0.475
cli flags now ignored after settings refactorconfig-loaderepisodeepisode:1xzimbosettings refactor broke cli flag loading in config-loader0.373
editor panel stuck after mcp restartvscode-extensionepisodeepisode:1arcr65mcp restart stuck vscode-extension panel0.671
persistent storage for graph datasqlite-clientbothepisode:150tyoigraph data persisted through sqlite-client store0.322
upstream probe fails then whatprovider-healthbothepisode:9sh6e9upstream probe failures tripped provider-health0.350
simple versus complex task splittriagebothepisode:1utbkfusimple tasks bypassed triage queue0.211
learn from what went wrongreflectorepisodeepisode:8bp9bmwhat went wrong captured by reflector0.529
stop a hung run safelycancellationbothepisode:wfucm1hung run cancelled by cancellation controller0.386
numbers behind the token savingstokensavingsepisodeepisode:10s9w7atoken savings numbers audited in tokensavings0.529
find similar past problemsembeddingsbothepisode:11q0kisimilar past problems matched by embeddings0.600
fast nearest neighbor searchhnswbothepisode:nbt8jpnearest neighbor search too slow in hnsw0.529
protocol messages over the wireatp-schemabothepisode:19tm79nprotocol message framing changed in atp-schema0.211
describe the work before planningtask-profileepisodeepisode:1w559i5describe work shape with task-profile0.350
pick between conflicting optionsdecision-enginebothepisode:e10lwiconflicting options resolved by decision-engine0.433
peek at the graph statesnapshot-viewepisodeepisode:1el7lr7snapshot-view graph state dump0.433
export the learning datasetexporterbothepisode:1fudjbuartifact-manager export compression0.267

Per-task detail

TaskGolden moduleKindTop-5 (B)Success (A)Pkg Top-5 (A)Carry (A)HintsEpisodesOverhead tokens
orchestrate task routingorchestratorgoldenmisshitnoepisode2255
dag execution enginedag-enginegoldenhithityesnone2380
triage task classification simple complextriagegoldenhithityesnone3391
model router provider selectionmodel-routergoldenhithityesnone3389
provider health fallback chainprovider-healthgoldenhithityesnone3385
graph compression pagerank centralitygraph-compressiongoldenhithityesnone3385
context slicer layered packagecontext-slicergoldenhithityesnone2257
skill flywheel hints scoringskill-flywheelgoldenhithityesnone3379
episodic memory similar episodesepisodic-memorygoldenhithityesnone3378
embedding cosine similarity vectorembeddingsgoldenmisshitnoepisode2260
file watcher incremental index on savefilewatchergoldenmisshitnoboth3392
sqlite graph storage fts5sqlite-clientgoldenmisshitnoboth3388
repo map module overviewrepomapgoldenmisshitnoepisode0120
token savings statisticstokensavingsgoldenmisshitnoboth3379
mcp server tool definitionstool-definitionsgoldenhithityesnone33100
cli output json formattingformatcliresultgoldenmisshitnoepisode1260
agent delegation work items bridgeworkitemgoldenmisshitnoepisode3379
six hats insight planningbrainstormergoldenmisshitnoepisode0120
hnsw approximate nearest neighbor indexhnswgoldenhithityesnone3389
adaptive token budget estimationestimatecontextbudgetgoldenmisshitnoepisode2377
artifact export import graph snapshotartifact-managergoldenhithityesnone3383
nightly learning trainernightly-trainergoldenhithityesnone2254
reflect episodes extract lessonsreflectorgoldenmisshitnoepisode3257
dag checkpoint recovery taskrundag-checkpointgoldenhithityesnone0247
cancellation timeout controllercancellationgoldenhithityesnone3253
language indexers tree sitter wasmlanguage-indexersgoldenhithityesnone3396
provider adapter crash kills routingmodel-routercross-modulemisshitnoepisode3379
adding an embedding provider changed graph scoresgraph-compressioncross-modulehithitnonone3378
cli flags now ignored after settings refactorconfig-loadercross-modulemisshitnoepisode3132
indexer reindex wipes mcp session statemcp-servercross-modulehithitnonone3385
new language grammar breaks file watchingfile-watchercross-modulehithityesnone3384
sqlite migration loses episodic historyepisodic-memorycross-modulehithityesnone3384
tool schema update confuses agent profilestool-definitionscross-modulehithitnonone3375
nightly training corrupts workspace configworkspace-rootcross-modulehithitnonone3378
editor panel stuck after mcp restartvscode-extensioncross-modulemisshitnoepisode3388
query expansion returns chinese resultsquery-expandcross-modulehithityesnone3135
feedback loop inflates skill scoresskill-flywheelcross-modulehithitnonone3385
atomic skill writes lock the whole storeskill-storecross-modulehithityesnone3372
tree walker skips hidden directoriesfile-indexer-walkerdisambiguationhithityesnone3147
persistent storage for graph datasqlite-clientdisambiguationmisshitnoboth3390
cached context goes stale on file savecontext-cachedisambiguationhithityesnone3396
which agent gets this taskagent-assignmentdisambiguationhithityesnone3258
upstream probe fails then whatprovider-healthdisambiguationmisshitnoboth3259
simple versus complex task splittriagedisambiguationmisshitnoboth3265
learn from what went wrongreflectordisambiguationmisshitnoepisode3387
stop a hung run safelycancellationdisambiguationmisshitnoboth2261
numbers behind the token savingstokensavingsdisambiguationmisshitnoepisode3382
find similar past problemsembeddingsdisambiguationmisshitnoboth3133
fast nearest neighbor searchhnswdisambiguationmisshitnoboth3139
did the run stay on targetgoal-anchordisambiguationhithityesnone3393
execute the chosen providerprovider-executorindirecthithityesnone3380
what can each role dorole-capabilitiesindirecthithityesnone3268
protocol messages over the wireatp-schemaindirectmisshitnoboth3390
describe the work before planningtask-profileindirectmisshitnoepisode3377
transition states in orderstate-machineindirecthithityesnone3395
break the goal into stepsplannerindirecthithityesnone3387
pick between conflicting optionsdecision-engineindirectmisshitnoboth3134
peek at the graph statesnapshot-viewindirectmisshitnoepisode3375
stats about the knowledge graphgraph-analysisindirecthithitnonone3381
bootstrap skills from scratchseed-skillsindirecthithityesnone3260
export the learning datasetexporterindirectmisshitnoboth3377
detect app routes automaticallyframework-routesindirecthithityesnone2135

Methodology & honest caveats

  • Task set: 26 queries duplicated from tests/retrieval-golden.test.ts GOLDEN_SET (that file is owned by another agent and is not modified; this list mirrors benchmarks/run-skill-ab.ts). Each task's golden node id (file:src/golden/<module>.ts) contains an expectAny alternative verbatim. The 36 HARD tasks (cross-module blast radius / name disambiguation / indirect-morphological) are authored for this benchmark; their golden node content deliberately shares zero query tokens, so pure retrieval cannot rank the target.
  • Success proxy: Top-K = the first 5 ranked anchors of the compressed context package (the retrieval channel); success there means the golden node id is within those 5 anchors (precise id membership — avoids substring false positives from distractor/decoy nodes). For Arm A, the injected hints + episode summaries form an additional channel an agent reads in full; hints/episodes reference modules by name, so injection success is the expectAny substring check. Arm A success = package Top-5 hit or injection hit. The package-only hit rate is reported separately for a like-for-like retrieval comparison.
  • Package ranking differs slightly between arms: Arm A's graph additionally holds the history nodes (skills + episodes), which can shift the package top-5 for a few tasks; such differences are visible in the per-task detail (Pkg Top-5 (A) vs Top-5 (B)) and count as real flywheel side effects — the summary's rescued/hurt numbers include them.
  • Attribution: for each rescued task, carryingChannel names the channel that actually carried the target; the top similar episode is the first entry of the real findSimilarEpisodes ranking, and similarity is recomputed with the exact formula that ranking uses internally (Jaccard over extractTaskTokens +0.1 for a pass outcome), since scores are not exported. The memory-contribution summary counts each distinct episode that rescued >= 1 task.
  • Arm B success is deliberately imperfect: the 27 tasks the OFF arm misses (11 golden + the hard tasks) share zero query tokens with their golden file (realistic: module names are morphologically different from task wording, and symptoms cross module boundaries) — prior episodic experience is the only bridge.
  • Both arms run through the real retrieval and learning paths (buildEnhancedContextPackage, applySkillLearning, recordEpisode, suggestSkillHints, findSimilarEpisodes, summarizeEpisodeForPrompt) on isolated in-memory graphs — no mocks, no network, no API key.
  • Token counts use gpt-tokenizer (gpt-4o encoding), identical to the token benchmark. Hashing is the project's DJB2a (FNV-class) — fully deterministic within a run; episode ids embed Date.now() so ids differ across runs, but ranking depends on tokens/scores, not ids.
  • This measures a mechanical success proxy, not LLM task completion. It validates that episodic memory moves the needle on finding the expected target, quantifies the exact token and wall-clock cost, and exposes which memories earned their keep.