A coding agent fixes a tricky deployment failure. Two weeks later, another session sees the same failure described in different words. The expensive part is not finding a nearby document chunk. It is deciding whether a past conclusion is safe enough to reuse.
That distinction is why I think agent memory needs more than vector similarity.
Vector search is excellent at finding semantic neighbours. Ask for help with a Docker healthcheck and it may find memories about container startup, service discovery, or a previous networking issue. Those can be useful leads.
But a ranked list is not a decision. The top result may be merely adjacent: it may apply to a different framework version; describe an abandoned approach; be true only under an unstated deployment constraint; or have been superseded by a later architectural decision.
For a human, these are normal caveats. For an agent working under time and context pressure, treating the nearest neighbour as an answer can turn retrieval into a subtle source of confident mistakes. The question is not only “what is semantically close?” It is also “have we seen this problem closely enough before to make that prior learning part of the current reasoning?” A useful memory system can expose different operations for different levels of certainty.
Verified recall is the narrowest path. It returns one candidate only when multiple signals support the match; otherwise it says that the match is weak or absent. The important output is not just a snippet, but a gate: STRONG, WEAK, or MISS.
A STRONG result is still evidence, not an instruction. The agent should inspect the returned context and decide whether it fits. A WEAK result should encourage investigation rather than shortcut it. A MISS tells the agent to solve the problem normally instead of inventing continuity.
Hybrid retrieval is broader. Semantic similarity is valuable, but it should be combined with lexical signals. Exact terms often carry disproportionate meaning in engineering work: a configuration key, exception type, table name, package version, or command flag. Dense retrieval captures paraphrase; BM25 preserves those precise anchors. Reciprocal-rank fusion is a practical way to blend independent rankings without pretending either is universally correct.
Graph exploration answers a third question: what else is connected to this? A deployment failure may touch a prior decision about ingress, a known local-development exception, and a later supersession. Those relationships are often more useful than another ten chunks with similar embeddings. Exploration should favour diversity and keep the relationship visible, rather than flattening everything into one similarity score.
This changes what we store. A codebase index asks: “What documents might answer this query?” Agent memory asks: “What did the agent learn that would be expensive to rediscover?”
Good memory entries are compact and explicit: the root cause and fix; the architectural choice and why it was made; a framework or infrastructure gotcha; a constraint that rules out an appealing approach; or a failed experiment worth not repeating.
Lifecycle matters too. If a decision changes, deleting the old memory loses context; leaving it untreated risks a stale answer. A better model marks the old learning as superseded and links it to the newer one. History remains inspectable while retrieval can favour what is current.
There is no universal threshold at which a match becomes safe. A recall system has to decide its false-positive and false-negative trade-off. For an agent that proposes code changes, false positives are costly: a plausible but stale memory can send work down the wrong path. For an agent doing background research, a false negative may be less harmful: it can simply search more broadly. Confidence should therefore be exposed as part of the contract rather than hidden inside a score.
A practical evaluation loop should include failures, not just happy-path hits: paraphrases of the same historical problem; near misses involving a different version, environment, or dependency; contradictions and superseded decisions; exact-identifier queries that vectors may dilute; and small noisy stores where every result appears relevant. The goal is not a leaderboard score. It is to learn when the system should stay silent.
I am building these ideas into Graft, an Apache-2.0 local memory layer for coding agents. Its core is a C11 daemon backed by SQLite, FTS5, sqlite-vec, llama.cpp, and local BGE-M3 embeddings. It does not require a SaaS account, external embedding API, or external LLM call for its storage and retrieval loop.
Graft keeps the three paths separate: confidence-gated query, hybrid retrieve using vector search plus BM25 title/body search with reciprocal-rank fusion, and explore for semantic and keyword relationships. It is an active alpha, and the cross-encoder reranker is scaffolded rather than active today; verification currently uses vector similarity plus lexical signals.
If you are building long-running coding-agent workflows, I would value feedback on the hard part: what evidence would make you willing—or unwilling—to reuse a prior agent learning?