Neo4j Agent Memory: What It Ships and How It Works
Neo4j Agent Memory gives agents three memory layers in one graph. How its vector index, GraphRAG retrievers, and the Cypher SEARCH clause actually work in 2026.
Table of Contents
Ask an agent “what did the person who approved this budget decide about the last similar request” and a vector store returns text that sounds like the question. It does not return the chain — person, to approval, to prior decision — because it never stored one. Neo4j Agent Memory closes that gap by storing the memory as a graph, where the chain is data rather than something the model has to infer.
This piece covers what Neo4j specifically ships for agent memory: the Agent Memory framework, the neo4j-graphrag-python retrieval library, and the native vector index. It is not a general graph-database primer and it does not benchmark Neo4j against other stores.
TL;DR: what Neo4j actually ships for agent memory
| Piece | What it is | Status |
|---|---|---|
| Neo4j Agent Memory | Three memory layers — short-term conversations, long-term entities and facts, reasoning traces — in one graph | Neo4j Labs, Apache-2.0, labelled experimental and community-supported |
| Neo4j Agent Memory Service (NAMS) | Hosted endpoint so you run no Neo4j yourself; same Python and TypeScript SDKs | Hosted, API-key based |
| Native vector index | Semantic search inside the graph, created and queried in Cypher | GA since Neo4j 5.13 |
Cypher SEARCH subclause | Preferred way to query a vector index, with in-index filtering | Neo4j 2026.01+, Cypher 25 only |
neo4j-graphrag-python | Official retriever library: vector, vector-Cypher, hybrid | Apache-2.0, generally available |
One line if you only read one: the reason to put agent memory in Neo4j is that vector similarity and relationship traversal happen in the same query, and the reason to be careful is that the memory framework on top of it is still an experimental Labs project.
Where this sits next to our other graph pages
If the vector-store-versus-graph decision is not settled yet, start with vector databases versus knowledge graphs for RAG — that is the storage-category page, and it comes before this one.
For how Neo4j compares against other graph platforms on pricing, governance and features, see the enterprise knowledge graph platform comparison. For measuring a GraphRAG pipeline once it is built, see how to evaluate GraphRAG pipelines. This page covers only Neo4j’s own agent-memory surface.
Why do AI agents need more than vector search for memory?
Standard RAG retrieves chunks of text that are semantically similar to a query. That works for pulling relevant documentation, but it treats every fact as an isolated snippet. An agent tracking decisions, people, and projects over months needs to know how those facts connect.
Neo4j’s positioning is straightforward: graphs let an agent reason about relationships between things it remembers, not just retrieve things that sound alike. Traversing “which project does this person own, and what changed after their last decision” requires following a chain. Flat vector similarity has no concept of one.
The gap shows up clearest in multi-hop questions, which need at least two edges: person to decision, decision to outcome. A vector search returns text that resembles the words in that question, not the chain of facts it depends on.
None of this means vector search stops mattering. Semantic similarity is still how an agent finds the right starting point in a large memory graph. The difference is what happens after that starting point is found.
What is Neo4j’s Agent Memory framework?
Neo4j Agent Memory is an Apache-2.0 licensed Neo4j Labs project that gives an agent three distinct, connected memory layers inside a single graph.
| Layer | What it stores | Notable features |
|---|---|---|
| Short-term | Conversations and experiences | Semantic message search, session scoping, metadata filters, LLM-generated summaries |
| Long-term | Facts, entities, preferences | POLE+O entity classification, entity deduplication, temporal fact validity, geospatial queries |
| Reasoning | Tool usage and reasoning traces | Trace similarity search, tool-call statistics, message-linked traces, streaming trace recording |

