Neo4j Agent Memory: Model Facts and Retrieve Context
Neo4j stores agent memory as a graph of connected facts, which suits knowledge that has meaningful relationships between entities. Here is how to design the graph, track provenance, test retrieval, and pair it with a shared project record.
Updated 4 min read
Neo4j stores agent memory as nodes and relationships, which makes it natural to model facts that are connected to each other: a person works at a company, a task depends on a decision, a term is defined by an approved rule. Retrieving a fact means following the relationships rather than scanning rows.
Graph memory is more expressive than a flat key-value store but also more complex to design and maintain. Tools like fenbs keep the shared project brief, the approved decisions, and the links between them in a separate record that any connected assistant can read without a Cypher query.
When graph memory is a good fit for agents
Graph memory suits agents that work with entities and their relationships: a research agent tracking authors, papers, and citations; a knowledge agent managing terms, definitions, and their source documents; a code agent tracking modules, dependencies, and the decisions that shaped them. If the memory is mostly independent key-value facts, a graph adds complexity without benefit. If relationships between facts are what the agent needs to reason over, a graph is the right structure.
Start by listing the three or four entity types your agent works with and the relationships between them. If the list naturally forms a network (A refers to B, B was approved by C), a graph is worth the setup. If the list is flat (a set of independent facts), use a simpler store. See what is agent memory for a comparison of storage models.
A knowledge graph also handles contradictions better than a flat key-value store. Two conflicting facts about the same entity can coexist as separate nodes with different provenance and confidence scores. The agent retrieves both and applies a resolution rule, such as preferring the more recent assertion or the one from a higher-trust source, rather than silently overwriting one with the other.
Designing a graph memory schema for agents
Keep the schema minimal. Each node type should represent one clear concept: a Fact, a Source, a Decision, a Person. Each relationship type should represent one clear connection: SUPPORTS, CONTRADICTS, DECIDED_BY, SUPERSEDES. An overly rich schema with many node types and relationship types is hard to query and hard to maintain.
Add a few standard properties to every node: a unique ID, a timestamp of when it was created, and a status (active, archived, superseded). These properties let you filter for current facts, retrieve the history of a node, and mark outdated entries without deleting them. Deletion removes the audit trail; archiving preserves it.
Tracking provenance
Provenance answers the question: who asserted this fact, based on what evidence, and when? In a Neo4j graph, model provenance as a relationship property or as a separate Assertion node. An Assertion node connects a Fact node to a Source node and carries a confidence score, a timestamp, and the agent or person that made the assertion.
Provenance matters when the agent retrieves a fact and the fact turns out to be wrong. With provenance, the source of the error is traceable: you can see which session asserted the wrong fact, from which source, and when. Without provenance, a wrong fact looks the same as a correct one. For a wider look at memory safety and attribution, see agent memory security.
Keep the project brief alongside the knowledge graph
A Neo4j graph is the right home for interconnected facts about a domain. The shared project record, the approved decisions, and the links to where the work is listed or referenced belong in fenbs. Connect your assistant from /integrations so it reads the project context from fenbs before querying the graph.
Create a free accountFree for one person · No credit card · Works with Claude, ChatGPT, Cursor and more
Testing retrieval with Cypher
Write a retrieval test after adding your first batch of nodes. A good test queries a fact by a known attribute and confirms the result matches what was stored. In Cypher:
MATCH (f:Fact {key: 'contact-form-approved'})
RETURN f.value, f.createdAt, f.statusRun the query after writing the node and confirm it returns the correct value. Then run it again after restarting the Neo4j instance to confirm the data is durable. A result that appears in the first query but not the second means the write did not commit to disk. Check your Neo4j persistence configuration if that happens.
Handling updates and superseded facts
Do not delete a fact when a newer version supersedes it. Instead, change the old node's status to superseded, create a new node with the updated value, and add a SUPERSEDES relationship from the new node to the old one. The old fact is still queryable, its history is intact, and the agent can retrieve only active facts by filtering on status.
This pattern is especially important for decisions. A decision changed by a later one should still be readable so that someone reviewing the history can understand why the project took the path it did. The SUPERSEDES chain tells the whole story. See what is agent memory for more on memory lifecycle management.
How to do this with fenbs
Use Neo4j for the agent's domain knowledge graph. Use fenbs for the project record, the approved decisions, and the links to where the work is referenced.
- Create a free account and add your project to fenbs. Record the standing decisions and any important external links in Links and listings.
- Connect your assistant from /integrations and ask it to read fenbs context before querying the Neo4j graph.
- Design a minimal graph schema: two or three node types, three or four relationship types, and standard properties (ID, timestamp, status) on every node.
- Add provenance properties to each Assertion: source, agent, timestamp, and confidence.
- Write a Cypher retrieval test and run it after restarting Neo4j to confirm that stored facts are durable.