Naive GraphRAG retrieves a fixed neighborhood and hopes the answer is in it. Production GraphRAG lets an LLM drive traversal — planning a path through the graph, deciding hop-by-hop where to go next, and stopping when it has enough. This day is about making that loop fast, cheap, and observable: bounding traversal cost, caching subgraphs and embeddings, holding a latency budget, and surviving the failure modes that only show up at scale.
The beginner course built a GraphRAG pipeline that does this: extract entities from the question, look them up in the graph, pull a fixed k-hop neighborhood, dump it into the prompt. That works for "who is the CEO of Acme?" It falls apart on "which suppliers of Acme's competitors had a recall in the last two years?" — a question whose answer lives several hops away along a path you can't know in advance.
A static k-hop fetch has two failure modes that pull in opposite directions:
You cannot pick one k that is right for every question. The fix is to stop pre-deciding the shape of the subgraph and instead let the LLM decide where to go next, one step at a time.
Agentic (or iterative) GraphRAG reframes retrieval as a control loop:
The crucial difference from naive RAG: the LLM never sees the whole graph. It sees a local view and steers. This is the same shape as a ReAct agent, with the "tools" being graph operations (expand, get_neighbors, get_node) instead of web search.
The single most important design choice: when you show the LLM the current frontier, show it the available relationship types ("Acme has 3 outgoing SUPPLIES edges, 12 COMPETES_WITH edges, 1 HEADQUARTERED_IN edge") rather than the raw list of neighbor nodes. The LLM picks an edge type to traverse; you then materialize only those neighbors. This keeps the per-step observation small even at a supernode, and it turns the LLM's job into typed query planning rather than scrolling a giant list.