Benchmarks

Most suites below are retrieval-level and use no answer-generating reader. MemoryAgentBench supplies an external conflict fixture, and is additionally run end-to-end inside its own harness with an LLM reader; the other two suites are internal regression data.

MemoryAgentBench conflict resolution

MemoryAgentBench (ICLR 2026 paper) defines a Conflict Resolution track for retrieving the newest valid fact after updates. The Knowl harness uses the factconsolidation_sh_6k row: 455 facts, 156 detected conflict groups, 100 questions, active-only top-5 vector+BM25 retrieval, and no LLM reader.

MemoryAgentBench conflict-resolution ablation: supersession on reached 98 percent top-1 with 2 stale returns; supersession off reached 47 percent top-1 with 62 stale returns
Configuration Top-1 Any rank Stale returns Active atoms Stored p50 / p95
Supersession ON 98.0% 100% 2 / 100 306 13 / 19 ms
Supersession OFF 47.0% 98% 62 / 100 455 14 / 20 ms

Supersession retired 149 facts at write time; both rows otherwise use the same corpus, path, and metric. The instance covers dynamic single-hop latest-fact conflicts, not static, conditional, multi-hop, or reader behavior.

End-to-end, in MemoryAgentBench's own harness

The figures above are retrieval-level and scored by this repository. The same claim was also run inside MemoryAgentBench's harness and scored by its own code, with an LLM reader consuming what Knowl returned. Metric is substring_exact_match, the field the benchmark specifies for Conflict Resolution; reader is gpt-4o-mini at temperature 0.7, top-k 10, 100 questions per cell.

Each cell is a single run, not a median of several. At temperature 0.7 with n = 100, binomial standard error is roughly 3 points, so treat each individual figure as carrying a few points of uncertainty. The comparisons are wider than that — the ablation gap is about five standard errors and holds at two corpus sizes — but a single figure quoted alone should not be read to the point.

MemoryAgentBench FactConsolidation single-hop at 262K context, substring exact match, gpt-4o-mini reader: Knowl 90, GPT-4o long-context 60, BM25 56, NV-Embed-v2 55, HippoRAG-v2 54, GPT-4o-mini long-context 45, Cognee 28, MemGPT 28, Mem0 18
System FactConsolidation-SH @262K
Knowl 90
GPT-4o (long-context) 60
BM25 56
NV-Embed-v2 55
HippoRAG-v2 54
GPT-4o-mini (long-context) 45
Cognee 28
MemGPT 28
Mem0 18

Knowl's row was measured here. Every other row is from the paper's Table 2, which states that "all RAG agents and commercial memory agents use GPT-4o-mini as the backbone" — the same reader used for Knowl, so the rows are like-for-like. Long-context rows use their own named model. Systems the paper does not evaluate on this task, including Zep, Graphiti and Letta, are not listed rather than carried over from secondary sources.

The ablation in that harness:

Instance Supersession ON OFF Gap
factconsolidation_sh_262k 90 73 +17
factconsolidation_sh_6k 94 78 +16
factconsolidation_mh_262k 7 6 +1

input_len stays within 294–410 on every row of every cell, which is the cheapest contamination check available: rows left behind by an earlier code path carry a visibly different context size, and MemoryAgentBench's --force flag does not discard old results — it only bypasses the context-level skip, so stale rows are otherwise silently averaged into a new score.

Multi-hop is retrieval-bound, not reader-bound. Only 14 of 100 multi-hop questions have the gold answer anywhere in the retrieved set, so no reader could exceed 14; Knowl scores 7. Quote it with that ceiling attached — the fix is chained retrieval, which Knowl does not do, not prompt or supersession tuning.

Method and full write-up: independent rebuild.

Re-measured 2026-08-06 with the granite-small-en-r2 default, stable across two runs. The previous figures — 96.0% and 40.0% top-1 with 3 stale returns — were taken on the minilm-l6-en default this repository shipped before 2026-08-02. The retrieval path here is vector + BM25, so the embedding model is part of the result and is named rather than left to the reader's config. Both arms moved; the gap narrowed from 56 to 51 points.

