graphite-mem: The memory layer that knows when to forget

Graphite Memory blends graph and vector retrieval with decay, suppression, and scoped sessions so an agent remembers what matters, not everything it has seen.

11 min read • View on GitHub • More from mishrak5j

A lone archivist stands between a net of linked index cards and a stack of fading notes, choosing which ones to keep close to the workbench. The scene explains the project's central idea: memory is not just stored, it is scored, cooled down, and filtered before it reaches the model.
Graphite Memory treats recall as selection, not accumulation.
Key Takeaways

Most AI memory systems fail by accumulation. They keep everything, then hope retrieval will rescue the right piece. Graphite Memory takes a stricter view: memory should decay, suppress, and scope itself so the prompt stays sharp.

What this repository is actually building

The codebase is small, opinionated, and easy to map. cmd/graphite-mem starts the service, internal/storage splits persistence between Chroma and Neo4j, internal/ingestor writes to both, internal/governor decides what rises to the top, and internal/vault adds session scope and inhibition. That shape matters because this is not just a database wrapper. It is a policy layer for context.

What's missing is a **temporal validity dimension on relationships**. When a fact changes — e.g., a user says "I work at Company A" in January, then "I just joined Company B" in March — both memories persist, but there's no mechanism to mark the first relationship as superseded. Graphiti (by Zep, ~24k stars) solves exactly this on top of Neo4j, and could complement MemOS's existing graph layer

brentkearney, Contributor, MemOS · MemOS issue #1257

The governor is the point

The governor merges semantic and structural evidence, then applies decay and suppression before context is assembled.

When a query lands, Graphite Memory fires two searches in parallel. One looks for semantic neighbors in Chroma, the other looks for structural relations in Neo4j. If a memory appears in both places, the governor gives it a boost. That is the core bet, that overlap is stronger than either signal alone.

score := vectorScore
if inGraph {
    score *= 1.5
}
score *= math.Exp(-lambda * hoursSinceCreated)
if suppressed {
    score *= negativeWeight
}
if overThreshold {
    coolDownFor(kTurns)
}

The forgetting logic is not a delete. It is a score transform. Temporal decay uses exponential drop-off, so an old memory can still exist without dominating a newer correction. Frequency suppression then cools down memories that keep getting injected, which helps long-running agent loops avoid fixation.

Ingestion turns prose into structure

The ingestion path does two different jobs at once. llm.ExtractTriples converts raw text into subject-predicate-object triples for Neo4j, while the original text is embedded into Chroma. That gives the system two ways to answer a question. One path is about meaning. The other is about relationship.

The vault adds the part most memory systems skip. Sessions can mount or unmount scopes, so a user can focus on a project path like /projects/cli without dragging everything else into the conversation. The InhibitPastContext flag goes one step further and temporarily mutes older memories without deleting them. That is a subtle but valuable distinction for task switching.

I'm one of the authors of Graphiti, an open-source library for building and querying temporal Knowledge Graphs. We see personal assistants and agents as a core use case for Graphiti.

danielchalef, Author, Graphiti · AnythingLLM issue #2227

How it compares

SystemStrengthTrade-off
Vector-only RAGFast semantic lookupMisses relationships, recency, and repetition pressure
GraphitiTemporal truth on graph edgesLess focused on prompt pressure and session policy
Mem0 or MemOSBroad memory frameworksMore abstraction can hide retrieval behavior
Graphite MemoryA governor that blends vector, graph, decay, and suppressionYou trade simplicity for tighter control over context

That comparison is the real story. Graphite Memory is for builders who want a local, inspectable memory governor, not a black-box memory service. Because it speaks MCP and leans on Go, Ollama, Neo4j, and Chroma, it fits the self-hosted stack where control, latency, and data boundaries matter.