Read the status line before you design around it. Neo4j marks the project Experimental · Community Supported, and neo4j-agent-memory on PyPI is classified Development Status :: 4 - Beta. That is a fine basis for a prototype and a real risk for a system you plan to run for two years.
There are two deployment shapes. Point the SDK at your own Neo4j over Bolt — Aura, Docker, or Desktop — when you need write-Cypher access, geospatial features, or air-gapped operation. Or use the hosted Neo4j Agent Memory Service with an API key and run no database yourself.
Entity extraction is a pipeline, not a black box
Conversations get parsed into structured entities and relationships without a team hand-modelling every entity type first, which is usually the slowest part of standing up a graph.
The extraction itself is a configurable multi-stage pipeline rather than a single LLM call. Neo4j combines spaCy for fast rule-based and statistical NER, GLiNER2 for zero-shot extraction against domain schemas, GLiREL for relation extraction, and an LLM fallback for ambiguous text, with eight prebuilt domain schemas including medical, legal, news and POLE+O.
That matters for cost and drift. Running spaCy and GLiNER2 first means most extraction happens without an API call, and the domain schema is the lever that keeps extracted types consistent across sessions. Five merge strategies decide how the extractors’ outputs get reconciled, and streaming extraction handles documents past 100K tokens without loading them whole.
Extracted entities are then enriched in the background against Wikipedia and Wikidata — descriptions, images, Wikidata IDs, and coordinates on location entities, which is what makes the geospatial queries usable. Useful, and also a second source of drift to watch: enrichment attaches external identifiers your agent did not assert.
The sharing model splits along the layers
Conversations and reasoning traces are isolated by session_id, so one agent never reads another’s chat history by accident. Entity, Preference and Fact nodes are shared: when one agent learns something, the next agent sees it on its next query with no manual sync.
A user_identifier parameter scopes reads and writes per end-user on top of that, which is what makes one backend serve many tenants. Python and TypeScript agents pointed at the same endpoint share memory transparently, because both SDKs implement the same REST contract.
Framework integration is already live outside Neo4j’s own tooling. Microsoft’s Agent Framework ships a documented Neo4j Memory Provider that plugs Neo4j in as a persistent memory backend rather than a static RAG knowledge base, recalling relevant memory before each agent run and persisting new memory after.
Microsoft’s documentation draws that distinction explicitly. A static RAG source answers from fixed documents; the memory provider accumulates and updates facts as the agent keeps running.
Neo4j lists first-party integrations well beyond that. On the Python side: LangChain, PydanticAI, LlamaIndex, CrewAI, OpenAI Agents, AWS Strands, Google ADK, Microsoft Agent Framework and AgentCore. On the TypeScript side: Vercel AI SDK, LangChain JS, Mastra, AWS Strands and MCP tools. There is also an MCP server, hosted and self-hosted, so an MCP-speaking client can read and write the memory graph without an SDK at all.
How does GraphRAG work on Neo4j?
The neo4j-graphrag-python library is the official, Apache-2.0 Python package for building GraphRAG pipelines against Neo4j. It ships retriever classes plus an index management API, and the two retrieval strategies below solve different problems.
Vector search retrieval
This is semantic search over Neo4j’s native vector index. Vector indexes have been generally available since Neo4j 5.13. Since Neo4j 2026.01, the preferred way to query one is the Cypher SEARCH subclause, used inside a MATCH or OPTIONAL MATCH:
MATCH (movie:Movie)
SEARCH movie IN (
VECTOR INDEX moviePlots
FOR $queryVector
WHERE movie.releaseDate > date('1990')
LIMIT 4
) SCORE AS score
RETURN movie.title AS title, score
The WHERE inside SEARCH is in-index filtering: the search keeps going until it finds the requested number of results that also satisfy the predicate. A WHERE outside the SEARCH is post-filtering, which can return far fewer rows than the LIMIT suggests. That difference is the reason to be on 2026.01 or later.
In-index filtering has limits worth knowing before you design a query around it. The filtered properties must have been declared as additional properties when the index was created, the predicate can only combine terms with AND, and IN inside a SEARCH filter only works from Neo4j 2026.06.
There is a language gate on top of the version gate: SEARCH is Cypher 25 only. A session pinned to Cypher 5 will not see the subclause even on a 2026.01+ server, which is the version check teams miss when an upgrade appears not to have worked.
The library handles the version split for you. supports_search_clause() reads the connected server version and uses the SEARCH path only at 2026.01 or above, falling back to the db.index.vector.queryNodes() procedure otherwise — and it also catches SEARCH-specific Cypher errors at runtime and retries on the procedure path.
Do not write new code against db.index.vector.queryNodes() directly. Neo4j deprecated it and db.index.vector.queryRelationships() as of Neo4j 2026.04; they still work on older servers, which is exactly why the library keeps them as a fallback rather than a default.
Vector-Cypher retrieval (hybrid)
This is where graph memory earns its keep. A vector search first finds anchor nodes by semantic similarity. From those anchors, a Cypher query traverses the graph to pull in connected context that similarity search would never surface on its own.
An agent asking “what does this person usually decide in situations like this” needs both at once: similarity, to find past situations that resemble the current one, and traversal, to follow that person’s actual decision history from there.

