Neo4j GraphRAG
Neo4j GraphRAG stores your data in a Neo4j graph and answers questions from it. In a graph, data is connected: each incident with its customer, its machine and the technician who handles it. That is why it answers questions that cross relationships (“which open incidents does the technician who serves this customer have?”) or that count and compare (“which customer has the most incidents?”), where a text-only search falls short.
The same component does both halves of the work. Operation decides which one, and the node shows only the fields of that operation:
- Store: Add Records turns rows (from a table, a sheet or a database) into nodes and relationships without writing Cypher. Build Graph reads documents with an AI model and extracts their entities and relationships.
- Find and answer: Vector and Hybrid search by meaning and by words; Vector + Graph and Hybrid + Graph also bring the nodes related to each result; Text2Cypher writes the query that answers the question; Cypher Query runs a query of yours with values the agent fills in; Graph Schema describes what the graph contains.
This is how a history is stored in Neo4j, from records and from documents, and an agent built that queries it without writing Cypher:
What you see in the video
- Storing records (flow “Neo4j GraphRAG · store records”): Storage Files reads
incidents.jsonwith Content set to Text, and Neo4j GraphRAG in the Add Records operation stores each incident with Node LabelIncident, Key Propertycodeand three lines in Relationships that link it to its bar, its technician and its machine. Run it: 24 incidents, 72 relationships and both search indexes created automatically, in under a second. - Graph Schema shows what the graph holds now: the labels with how many nodes each has, their properties with sample values, the relationships and the indexes.
- Storing documents (flow “Neo4j GraphRAG · store documents”): Storage Search finds the three monthly PDF reports, Storage Files reads them in batch, and Neo4j GraphRAG in the Build Graph operation extracts the entities with DeepSeek, guided by Allowed Patterns, Node Types and Extraction Instructions. Result: 40 nodes and 72 relationships from the text.
- The agent (flow “Neo4j GraphRAG · agent”) has three Neo4j GraphRAG tools: “A technician’s incidents” in Cypher Query, with a fixed query whose
$technicianand$statusthe agent fills in; “Similar cases” in Hybrid + Graph with the Retrieval Query left empty, which brings just each result’s neighbours; and “Query the graph” in Text2Cypher, with two examples in Examples. - “Which open incidents does Lucía Ortega have?”: the agent calls the fixed query with
technicianLucía Ortega andstatusopen, and answers with all three, each with its bar and machine. - “An Aurora is not dosing and shows E07: has this happened before, and who fixed it?”: the search finds the two identical cases, fixed by Javier Ruiz and Rocío Benítez by replacing the VL-1180 flowmeter.
- “How many incidents has each brand had?”: Text2Cypher writes the counting query (Vellani 9, Jaltec 8, Molinar 7). You can see the query it wrote by opening the tool call.
When to use it
- You have records with fields (incidents, orders, contracts) and want to load them into Neo4j with their relationships to ask about them: Add Records.
- Your information is in documents (reports, work orders, emails) and you want to turn it into a graph of entities and relationships: Build Graph.
- Your users ask how many, which one has the most, who has or what is pending: questions answered by counting or filtering records, not by reading a paragraph. Text2Cypher or Cypher Query.
- You want to find similar cases to a description with all their context (customer, technician, machine): Hybrid + Graph.
- You want an agent to query the graph on its own, as a tool, without anyone writing queries.
Operations
Storing data
| Operation | What it does |
|---|---|
| Add Records | Each row that reaches Ingest Data becomes a node of type Node Label, identified by Key Property: if the key already exists, the node is updated instead of duplicated. The columns you list in Relationships become linked nodes (the customer, the technician, the machine). It computes each row’s vectors with Embedding and creates the search indexes. It uses no AI model. |
| Build Graph | A Language Model reads each document in Ingest Data and extracts the entities and relationships your schema asks for (Allowed Patterns and Node Types). It merges the mentions of the same entity (ignoring case and accents, also with the ones already in Neo4j) and, when a later document changes a value, such as the status, it keeps the most recent one. Long documents are read in parts. With Save Source Chunks it also stores each text, linked to the entities it mentions. |
Finding and answering
| Operation | What it does |
|---|---|
| Vector | Finds the nodes whose text is closest in meaning to the question. |
| Hybrid | Searches by meaning and by words at the same time. Useful when the question contains names, codes or exact references. |
| Vector + Graph / Hybrid + Graph | Like the previous ones and, in addition, returns each result with the nodes it is connected to: an incident’s customer, technician and machine, for example. You don’t need to write anything; to choose what to bring yourself, write a Retrieval Query. |
| Text2Cypher | The model reads the structure of the graph, with its real values, and writes the query that answers the question. It is the operation that counts, sorts and filters over the whole graph. If the query fails or finds nothing, it reviews it once. |
| Cypher Query | Runs a query you write, with gaps ($technician) that are filled in on each run. Used as a tool, each gap is a value the agent writes. It is always exact and uses no model. |
| Graph Schema | Returns what the graph contains: node types with how many there are, their properties with example values, the relationships and the search indexes. |
Text2Cypher, Cypher Query and Graph Schema only read: if a query tried to create, change or delete data, Neo4j refuses it. Only Add Records and Build Graph write.
To find out which way of storing suits your data and what each one costs, see GraphRAG with Neo4j.
Configuration
You need a Neo4j API credential with the address, user and password of your database. See Credentials.
| Field | What it does |
|---|---|
| Credential (required) | The Neo4j API credential. Fills in Neo4j URL, Neo4j Username and Neo4j Password. |
| Operation | What the component does. Default: Vector. |
| Search Query | Vector, Hybrid, ”+ Graph” and Text2Cypher. The question. When an agent uses the component as a tool, the agent writes it. |
| Node Label | Add Records (required). The type of node each row becomes, for example Incident. In Build Graph it is optional: the type of node you want to be able to search by meaning. |
| Key Property | Add Records. The column that identifies each row, for example code. If you leave it empty, codigo, code, id or name is used, the first one the rows have. |
| Relationships | Add Records. Which columns become linked nodes, one per line: column -> RELATIONSHIP -> Type.property. Columns in brackets are stored on that node. See the example. |
| Allowed Patterns | Build Graph. The graph’s schema, one connection per line, for example (Incident)-[:FOR_CUSTOMER]->(Customer). Only those node and relationship types are kept. If you leave it empty, the model decides. |
| Node Types | Build Graph. The node types, separated by commas, with their properties if you want to fix them: the first one identifies the node and, after a colon, the only values it accepts. For example, Incident(code, date, status: open | closed), Customer(name). |
| Save Source Chunks | Build Graph. Also stores each text as a Chunk node linked to the entities it mentions, searchable with the chunk_vector index. |
| Examples | Text2Cypher. Questions with the query that answers them. See Examples for Text2Cypher. |
| Cypher Query | Cypher Query. The query that runs. Each $name you write becomes a field of the node and, as a tool, a value the agent fills in. |
| Retrieval Query | ”+ Graph”, optional. What to return for each result, where node is the node found and score its score. If you leave it empty, each result comes with its related nodes. |
| Vector Index | Name of the search-by-meaning index. When storing, if you leave it empty, one is created with the node type’s name, for example incident_vector. When searching, if you leave it empty, the only one in the database is used. |
| Full-text Index | Name of the search-by-words index, with the same rule: storing creates, for example, incident_text; searching uses the only one there is. |
| Ingest Data | Add Records and Build Graph. Bottom connector. The rows or documents to store. |
| Embedding | Bottom connector. The model that turns text into vectors. Use the same one to store and to search. |
| Language Model | Bottom connector. Build Graph and Text2Cypher. The model that extracts the entities or writes the query. |
The connectors sit at the bottom of the node so they stay visible when the component hangs from an agent’s Tools.
Advanced options
| Field | What it does |
|---|---|
| Database | The database inside Neo4j. Default: neo4j. |
| Relationship Types | Build Graph. Relationship types separated by commas. Not needed if they are already in Allowed Patterns. |
| Write Query | Add Records. A Cypher query run for each row (row) instead of Node Label, Key Property and Relationships, for full control. Each row’s vector is in row.embedding. |
| Extraction Instructions | Build Graph. Guidance for the model, for example how to write a name: “A machine model is written without its brand”. |
| Parallel Requests | Build Graph. How many texts the model reads at the same time (1 to 20, default 5). |
| Full-text Analyzer | Add Records and Build Graph. The language of the search-by-words index (english, spanish…), so that “faults” finds “fault”. Default: standard. |
| Text Property | The node property with the text that is vectorized, indexed and returned. Default: text. If a row has no text, its descripcion, description, summary or content is used. |
| Number of Results | How many results are returned, 1 to 100. Default: 5. In Text2Cypher and Cypher Query, a query can return up to 20 rows per result, so a long list arrives complete. |
Output
- Results: in every operation. The search results, the query’s rows, the description of the graph or the summary of what was stored (how many nodes and relationships, and which indexes were created). When a query finds nothing, it returns the query that ran, so an agent can try again with other values.
- Retriever: in Vector, Hybrid, ”+ Graph” and Text2Cypher, to connect it to components that ask for a retriever.
Use as an agent tool
Connect Neo4j GraphRAG to the Tools input of an Agent. Depending on the operation, the agent writes:
| Operation | What the agent writes | Default tool name |
|---|---|---|
| Vector, Hybrid, ”+ Graph” | The question (Search Query) | neo4j_graph_search |
| Text2Cypher | The question | neo4j_graph_query |
| Cypher Query | One value for each $name in the query | neo4j_cypher_query |
| Graph Schema | Nothing | neo4j_graph_schema |
In the Tool tab, Tool Name and Tool Description are the name and explanation the agent uses to decide when to use the tool. When you change the operation, ones that fit it are proposed; change them to say what your graph contains: “Queries the technical service’s incidents, customers, technicians and machines: how many, whose, in what status”.
Examples
All the examples use the incidents of a coffee machine technical service: 24 incidents from July to September, each one with its customer, technician and machine.
1. Loading records with Add Records
The rows come, for example, from a spreadsheet, with the columns code, date, customer, technician, model, brand, error_code, description and status.
-
Select Add Records and connect the rows to Ingest Data and FastEmbed Embeddings (Local) to Embedding.
-
Node Label:
Incident. Key Property:code. -
Relationships:
customer -> FOR_CUSTOMER -> Customer.nametechnician -> ASSIGNED_TO -> Technician.namemodel -> ON_MACHINE -> Machine.model (brand) -
In advanced, Full-text Analyzer:
english. -
Run it. The result says: “Wrote 24 record(s) into Neo4j as Incident merged by code; relationships: 24 FOR_CUSTOMER, 24 ASSIGNED_TO, 24 ON_MACHINE. Indexes: incident_vector, incident_text.”
The graph ends up with 24 incidents, 8 customers, 4 technicians and 4 machines (each machine with its brand), and each incident’s description as its text. If you run it again, nothing is duplicated: each incident is updated by its code, and if a row changes technician, the old relationship is replaced by the new one.
If you prefer to write the query, for example to store the date as a date, put this in Write Query:
MERGE (c:Customer {name: row.customer})MERGE (t:Technician {name: row.technician})MERGE (m:Machine {model: row.model}) SET m.brand = row.brandMERGE (i:Incident {code: row.code})SET i.text = row.description, i.status = row.status, i.date = date(row.date), i.error_code = row.error_code, i.embedding = row.embeddingMERGE (i)-[:FOR_CUSTOMER]->(c)MERGE (i)-[:ASSIGNED_TO]->(t)MERGE (i)-[:ON_MACHINE]->(m)With Node Label Incident, the indexes are created the same way.
2. Building the graph from documents with Build Graph
The monthly reports tell the same incidents in text.
-
Select Build Graph. Connect the documents to Ingest Data, a model to Language Model and the embeddings model to Embedding.
-
Allowed Patterns:
(Incident)-[:FOR_CUSTOMER]->(Customer)(Incident)-[:ASSIGNED_TO]->(Technician)(Incident)-[:ON_MACHINE]->(Machine) -
Node Types:
Incident(code, date, status: open | closed, error_code), Customer(name), Technician(name), Machine(model, brand). -
Node Label:
Incident. In advanced, Extraction Instructions: “A Machine model is written without its brand (Brío 2G, Aurora 3G, M64 OD); the brand goes in brand.” and Full-text Analyzer:english. -
Run it. With the 9 documents of the knowledge base (manuals, policies and reports), the result was the same graph as with Add Records: 24 incidents, 8 customers, 4 technicians, 4 machines and 72 relationships, all of them correct, with the final status of the incidents that were closed a month later.
3. Finding similar cases with Hybrid + Graph
- Select Hybrid + Graph and connect the same Embedding model. Leave Vector Index, Full-text Index and Retrieval Query empty.
- Ask “The coffee machine leaks water through the portafilter”. Each result arrives like this:
Incident INC-2608-05 (date: 2026-08-19, status: closed): Water leaking through the portafilter of group 2 without any error code. The portafilter gasket was hardened and cracked. The JT-120 gaskets of both groups and the shower of group 2 were replaced. ON_MACHINE -> Machine Brío 2G (brand: Jaltec) ASSIGNED_TO -> Technician Lucía Ortega FOR_CUSTOMER -> Customer Bar Los ArcosVector and Hybrid return only each incident’s text, without its related nodes.
4. Answering with Text2Cypher
- Select Text2Cypher and connect a model to Language Model.
- Write two or three typical questions with their query in Examples (see Examples for Text2Cypher).
- Ask “How many open incidents is Lucía Ortega assigned?”. The model writes
MATCH (i:Incident)-[:ASSIGNED_TO]->(t:Technician {name: 'Lucía Ortega'}) WHERE i.status = 'open' RETURN count(i) AS totaland the result istotal: 3.
5. A fixed query with Cypher Query
When the question always has the same shape, write the query yourself and leave the values to the agent:
MATCH (i:Incident)-[:ASSIGNED_TO]->(t:Technician {name: $technician})WHERE i.status = $statusOPTIONAL MATCH (i)-[:FOR_CUSTOMER]->(c:Customer)RETURN i.code AS incident, c.name AS customerThe node shows the fields technician and status. Fill them in or connect the component to an agent: the tool asks it for technician and status, and with “Lucía Ortega” and “open” it returns INC-2608-02 (Bar La Giralda), INC-2609-02 (Café Alameda) and INC-2609-06 (Cervecería Macarena). Values arrive as text; to compare them with a number, use toInteger($value).
6. Seeing what the graph contains with Graph Schema
Select Graph Schema and run it. The result, shortened:
- Incident (24) code (String): e.g. 'INC-2607-01', 'INC-2607-02', … (24 different values) status (String): one of 'closed', 'open' date (Date): from '2026-07-03' to '2026-09-29'- Technician (4) name (String): one of 'Javier Ruiz', 'Lucía Ortega', 'Manuel Campos', 'Rocío Benítez'- (:Incident)-[:ASSIGNED_TO]->(:Technician) (24)Search indexes:- incident_vector: vector on Incident.embeddingIt helps you write the Text2Cypher examples or a Cypher Query, and, as a tool, lets an agent know what it can ask.
Examples for Text2Cypher
Text2Cypher already shows the model the graph’s real names and values. The examples in Examples also teach it the shape of your questions. Write question and query pairs, with your graph’s names, that cover what your users ask: counting with filters, going through several relationships and filtering by dates.
Question: How many closed incidents does Rocío Benítez have?Cypher: MATCH (i:Incident)-[:ASSIGNED_TO]->(t:Technician {name: 'Rocío Benítez'}) WHERE i.status = 'closed' RETURN count(i) AS total
Question: Which customers had incidents on Jaltec machines in August?Cypher: MATCH (i:Incident)-[:ON_MACHINE]->(m:Machine {brand: 'Jaltec'}), (i)-[:FOR_CUSTOMER]->(c:Customer) WHERE i.date >= date('2026-08-01') AND i.date < date('2026-09-01') RETURN DISTINCT c.name AS customerThe examples don’t have to match the real questions. If you store dates as text (for example with Add Records without Write Query), the month filter is written i.date STARTS WITH '2026-08'.
Good practices
- Use the same Embedding model to store and to search; otherwise the vectors are not compatible.
- In Build Graph, always write the schema: Allowed Patterns and Node Types with their properties. Without a schema, the model invents different names for the same thing in each document.
- If a property can only take some values, declare them in Node Types (
status: open | closed): a different value never replaces a good one. - For questions that count or compare, use Text2Cypher or Cypher Query. Searches (”+ Graph” included) only see the results they find.
- With several indexes in the database, write the one you want in Vector Index and Full-text Index.
- For an agent that serves customers, use a Neo4j user that can only read in the credential.
Related components
- Neo4j: stores documents in Neo4j as a vector store.
- SelfQueryRetriever: search with filters on a vector store.
- Local Rerank: reorders a search’s results by relevance.
- Agent: the agent that can use this component as a tool.
To choose how to store your data and compare the techniques with figures, see GraphRAG with Neo4j.