Field note

Agent Memory That Beats Grep: How I Built Heimdall

Why agents redo work, how I built Heimdall — a verified, self-healing knowledge layer for AI coding agents — and how it compares to graphify and Graft.

Agent Memory That Beats Grep: How I Built Heimdall

Originally published on my blog. Repo: github.com/ArihantDeva/heimdall

The problem: agents redo work because their memory is search, not retrieval

Every agent session starts cold. That’s the hidden tax of working with AI coding agents: no matter how many times an agent has solved a problem, the next session begins with zero knowledge of it.

I’ve been building with agents for a while now, and the pattern that cost me the most wasn’t slow loops or bad prompts — it was rework. The same pipeline, the same fix, the same architecture decision, rebuilt three times in three different project directories, because the agent starting each session had no idea the work already existed.

Grep can’t fix it. The answer to “did I already solve X?” lives in a different project’s file, described in prose, under a path you don’t know. A single LLM query is a coin flip — it hallucinates, or it returns one flat hit with no indication of whether the file is even still on disk.

The realization that changed my approach: agents needed a memory layer that returned ranked, verified, reusable work — not text matches.

So I built one. It’s called Heimdall, it’s open source (MIT), and the part that makes it work is the part nobody builds: the trust verification layer.

Three pieces, each solving a distinct failure mode.

1. A persistent graph store

Every completed fix, pattern, or decision is recorded as a node — title, body, keywords, and edges to related work — in a local semantic memory daemon.

I did not reimplement the vector engine. The store is Graft, a local-first semantic memory daemon (SQLite + local embeddings + graph edges, Apache 2.0). It provides hybrid lexical + vector ranked retrieval, keyword dedup, and a local embedding model (bge-m3) that runs entirely on-device.

Proper attribution up front: Graft is the storage and ranking engine; Heimdall is the orchestration layer on top — watching agent sessions, keeping the graph fresh, and making results trustworthy. That split is the honest story, and it’s the right architecture: don’t rebuild a vector store, build the layer that makes one usable by an agent.

2. Ranked retrieval + graph walk

Search returns top-k candidates scored by a hybrid of lexical and semantic similarity, then walks the graph to surface related work you didn’t know you had.

Ask about a resume-tailoring pipeline and you get the pipeline, the scoring script you forgot about, and the gotcha notes — edges are part of every search, not an afterthought. The graph walk is the difference between searching and remembering: it surfaces the work your future self needs, not just the exact string your past self wrote.

3. The verification layer — the actual novel part

Every hit gets a trust verdict before it’s shown:

  • STRONG — the anchor path exists on disk and has strong lexical coverage
  • WEAK — semantic match, path exists
  • STALE — path gone → auto-rehome (find where the file moved) or auto-remove
  • REBUILT — stale node found its new home, rebuilt in place

An agent acting on a dead path is worse than no answer. The verdict is what makes the graph actable: my agent trusts a STRONG hit enough to reuse it without re-verifying, and STALE hits get cleaned up instead of poisoning future searches.

Why it beats the alternatives

grepsingle LLM queryHeimdall
finds prose knowledge~
ranked candidatesone flat hit✓ top-k
path verified on disk✓ verdicts
discovers related work✓ graph walk
survives file reorgs✓ self-healing

How it fits with the tools you already know

If you’ve seen code-graph tools, the natural question is: isn’t this what graphify or Graft already do? Fair — here’s the honest split.

Graphify builds a per-repo AST+semantic graph (graphify-out/graph.json) from your source, LLM-extracts nodes, and answers questions by BFS-walking that graph with a token budget. It answers codebase questions — “where does this function live, what calls it” — with precise, token-cheap context. What it doesn’t do: persist across projects, or tell you whether a node’s file still exists. It’s a code graph, not a memory.

Graft (Apache 2.0) is the semantic memory backend: a local daemon with SQLite + local embeddings + graph edges, hybrid lexical/vector retrieval, and verified semantic caching. It’s the storage and ranking engine — the hardest part to build well. But a backend isn’t a system: it needs something to watch sessions, keep the graph fresh as files move, and label hits so an agent can trust them.

Heimdall is the layer between. It watches agent sessions and auto-syncs the graph (edits, moves, deletes, bulk renames), verifies every hit with a trust verdict, guards against grep-habit, and orients agents at session start.

graphifyGraftHeimdall
scopeone repoone daemonall projects
contentcode AST+semanticnotes/factsnotes + code + session edits
queryBFS over graph.jsonhybrid rankedranked + graph walk
trust verdictspartial✓ STRONG/WEAK/STALE
session auto-sync
reorg self-healing
drop-in✗ (code-only)✗ (backend)✓ (orchestrates Graft)

All three are useful; they’re just different layers. Graphify gives you a code map, Graft gives you a store, Heimdall is the agent-integration layer that makes retrieval trustworthy.

The lesson: memory is a systems problem

The insight that generalizes: agent memory fails not from lack of storage but from lack of retrieval with trust.

Any agent harness — Claude Code, Cursor, Copilot, a custom agent — could ship this. The components are small: a graph store, a session watcher, a verifier, a guard. None of it is hard. The hard part is noticing that this is the missing layer — and that grep-shaped thinking is why agents keep re-doing work.

In practice it paid for itself: I stopped rebuilding pipelines that already existed, and sessions now start with relevant prior work injected instead of from zero. A concrete example: I needed an ATS-scoring check for a resume workflow. A year ago that was a fresh build — grep for “ats” returns a dozen unrelated files, a single query returns one guess. With Heimdall, one search returned the scoring script I’d forgotten, its calibration notes, and a gotcha note about a parser quirk — ranked, verified, reusable in seconds. That’s the difference between an agent that redoes work and one that compounds it.

Open source

The repo is at github.com/ArihantDeva/heimdall — MIT licensed, with:

  • extensions/ — kb-tools.ts, kb-orient.ts, kb-autosync.ts, kb-search-guard.ts + lib/kb-guard-core.mjs (pure JS, zero deps)
  • bin/ — kb-search.sh, kb_search_verify.py (the trust verifier), sync-edits.sh, kb-health.sh, kb-stale-scan.py, telemetry.sh, seed-graft.sh, kb-rebuild.sh, kb-rehome.sh
  • config/ + launchd/ templates — plug into any semantic-memory backend with a retrieve/insert/explore CLI

The Graft binary is not bundled — Heimdall detects it and degrades gracefully. Install Graft, point bin/ at it, done.

If you run agents across multiple projects, this is the missing layer.