The two result JSON files are checked in: supersession ON and supersession OFF. The fetched dataset fixture is ignored by Git and is not checked in. fetch --row 4 reads the current Hugging Face row without a pinned dataset revision, so future fetches depend on that upstream row remaining unchanged. The stored results contain no hardware metadata; their timing fields are run artifacts, not portable latency claims.

See the protocol and interpretation. Reproduce from a source checkout with the repository-only harness:

npm run bench:cr -- fetch --row 4

# --json prints the full run result.
npm run bench:cr -- run \
  --instance benchmarks/memoryagentbench/data/cr-sh-6k.json \
  --top-k 5 --json
npm run bench:cr -- run \
  --instance benchmarks/memoryagentbench/data/cr-sh-6k.json \
  --top-k 5 --no-supersede --json

# --out writes a result snapshot.
npm run bench:cr -- run \
  --instance benchmarks/memoryagentbench/data/cr-sh-6k.json \
  --top-k 5 --out ./memoryagentbench-result.json

These npm run bench:cr -- ... commands are repository scripts, not published knowl CLI commands.

Internal governance regression suite

The checked-in retrieval-governance.json has 56 decision fixtures: 22 current decisions, 22 stale predecessors, and 12 rejected decisions. It defines 44 top-3 cases.

Internal governance regression suite: MRR 100 percent, 27 stale-active returns with 21 stale-trap failures, and zero rejected items returned
Recall@3 MRR nDCG Stale-active returns Stale-trap failures Rejected items returned
100% 100% 100% 27 21 0

MRR is reciprocal rank, not top-1 accuracy, and at 100% it means the expected current decision ranked first in every one of the 44 cases. Stale predecessors remain active, so 21 stale traps still failed and produced 27 stale-active returns; rejected items test a separate status filter and never appeared. Recall@3 means every top three contained the expected current decision, not that every result was current.

This suite is now saturated and cannot show an improvement, only a regression. Every ranking metric is at ceiling, so the only figures left that can move are the two stale counts. Use semantic-suite.json for anything that has to discriminate.

Measured on the granite-small-en-r2 default. Two earlier sets of figures are worth knowing about, because both differed by something other than the ranker: MRR 94.3182% with 43 stale-active returns was taken on the minilm-l6-en default this repository shipped before 2026-08-02, and MRR 98.86% with 28 stale-active returns predates the semantic rescale in scoreCandidates. The model and the scoring are both part of the result.

knowl eval \
  --dataset docs/evals/retrieval-governance.json \
  --vector --json

Internal retrieval regression suite

The checked-in retrieval-suite.json contains 500 cases over 168 fixtures. It is a repository regression suite with expected items, stale traps, and forbidden items; it is not third-party evidence.

Internal retrieval regression suite: vector plus BM25 Recall at 3 98.6 percent, Recall at 10 99.8 percent, MRR 95.21 percent, and nDCG 96.36 percent
Retrieval path Recall@3 Recall@10 MRR nDCG Stale hits Forbidden hits Failed criteria
Vector + BM25 98.6% 99.8% 95.21% 96.36% 11 2 3

Measured on the granite-small-en-r2 default, byte-identical across two runs; no result snapshot is checked in. The run passed 497 of 500 evaluator cases, including expected, stale, and forbidden conditions rather than only search hits.

This suite is near its ceiling too, and the numbers moved slightly down when the semantic rescale in scoreCandidates landed — Recall@3 98.8% to 98.6% and Recall@10 100% to 99.8%, one case each. That change was kept because it wins where these suites cannot discriminate: on semantic-suite.json it moved Recall@3 89.6% to 91.9% and the hardest tier's MRR 33.3% to 38.1%, and it left the external MemoryAgentBench result unchanged. A suite at ceiling reports the cost of a change and not its benefit, which is the reason not to tune against this one.

Fresh BM25-only runs varied under equal-score ordering, including their failure counts. Exact BM25 outcome and rank values are therefore not published; rerun the command below in the target environment. No cross-hardware latency is claimed.

knowl eval --dataset docs/evals/retrieval-suite.json --vector --json
knowl eval --dataset docs/evals/retrieval-suite.json --json