What Is GraphRAG?

GraphRAG

GraphRAG is a retrieval approach that builds a graph of entities and relationships from your documents and retrieves connected context to answer questions. In AI engineering, it helps when an answer depends on relationships spread across many documents, which plain passage retrieval often misses.

For example, suppose a team indexes its incident reports. A user asks, “Which services were affected by the same database change that caused last month’s checkout outage?” Passage retrieval finds the checkout report but not the others. A graph that links the change db-migration-214 to checkout, payments, and inventory can return all three services, along with the reports behind each link.

Try Arize AX

Build better agents with Arize

Trace, evaluate, and learn. Build agents that work with Arize AX and start tracing your runs today.

Prefer open source? Try Arize Phoenix for self-hosted, open source agent observability.

Why GraphRAG matters

Standard retrieval-augmented generation (RAG) retrieves passages that look similar to the question. That works well when the answer sits in one passage. It works less well when the answer is a chain of facts across several documents.

GraphRAG is useful for:

  • Answering multi-hop questions: Follow a path such as outage to change to affected services, where each step comes from a different document.
  • Mapping relationships: Answer questions such as which suppliers are exposed to a given component, where the path is explicit in the graph.
  • Summarizing a corpus: Answer broad questions from summaries of related groups of entities, in implementations that build them.
  • Tracing evidence: Keep a link from every graph edge back to the source text it came from.

For a simple fact lookup in one passage, plain passage retrieval is usually cheaper and easier to debug.

What the name GraphRAG refers to

The name covers two things. It is a general term for a family of graph-based RAG methods. It is also the name of Microsoft’s specific open-source GraphRAG implementation.

When you describe or report results for a GraphRAG system, say which one you mean. Also say how it builds the graph and how it retrieves from it.

How GraphRAG works

GraphRAG has two phases. First you build the graph from your documents. Then, at query time, you use the graph to find context for the model.

Building the graph

A typical pipeline works through four steps:

  1. Extract entities and relationships from each text chunk.
  2. Resolve duplicates, such as the same company appearing under two names.
  3. Store the nodes, the edges, and the source chunks each one came from.
  4. Optionally, detect communities of related entities and write summaries of them.

Microsoft’s GraphRAG documentation describes one concrete version that includes community detection and summaries. Generic graph-based RAG systems may skip community summaries entirely.

The graph is a derived index, not the source of truth. When a document changes, the extractions that came from it need rebuilding.

Retrieving with the graph

At query time, the system finds the entities that the question mentions. It then follows relationships from those entities to related nodes.

For a broad question, it may pull a community summary. For a specific question, it may pull the underlying source chunks. That structured context goes to the model alongside, or instead of, plain retrieved passages.

How GraphRAG retrieval looks in code

The following sketch shows the two hops from the incident example on a tiny in-memory graph. Each edge stores the IDs of the source chunks it was extracted from. The node names and chunk IDs are hypothetical.

# Each edge is (source node, relation, target node, source chunk ids).
edges = [
    ("checkout outage", "caused_by", "db-migration-214", ["inc-0412#1"]),
    ("db-migration-214", "affected", "checkout", ["inc-0412#3"]),
    ("db-migration-214", "affected", "payments", ["inc-0415#1"]),
    ("db-migration-214", "affected", "inventory", ["inc-0419#2", "inc-0419#5"]),
]

def follow(node, relation):
    return [(dst, chunks) for src, rel, dst, chunks in edges
            if src == node and rel == relation]

# Hop 1: find the change behind the outage named in the query.
change, cause_chunks = follow("checkout outage", "caused_by")[0]
print(f"checkout outage caused_by {change}: cite {', '.join(cause_chunks)}")

# Hop 2: collect every service that change affected, with its evidence.
for service, chunks in follow(change, "affected"):
    print(f"{change} affected {service}: cite {', '.join(chunks)}")

Output:

checkout outage caused_by db-migration-214: cite inc-0412#1
db-migration-214 affected checkout: cite inc-0412#3
db-migration-214 affected payments: cite inc-0415#1
db-migration-214 affected inventory: cite inc-0419#2, inc-0419#5

