Options paper · agent-memory landscape

Why we built reflect instead of adopting one

Eight coding-agent memory systems, four deciding axes, and an honest build-vs-adopt verdict. The short version: the tools that need no second API key tend to hoard noise; the ones that curate well make you run a server and pay a second provider; and none capture corrections, tests, git events or skill upgrades as typed signals. reflect is the row that holds all four — so we ported the good retrieval ideas and built the thin layer nobody else does.

Date2026-06-21 Author@stevie Systems compared8 Verdict · build + port (CAUTION)
01

The problem: context engineering, not a bigger file

Every coding harness gives you exactly one persistent-memory primitive: a static instructions file you maintain by handCLAUDE.md, AGENTS.md, MEMORY.md, copilot-instructions.md — front-loaded into the context window at the start of every session.

That has a hard ceiling. The window is finite and shared with the actual task. Every line you front-load "just in case" is bloat the moment this session doesn't need it, and it crowds out the files, diffs and reasoning the task does need. A bigger instructions file is the wrong axis.

The real questions are temporal and selective: a correction you made three weeks ago should reach the agent only in the session about to repeat the mistake; the architecture reason behind a non-obvious choice should surface when someone questions that code and stay invisible otherwise. That's a retrieval problem — store the signal-bearing moments and query the right one at the right time. It's why a class of "agent memory" products exists. This paper compares them and explains why we built rather than adopted.

02

Evaluation criteria

Weighted to a coding-agent self-improvement workflow — the priority is capturing corrections and turning them into behaviour, cheaply, without standing up infrastructure. Each criterion scores 1–5; weighted total out of 5.0. (Re-weighting changes the order — see the sensitivity note in §09.)

Signal capture / self-improvementcorrections, tests, git, skills as typed events
0.25
No extra key / token economyreuse the agent's model vs a 2nd provider
0.22
Local-first / low infrafiles vs always-on server / cloud
0.20
Selective capture / noise controlvs whole-session hoarding + growth
0.16
Retrieval qualityhybrid + rerank + graph + temporal
0.12
License / portabilitypermissive OSS, cross-harness
0.05
03

The eight systems

Each scored on the four most decisive criteria (signal capture · no-extra-key · local-first · retrieval). Weighted total uses all six.

Built

reflect

MIT · local-first · cross-harness

Selective learnings; markdown is the source of truth. Reuses the agent's own model (claude -p) + a local embedder — no extra key. First-class typed signals.

Signals5
No key5
Local5
Retrieval4
weighted4.72 / 5
Strongest adopt

Hindsight

MIT · vectorize-io

LLM-extracted facts + mental models. Best-in-class multi-strategy retrieval (94.6% LongMemEval), ~48 integrations. retain needs an LLM; reuse-your-sub loopback is ToS personal-use-only.

Signals2
No key2
Local3
Retrieval5
weighted3.03 / 5
Closest on cost

claude-mem

Apache-2.0 · thedotmack

Compresses every tool call into observations. Reuses Claude auth + local embeddings (no extra key — ties reflect here). But unbounded growth, no native prune, ChromaDB fragility, probabilistic extraction.

Signals2
No key5
Local3
Retrieval3
weighted3.08 / 5
Curated tree

ByteRover

Elastic-2.0 (not OSS)

Curate-before-store markdown tree, local-first, importance decay. But curation makes its own LLM calls and is agent-directed, not passive — nothing captured unless the agent calls curate.

Signals2
No key3
Local4
Retrieval3
weighted3.06 / 5
Fact extractor

Mem0

Apache-2.0 + SaaS

LLM-extracted facts; OpenAI by default at ingest (separate key). Full stack is Postgres + Neo4j; graph memory gated to the $249/mo Pro tier. Documented dedup gap.

Signals2
No key2
Local2
Retrieval4
weighted2.50 / 5
Fire-hose

agentmemory

Apache-2.0 · rohitg00

Captures every tool call verbatim, then consolidates via opt-in LLM. Always-on Rust daemon (4 ports, pinned binary). O(N²) forget ceiling ~1k; documented token-burn incidents.

Signals2
No key3
Local2
Retrieval3
weighted2.28 / 5
Personalization

Honcho

AGPL-3.0 · Plastic Labs

Theory-of-mind models of users/peers — built for end-user personalization, not coding signals. Self-host needs 1–3 provider keys + Postgres + Redis + a deriver worker; cloud is per-query.

Signals1
No key2
Local2
Retrieval4
weighted1.99 / 5
Context DB

OpenViking

AGPL-3.0 · ByteDance

Tiered (L0/L1/L2) LLM-extracted memories/skills with conflict-aware dedup. Strong on noise — but OpenAI/Volcengine by default (separate key) and a Rust+Go+C++ always-on server.