Vector-Cypher retrieval runs both steps as one query instead of two lookups stitched together by application code. The retrieval logic stays in the database layer rather than scattered across a client pipeline, which matters once several agents need the same behaviour.
Setting up Neo4j for agent memory: key technical building blocks
The library’s index management API wraps the raw Cypher for creating, checking and dropping vector indexes into a few Python calls, and it is the layer most integration code calls day to day. Understanding the underlying Cypher still helps, because index configuration is the setting hardest to change later.
CREATE VECTOR INDEX moviePlots IF NOT EXISTS
FOR (m:Movie) ON m.embedding
WITH [m.releaseDate, m.rating]
OPTIONS { indexConfig: {
`vector.dimensions`: 1536,
`vector.similarity_function`: 'cosine'
}}
The WITH [...] list declares the additional properties available for in-index filtering later, and it requires Neo4j 2026.01 or later. The type allowlist is narrower than it looks: only INTEGER, FLOAT, STRING, BOOLEAN, DATE, ZONED DATETIME, LOCAL DATETIME, ZONED TIME, LOCAL TIME and DURATION are indexed. A property of any other type — a list, a map, another vector — is treated as null by the index, so a filter on it silently matches nothing. vector.similarity_function accepts 'cosine' or 'euclidean' and defaults to 'cosine'. vector.dimensions accepts an integer from 1 to 4096.
Setting vector.dimensions is optional but recommended, and skipping it is the mistake that costs the most. With it set, Neo4j rejects vectors of the wrong size and returns an error if you query with a mismatched dimension. Without it, the index will happily hold vectors of different dimensions side by side, and only same-dimension vectors are ever compared — so a model swap mid-project silently splits your memory into two halves that never match each other.
There is no ALTER for this. Changing an index’s dimensions means dropping and recreating the index, then re-embedding whatever is already stored.
One thing to keep straight: the Agent Memory SDKs are Python and TypeScript only. Neo4j itself ships official drivers for Python, JavaScript and TypeScript, Java, .NET and Go, all speaking the same Bolt protocol — so a Java or Go service can read and write the same memory graph directly in Cypher, it just will not use the Agent Memory client to do it.
Neo4j Agent Memory vs. vector-database-only memory
The two approaches stop being interchangeable once relationships between facts matter for what the agent has to answer. The Neo4j column below reflects Neo4j’s own documentation; the vector column reflects the general characteristics of that product category rather than any single vendor.
| Capability | Neo4j (graph + vector) | Vector-database-only |
|---|---|---|
| Semantic similarity search | Yes, via native vector index | Yes, this is the core function |
| Relationship / multi-hop reasoning | Yes, via Cypher traversal | No native support |
| Automatic entity extraction | Yes, multi-stage pipeline in Agent Memory | Not typically built in |
| Multi-agent shared memory | Yes, shared Entity/Fact nodes, per-session isolation | Depends on application layer |
| Schema flexibility | Property graph, extraction-driven | Flexible, but no relationship modelling |
| Query language | Cypher | Vendor-specific query API |
| Operational burden | One more stateful database to run and tune | Usually lower |
Neither column wins everywhere. A vector-only memory layer is simpler to operate when an agent’s memory genuinely is unrelated snippets. The graph column earns its complexity once “who decided what, and what followed from it” is a question the agent has to answer.
Real-world patterns for using Neo4j as agent memory
The clearest pattern is the long-running co-builder agent. Six months into a project, an agent relying on flat text similarity re-derives the same relationships repeatedly from scattered mentions, while a graph-backed agent traverses a relationship that was recorded the first time it came up.
Multi-agent collaboration is the second. A support agent and a billing agent working the same account do not need each other’s transcripts, but both benefit from the same facts about that customer, their plan, and their open issues living in one place.
The third pattern addresses enterprise data sprawl. Neo4j’s material on its Enterprise Knowledge Layer describes an ontology-based semantic layer that helps agents navigate large, fragmented sources by connecting related information, rather than querying several disconnected systems.
Feature names and scope in that last area are still moving as Neo4j builds out this product line. Check current Neo4j documentation before treating it as a fixed boundary to design against.
Common pitfalls when using Neo4j for agent memory
Extraction drifts unless you pin a schema. Automatic extraction can model the same real-world thing two different ways across sessions, and nothing throws an error when it does. Pick one of the eight domain schemas, or define your own entity types, rather than running fully open-ended extraction.
Not everything needs to be a graph. Short-lived session context is often simpler kept as plain conversation history. Forcing every scrap of context through entity extraction adds cost without adding retrieval value if it is never reused.
Version requirements are easy to miss. The SEARCH subclause and in-index filtering need Neo4j 2026.01 or later on a Cypher 25 session, and IN inside a SEARCH filter needs 2026.06. On older deployments the legacy procedure has no in-index filtering, so query patterns built around it need rework on upgrade.
Experimental status is a real constraint. Agent Memory is a community-supported Labs project on a beta package. Read the changelog before upgrading and pin the version.
How Future AGI evaluates an agent built on Neo4j memory
Future AGI does not store agent memory and there is no Neo4j-specific connector to point at. What it does own is the layer above: proving the agent consuming that graph is retrieving the right nodes and actually using them. Future AGI is open source and self-hostable, so you can sign up or run the whole stack inside your own network next to the database.
Score the traversal, not the sentence. Evaluate ships retrieval built-ins — Precision@K, Recall@K, NDCG@K, MRR, Hit Rate, Context Relevance, Chunk Attribution, Chunk Utilization and Groundedness. One practical detail decides whether they work on graph memory: these evaluators match on exact string equality, so score against stable node identifiers such as elementId, never against generated text that varies run to run.
Check the agent used what it retrieved. A correct traversal and a wrong answer look identical from the database side. Groundedness and Context Relevance close that gap by asking whether the response is actually supported by the nodes the traversal returned.
Trace the retrieval step itself. Observe is built on traceAI, our open-source OpenTelemetry instrumentation library. Retrieval becomes its own span with latency, inputs, outputs and cost alongside the model call, which is what tells you whether a bad answer came from a slow or wrong traversal rather than the LLM.
Group the recurring failures, and get a fix with them. Error Feed reads a sample of production traces, at a sampling rate you set, and clusters same-failure traces into one issue with evidence, so a traversal that keeps returning the wrong hop appears once instead of four hundred times. Errors are classified against a 30-plus taxonomy that includes ungrounded summary and dropped context — the two failure modes a graph-memory agent produces most — and each issue carries an immediate patch and a longer-term architectural recommendation, each with a confidence score.
Conclusion
Neo4j’s value for agent memory is structural. It stores the relationships between facts rather than only the similarity between text chunks, and the native vector index plus neo4j-graphrag-python let one query combine both retrieval modes instead of syncing two systems.
Two dependencies decide whether it fits. The SEARCH subclause and in-index filtering need Neo4j 2026.01 or later on a Cypher 25 session, and the Agent Memory framework on top is an experimental, community-supported Labs project on a beta package — fine for a prototype, worth a hard look before a two-year commitment.
A memory layer still needs an evaluation layer above it. Knowing the graph exists, and even that retrieval is fast, does not confirm the agent is using that memory correctly. That is the question to answer before shipping, and it is the one Future AGI is built for.
Frequently Asked Questions
What is Neo4j Agent Memory?
Does Neo4j support vector search natively?
What is the difference between GraphRAG and standard RAG?
Can multiple AI agents share the same Neo4j memory graph?
Do I need a separate vector database if I use Neo4j for agent memory?
How do you evaluate an agent that uses Neo4j graph memory?
Vector databases vs knowledge graphs for RAG in 2026. Pinecone, Weaviate, Qdrant, Milvus, Chroma vs Neo4j, GraphRAG, LightRAG. Decision matrix.
Neo4j, Amazon Neptune, Stardog, Ontotext GraphDB, and TigerGraph compared on deployment model, query language, governance, licensing, and GraphRAG readiness.
Base RAG metrics miss the graph underneath GraphRAG. Here is a three-layer framework, runnable graph metrics, and answer scores that isolate each failure.