The answer should cite those chunks, not the graph edges alone. The edges are only as reliable as the extraction that produced them.

This is why the developer still checks the returned chunks. Suppose entity resolution had merged two different database changes into one node. The graph would then confidently return the wrong set of services.

How to evaluate GraphRAG

Evaluate retrieval and generation separately. Otherwise you will confuse graph errors with generation errors.

Use RAG evaluation to answer two questions. Were the right chunks or subgraphs retrieved? Did the answer use them correctly? Retrieval quality metrics judge the candidate set before generation.

Compare against a passage-only baseline

Run GraphRAG and a passage-only system on the same questions. Include straightforward lookups where the graph should not help. If GraphRAG does not beat the baseline on the questions it was meant for, the extra complexity is not paying off.

Hold your chunking strategy fixed during the comparison. Chunking changes the results of both systems.

Debug a wrong answer in order

When GraphRAG gives a wrong answer, check each stage in turn:

  1. The extracted entities and edges for the query.
  2. The retrieved chunks.
  3. The generated answer.

A wrong edge and a misread chunk need different fixes. A wrong edge means fixing extraction or entity resolution. A misread chunk means fixing generation.

Limitations of GraphRAG

  • Extraction errors: Extraction can invent relationships that are not in the text or miss ones that are.
  • Wrong merges: Entity resolution can merge two distinct things into one node.
  • Stale graphs: After documents change, a graph that has not been rebuilt gives misleading answers.
  • Smoothed summaries: Community summaries can hide a source that disagrees with the rest.
  • Build and refresh cost: Building and refreshing the graph takes model calls, and the index must be maintained as documents change.
  • Unproven accuracy claims: Claims that GraphRAG is generally more accurate are not safe without a comparison on your own task.

GraphRAG vs. vector retrieval

Embeddings and vector search retrieve passages by meaning. They need no extraction pipeline.

GraphRAG adds explicit relationships and corpus-level summaries. The price is extraction errors, index maintenance, and harder debugging.

GraphRAG augments retrieval. It does not remove the need to inspect the passages an answer rests on. Many designs keep passage retrieval and add graph context on top, or use the graph to select passages.

Agentic RAG is a different idea. In agentic RAG, an agent chooses its own retrieval steps, and those steps may or may not use a graph.

Adaptive knowledge graph memory uses a graph to store an agent’s memory. That is not the same as indexing a document corpus for question answering.

Frequently asked questions

Is GraphRAG a Microsoft product or a general method?

Both. Microsoft GraphRAG is a specific open-source implementation, and GraphRAG is also used as a general term for graph-based RAG. Name the implementation when you report results.

When is GraphRAG worth the extra complexity?

It is worth it when your questions need multi-hop relationships or synthesis across a corpus, and a passage baseline demonstrably misses them. Prove that with a comparison set before you commit to maintaining a graph.

Usually not. Many designs keep passage retrieval and add graph context, or use the graph to choose passages. The source chunks remain what an answer should cite.

How do I debug a wrong GraphRAG answer?

Check the extracted entities and edges for the query first. Then check the retrieved chunks, and finally the generated answer.

Why does my GraphRAG system return outdated answers?

The graph is probably stale. It is a derived index, so extractions from changed documents must be rebuilt before the graph reflects the change.

Putting GraphRAG to work

Start with a set of questions your current retrieval misses, and confirm they genuinely need relationships across documents. Run GraphRAG and a passage-only baseline on that set and on simple lookups.

Store the source chunk IDs on every edge, and make answers cite those chunks. Plan for rebuilding extractions whenever documents change.

Trace each query through entity lookup, graph traversal, chunk retrieval, and generation. Tools such as Arize Phoenix can capture those retrieval steps as spans, so you can tell a wrong edge from a misread chunk.

Example

A user asks which services were affected by the database change behind last month's checkout outage. Passage retrieval finds only the checkout report, but a graph links change db-migration-214 to checkout, payments, and inventory, each with its source chunks. The answer cites those chunks, which is only safe if entity resolution did not merge two different changes.

Don’t ship vibes.

Arize gives AI teams observability and evals to understand and improve agent performance.