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.
- Graphite Memory is a control layer for context, not just a place to store it, because it blends vector similarity, graph structure, recency, and suppression before anything reaches the model.
- Its strongest idea is that good memory should cool off as well as persist, so repeated or stale facts do not dominate long-running agent sessions.
- The repository is built like a policy engine around two stores, with Chroma handling semantic recall and Neo4j handling structure, then a governor deciding what survives.
- MCP support makes the design portable across assistant surfaces, which turns the project into a practical local-memory stack instead of a one-off demo.
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
The governor is the point
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.
How it compares
| System | Strength | Trade-off |
|---|---|---|
| Vector-only RAG | Fast semantic lookup | Misses relationships, recency, and repetition pressure |
| Graphiti | Temporal truth on graph edges | Less focused on prompt pressure and session policy |
| Mem0 or MemOS | Broad memory frameworks | More abstraction can hide retrieval behavior |
| Graphite Memory | A governor that blends vector, graph, decay, and suppression | You 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.