Signals2
No key2
Local2
Retrieval4
weighted2.56 / 5
04

Comparison matrix

Darker green = stronger fit, rust = weak. The clay outline marks the best cell in each row. Bottom row is the weighted total under §02's coding-agent weights.

reflectHindsightclaude-memByteRoverMem0agentmemHonchoOpenViking
Signal capture (0.25)52222212
No extra key (0.22)52532322
Local-first (0.20)53342222
Selective / noise (0.16)44243124
Retrieval quality (0.12)45334344
License / portability (0.05)55424422
Weighted total4.723.033.083.062.502.281.992.56

The pattern reads straight off the matrix: the only other system that matches reflect on no extra key (claude-mem) collapses on selective/noise; the systems that curate well (Hindsight, OpenViking, ByteRover) lose on no extra key or local-first; and signal capture is a wall of 2s — nobody else treats corrections, tests, git or skills as typed events.

05

How reflect actually works

Two diagrams: where reflect operates across a single session, and where it stores what it captures (local by default, optional shared Postgres).

How reflect operates across one coding session Reads inject prior knowledge into context · writes capture new signals · the index closes the loop to the next session. READ → INTO CONTEXT WRITE ← FROM SESSION SessionStart UserPromptSubmit→ tool calls (Bash/Edit/Todo…) UserPromptSubmit→ more tool calls Stopturn ends PreCompact Recallinject relevant prior learnings+ drain queued captures Recall (intent-sharp)per prompt · de-duped RecallRRF · rerank · OOD gate PostToolUse · signalstest pass/fail · tool-loop · git event · todo donecorrection (“no — don’t…”) · permission reply Captureslice window →learning + sidecar Flushcapture before compact IndexQMD (BM25) + nano-graphrag (vector + entity graph) · local model, no extra key recalled in the next session → Idle sweepquiet transcripts → speculative (down-ranked)
Reads inject at SessionStart + each prompt; typed signals and capture write out at tool calls, Stop and PreCompact; the index closes the loop to the next session.
reflect — component topology one engine · three harnesses · two memory modes (local default / shared Postgres) AGENT HARNESS (your LLM lives here — no extra API key) Claude Codenative plugin · full hooks Codex CLIadapter · hooks.json (0.129+) GitHub Copilotadapter · native hooks lifecycle hooks: SessionStart · PreCompact · Stop · PostToolUse reflect CLI — engine (Python pkg `reflect-kb`) capturecorrections → notes indexembed + extract recallhybrid + rerank client keeps the brain — recall+index run a LOCAL embed model; capture reuses the harness LLM (claude -p). No separate key. markdown KB ~/.claude/global-learnings/*.md — SOURCE OF TRUTH (local, always) MODE 1 — LOCAL (default)each machine builds + queries its own derived stores QMDindex.sqliteBM25 lexical nano-graphraghnswlib vectors.graphml graph share across machines:git-sync ~/.claude/global-learnings + `reflect reindex`on each machine (re-embeds locally) MODE 2 — SHARED (Postgres)one store; every machine queries the same memory Supabase Postgres (dumb · RLS · no LLM)ng_vectors (pgvector) · ng_graph_nodes/edges · ng_kvreplaces the nano-graphrag LOCAL stores enable per machine:export REFLECT_PG_DSN=… REFLECT_WORKSPACE_ID=…nano-graphrag runs unchanged (storage_classes swap) MODE 1 + MODE 2 share the SAME markdown source of truth + the SAME reflect engine — only the derived vector/graph store moves.
Local by default (sqlite + graphml), optional shared Postgres — the markdown KB stays the source of truth either way; only the derived index moves.
06

Token economics — both sides of the ledger

Memory looks cheap if you only price retrieval. The real cost is the write side (LLM extraction / consolidation) plus the read side (context injection). Here's where each system spends.

SystemWrite side (capture/extract)Read side (recall)Net extra spend
reflectreuses harness LLM (claude -p), gated + queued; local embedlocal — vector + BM25 + graph, no LLM$0 extra (rides your existing sub)
claude-memHaiku on your Claude auth, per tool-call batchFTS5 + local ONNX vectors$0 extra, but high write volume
Hindsightretain = LLM extraction; cloud $15/M tokensvector/graph (no LLM); reflect synthesis costsseparate key or $15/M retain
Mem0OpenAI extraction at ingest (ADD/UPDATE/DELETE)vector/BM25; graph = Pro $249/moseparate OpenAI key + tier
OpenVikingVLM extraction + L0/L1 summaries at commitvector recursive (no LLM)separate provider key
Honchoderiver LLM ("dreaming") per message batchcontext() free; dialectic up to $0.50/query1–3 keys (self-host) or per-query
agentmemoryoptional LLM compression (off by default)local embed; triple-stream RRF$0 if LLM off — but value degrades
ByteRovercuration = own LLM calls (your key or credits)BM25 → LLM fallbackown key tokens or Pro $19/mo
Dangerous default to watch

Auto-retain every turn + large auto-recall is how memory tools quietly burn a subscription — agentmemory has documented incidents of exhausting a Claude Pro quota in a handful of messages. reflect's capture is gated and queued (not every turn), and recall is OOD-gated + token-budgeted — it injects nothing when nothing fits, rather than paying to surface the least-bad note.

07

Observability & correction

When the memory is wrong, can you see it, edit it, delete it, and trace where it came from? This is where "the store is dumb and human-readable" pays off.

reflect — inspect / edit / trace in your editor

  • Inspect & edit: learnings are plain markdown in ~/.claude/global-learnings — open, edit, or delete a note like any file.
  • Clean diffs: volatile signals (recall counts, scores) live in a DB sidecar, so note bytes stay stable and changes are reviewable in a PR.
  • Trace: each learning links back to its source transcript + chunk; commits link to the sessions that produced them.
  • Forget: per-row TTL + contradiction handling revise or expire stale beliefs.

Most others — opaque blobs behind an API

  • Mem0 / Hindsight / Honcho / OpenViking store facts in Postgres + vector DBs — inspection/edit is via API or SQL, not your editor.
  • claude-mem ships a web viewer on :37777, but observations are DB rows, not files.
  • ByteRover is the exception — a human-editable markdown tree (good), though writes still flow through curation.
  • Correcting a wrong memory generally means an API call or a re-curation pass, not a one-line file edit + commit.
08

Self-improvement — how a correction becomes behaviour

This is the wedge. In every other system, a correction is — at best — a sentence in a transcript that an extraction LLM might turn into a fact. Hindsight literally files the case of capturing a skill update as a bug. There is no mechanism that says "the user said stop doing X → make that a rule the agent follows next time."

reflect routes that path as typed signals at hook time — SG1SG8: cross-turn contradiction, git commit/revert (a revert demotes the learnings it produced), test pass/fail, tool-loop, permission reply, idle sweep, negative-recall gaps — and then auto-refreshes the skills those learnings affect (R13/R14). A correction isn't hoping to be extracted from prose; it's captured as a structured event and can revise a belief or promote a skill deterministically.

The one-liner

Everyone else remembers what was said. reflect captures what changed — and turns it into the next session's behaviour.

09

Recommendation & decision rule

1streflect4.72
2ndclaude-mem3.08
3rdByteRover3.06
4thHindsight3.03
Decision rule

Adopt an external memory provider only if it (a) needs no second API key or subscription, (b) runs without a mandatory always-on server, and (c) captures coding signals as typed events. No single external tool clears all three. So: build the thin, differentiated layer (capture + typed signals + local-first), and port — don't re-invent forever — the commodity retrieval, keeping it behind a seam so a stronger backend can be swapped in later.

Verdict: build + port, with eyes open (CAUTION). reflect ported Hindsight's retrieval ideas (graph-expansion arm, RRF fusion, cross-encoder rerank, temporal arm) across a 57-port effort — so it has the retrieval brains without the infra/LLM/ToS baggage, at the cost of owning that code.

Honest sensitivity note. These weights favour self-improvement and zero-friction operation — reflect's strengths. Re-weight toward pure retrieval quality and ecosystem maturity and Hindsight wins: it's MIT, production-grade, benchmarked at 94.6% LongMemEval, with ~48 integrations and 62 releases. If your priority is "best recall, least code I maintain," adopting Hindsight (as a retrieval backend) is the smarter call. The build case rests entirely on valuing no-extra-key capture and typed signals — which is why we keep retrieval swappable rather than sacred.

10

If you'd adopt instead — four pilot acceptance tests

Before swapping in any external tool, run these. They encode the four axes as pass/fail checks.

1 · Zero extra credentials

Install on a fresh machine with only the coding agent's existing auth. Does memory capture + recall work with no new API key or account?

reflect / claude-mem: pass · most others: fail

2 · No always-on server

Reboot. Does memory work with nothing running in the background — no daemon, no Postgres, no vector DB to babysit?

reflect: pass · daemon-based tools: fail

3 · Correction → behaviour

Correct the agent once ("stop bumping the proto without regen"). Next session, does the rule resurface without manual curation?

the typed-signal test — reflect's wedge

4 · Noise over 30 days

Run daily for a month. Is recall still sharp, or flooded with stale / duplicate / fire-hosed entries? Check for a real prune/forget mechanism.

fire-hose tools degrade here