AI Engineer World's Fair 2025
Agentic GraphRAG: Simplifying Retrieval Across Structured & Unstructured Data — Zach Blumenfeld
Read the talk
Agentic GraphRAG: From Resume Search to Shared Project Evidence
An employee assistant needs more than relevant resumes to count skills or find collaborators. A small knowledge graph gives its retrieval tools explicit relationships to query and extend.
From a talk by Zach Blumenfeld
Before you start: Familiarity with embeddings, agent tools, and basic database queries will help; graph concepts are introduced through the employee example.
Give the agent a model of the data
How should an agent retrieve information when part of the answer lives in documents and part lives in structured records? Zach Blumenfeld’s Neo4j Employee Graph notebook walkthrough starts with an architecture that puts a knowledge graph between those sources and the agent’s retrieval tools. Document extraction brings in unstructured information; standard ETL brings in structured data. Both feed the model the agent queries.
That shared model matters when retrieval becomes a sequence of operations. An agent can decompose a question into several queries rather than make one vector search and answer from its results. A small, explicit data model helps it decide what to retrieve and how the pieces fit together. The model can then grow as additional sources arrive. Here, the starting point is an employee graph.
Suggest correction
This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.
Five retrieved resumes are not a workforce count
The employee assistant should support skills analysis, team substitutions, collaboration discovery, and identifying skill gaps. Its first source is a folder of PDF resumes for Cyberdyne Systems—the Terminator reference—with professional experience and descriptions of work. Blumenfeld initially loads each resume into Neo4j as a document node containing text, metadata, and an embedding. The database is a graph database, but this first retrieval path treats it as a document store.
An agent built with Google’s Agent Development Kit receives instructions to retrieve information and one tool: document search. Asked how many Python developers the company has, it reports five because the retrieval setting is K = 5. Blumenfeld explicitly identifies that answer as wrong: the agent has turned the size of its retrieved result set into a claim about the whole workforce. A retrieval limit is not an aggregation.
Suggest correction
This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.
Similarity, distributions, and collaboration need different operations
Entity extraction and additional metadata could help with the counting problem. The next question exposes a different limitation: who is most similar to a particular employee in skills or experience? Lucas is a full-stack AI engineer with Python, JavaScript, and machine-learning experience. The agent uses those descriptions as search terms to retrieve similar resumes. That can find plausible candidates, but the explanation reveals semantic search rather than an explicit, controllable comparison of skill sets.
As the questions broaden, the missing operations become clearer:
| Question | What document search does | What the answer requires |
|---|---|---|
| Summarize technical talent and skills distribution | Retrieves resumes using selected terms | Aggregate skills across employees |
| Find people collaborating on many projects | Searches for collaborators | Connect people through shared projects |
A useful workforce summary needs counts and distributions, not just relevant examples. Likewise, searching for the word “collaborators” does not establish who worked with whom. Resumes may contain that evidence, but the relationships remain buried in text.
Suggest correction
This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.
Extract people, skills, and accomplishments
The next step is to express the questions’ requirements at the data layer. Start with three concepts: people, skills they know, and things they do. Entity extraction turns the resumes into that graph. The accomplishment model then becomes more specific: someone published, built, won, led, managed, optimized, or shipped something. Those things connect to domains and work types, allowing related activities to meet at shared concepts rather than relying on similar wording.
Blumenfeld uses Pydantic models and enumerations to define accomplishment types, domains, and work types. A compact Python version of that extraction contract can look like this; the domain and work-type vocabularies here are illustrative:
python
from enum import Enum
from pydantic import BaseModel, Field
class Action(str, Enum):
PUBLISHED = "published"
BUILT = "built"
WON = "won"
LED = "led"
MANAGED = "managed"
OPTIMIZED = "optimized"
SHIPPED = "shipped"
class Domain(str, Enum):
AI = "AI"
ANALYTICS = "analytics"
DATA_ENGINEERING = "data engineering"
class WorkType(str, Enum):
SYSTEM = "system"
CODE = "code"
class Thing(BaseModel):
name: str
domain: Domain
work_type: WorkType
class Accomplishment(BaseModel):
action: Action
thing: Thing
class EmployeeExtraction(BaseModel):
name: str
skills: list[str] = Field(default_factory=list)
accomplishments: list[Accomplishment] = Field(default_factory=list)
The schema constrains the structure and allowed values of extraction output. It does not establish whether an extracted skill or accomplishment is factually correct.
The extraction workflow—Blumenfeld recalls using LangChain here—decomposes the documents and produces JSON containing each person’s skills and accomplishments. Loading that JSON into Neo4j creates a more expressive model: people connect through shared skills, the things they worked on, and higher-level concepts describing that work. Those connections become queryable evidence for the assistant’s answers.
Suggest correction
This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.
Count and compare through explicit relationships
The next agent receives similar instructions plus a description of the graph’s data model. An MCP server gives it access to the schema and supports the Cypher query workflow. The useful division of labor is schema inspection, language-model query generation, and database execution; MCP is the interface connecting those capabilities, not the reasoning mechanism itself.
Now the Python-developer question can match people connected to the Python skill and aggregate the matches. Blumenfeld reports twenty developers from the graph query, describing the result as much closer to correct. That is a result from the demonstration’s extracted graph, not an independently established workforce total. With illustrative labels and relationship names, the operation is:
cypher
MATCH (person:Person)-[:KNOWS]->(:Skill {name: 'Python'})
RETURN count(DISTINCT person) AS python_developers;
The Cypher aggregation counts distinct matched people rather than retrieved documents. DISTINCT prevents repeated matches for the same person from inflating this count; completeness still depends on the people and skill relationships present in the graph.
The same similarity question—who is most similar to Lucas Martinez, and why?—now returns Sarah. The explanation uses shared skills and the sizes of the compared skill sets; Blumenfeld says some runs also consider similar accomplishments. The useful change is that the comparison refers to inspectable relationships and an overlap calculation, rather than only search-term selection.
That also gives corrections a concrete target. If a person has an incorrect skill relationship, it can be audited and changed in the graph. The assistant can then aggregate those same relationships to summarize how many people know each skill, or break down accomplishments. The data model makes both the answer and the underlying evidence easier to inspect.
Suggest correction
This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.
Add tools for richer employee comparisons
Generated Cypher is not the only retrieval option. Blumenfeld adds specialized tools alongside it, including a query that traverses between person IDs. He describes a zero-to-three-hop traversal that can follow connections through skills, common systems, domains, and accomplishments. This broadens the evidence for similarity beyond a direct skill match.
Because the query explores relationships, Blumenfeld says an added collaboration or project link could also be picked up by that traversal. The scope is still determined by the query’s allowed paths and hop bounds. He also claims flexibility and higher performance for complex graph traversals, but presents no performance benchmark.
With these tools available, the Lucas Martinez comparison returns more detailed evidence: numbers associated with shared skills and domains such as AI, analytics, and data engineering. The agent can use the retrieved connections to explain how the employees’ work overlaps, instead of giving only a broad statement that their resumes are similar.
Suggest correction
This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.
Extend individual accomplishments into shared work
The final source is structured internal data from a human resource information system, or HRIS. It describes projects and collaboration among the same people already represented by the resumes. This introduces information the initial extraction model did not capture: multiple employees working on the same thing.
Resume ingestion began with an ownership assumption: a person could have many accomplishments, but each accomplishment belonged to one person because it came from that person’s resume. Shared project records change that relationship to many-to-many.
For the relational design Blumenfeld describes, representing shared ownership would require a join table and a model refactor. In the graph, additional relationships can connect multiple people to shared work. New node and relationship types can also be introduced as sources and agent requirements expand. The existing people and their resume-derived skills remain useful; the new collaboration data adds another way to connect them and another class of questions to ask.
Suggest correction
This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.
Find who delivered AI work together
A collaboration tool now matches people working on the same thing within selected domains. Asked which individuals collaborated to “deliver the most AI things,” the agent can invoke that operation against shared project relationships. It no longer needs to approximate collaboration by searching resume text for the term.
The resulting answer identifies Sarah Chen and Dr. Amanda Foster and lists their shared AI projects; it also includes other collaboration evidence involving supply-chain work. The final demonstration brings the two sources together: resumes establish skills and individual experience, while structured project records establish shared work. The assistant can answer who collaborated by returning the projects that connect them.
Suggest correction
This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.
Resources
From the talk
Employee-assistant notebooks combining resume documents and HRIS records, with Google ADK agents, graph construction and retrieval tools.
Current documentation for building agents with instructions, function tools and MCP integrations.
Define typed Python models and validate, serialize and generate schemas for structured data.
Further reading
Experimental MCP servers for Neo4j schema inspection, Cypher execution and other graph operations.
Reference examples for graph aggregations, including counts with and without duplicate matches.
Read the complete timestamped transcript
- 0:00
[upbeat music] I'm gonna go over today GraphRAG, particularly dealing with multiple data sources, uh, so both unstructured and structured data sources and kind of why you would wanna ever do that in the first place even.
- 0:25
So I prepared, uh, some notebooks here. I was gonna make slides, but then I thought it would just be easier to walk through some of what this looks like in practice.
- 0:34
Um, so there's a link here, and I can share it with you at the booth later, um, if you have follow-up questions. But basically, uh, what I wanted to show you first is just what a general GraphRAG architecture looks like.
- 0:46
Right? And so basically what we do is we have our agents, right, we have our tools, just like you normally would, but then in the middle here, you see off to the side, we have this knowledge graph.
- 0:56
And this knowledge graph you can ig- both extract data from documents and unstructured places and also have standard ETLs for structured data. And so there's a big question of why in the hell you would want this knowledge graph thing sticking in the middle there.
- 1:10
And I could talk about accuracy and explainability, but I think what's really valuable to talk about is kind of what this means going forward with agents and how it's valuable for agentic workflows.
- 1:20
And as we think about some of what agents can do with reasoning and decomposing questions, a lot of the retrieval that we're seeing is not so much just a straight shot vector search anymore.
- 1:32
A lot of what we're seeing is a question being broken down and being handed multiple queries, right, to go and pull the data that you need. And the great thing about having a knowledge graph is that you can express a very simple data model to get started to your agent, which can help it do that decomposition, pull
- 1:48
information accurately, and then as you sort of expand, you can keep adding more and more data. The example that I'm gonna show you here inside of these notebooks is gonna be for a, uh, employee graph.
- 2:00
So basically, think about a knowledge assistant that's responsible for helping pull information around skills analysis, um, look for similarities or substitutions in a team and try to figure out who's collaborating, where skill gaps are, all that sort of stuff.
- 2:14
And the data that we're gonna start with today is just gonna be in resumes. I just have these PDFs, just like a folder of resumes, um, that are pretty standard.
- 2:22
It just lists people's professional experience and descriptions. Um, it's for a company called, uh, what did we have here? Cyberdyne Systems, if anyone's familiar with them.
- 2:35
A little Terminator reference. All right. Um, so anyway, the first thing that I'm going to do to just show you what this looks like is I'm going to load documents into the Neo4j Graph database, but just sort of as, like, basically documents.
- 2:50
Chump, basically take every resume, put an embedding on it. What it looks like here if I was to, if I was to scroll here, is kinda like this. So basically, you know, I have these different nodes, but you'll see the nodes are basically just gonna have some metadata, some text, which is the resume, and then an embedding.
- 3:08
And basically what I'm going to do is I'm just gonna create an agent inside of ADK, so Google's framework, and I'm gonna start asking it some of those questions.
- 3:17
And so basically what you're gonna see here, and I don't have time, unfortunately, to walk through all of the code, but basically if you look at this agent that's been constructed, right, I have my agent, I have some instructions to pull data, and then I give it one tool, which is a tool to go search documents, right?
- 3:34
And so I'm gonna ask it a question: How many Python developers do I have? You can imagine, right, this is probably not gonna work out very well if all I have is just documents.
- 3:44
Because basically it's gonna tell me I have five Python developers. And that's because I set K equal to five, right, when I went to go pull my documents. So obviously that's gonna be wrong, and I'm telling you that that answer, that answer is wrong.
- 3:56
So you could probably solve that with doing some entity extraction and putting more metadata, right, on your nodes. So that's, so that's fine. So then I'm gonna ask who is most similar to a particular person in terms of just their skill set or what they've done.
- 4:09
Um, and again, here what you'll see, and I've told it in the bottom to kind of explain what it's doing, um, if I go down to the display here, um, it, it'll tell me basically here that what it's doing is it's just gonna be using search terms to go pull information.
- 4:26
So this might help you find similarity to a certain extent. Like, it knows, you know, Lucas is, is a full stack AI engineer and he does, you know, Python, JavaScript, and some machine learning stuff, I guess.
- 4:37
Um, so you can search for that and you can find some similar people, but the logic is still a little bit hard to control. It's just sort of, you know, plain semantic similarity search.
- 4:46
Um, and as I start to go down, I can ask questions like, summarize my technical talent and skills distribution. It's not gonna be able to answer that, right? 'Cause it needs to be able to do an aggregation to answer a question like that.
- 4:57
So if I was to go up and look at the logic again, or I'll go down here, um, it could say I search, you know, employee's resumes using certain search terms and stuff, right?
- 5:06
And so it's basically if I go down and ask these questions, it's just gonna be using search terms to find things. And so that's not really good enough for our use case because we wanna do analytics, we wanna do aggregations, and we wanna try to find relationships between people.
- 5:20
Um, and again, like in the last question, I basically asked it to find who's collaborating on lots of projects, and alls it can do is search for collaborators, which is not really what I want.
- 5:29
Like, what I want is to find who's been collaborating with who on different projects, right? And the resume data, you know, might have that, but it's all, you know, sunk inside of the text and stuff, so, so it can't really do that.
- 5:40
So the question is now, well, how do I think about basically explaining my data to my agent and then also making sure, right, that I have a data model that makes sense?
- 5:51
So if you think about it, you can do this at the data layer. You can think about, how do I wanna model my data just to start for some of these beginning questions?
- 6:00
And here it's basically like I wanna know what a person is, so I need that. I want some concept of a person knowing skills, and then the only other thing that I really care about is what do people do?
- 6:13
Like, what things do they do, right? Very simple. That's just the data model that I want to express. So I'm gonna do entity extraction of these documents to basically create this graph.
- 6:24
And really, it's gonna be just slightly more complicated than that because basically what I need to do here is I actually need to create a graph where, right, I have instead of just doing things, I have publish, built, won, led, managed, optimized, shipped things, and then those things are gonna belong to different domains and work types, um,
- 6:46
which is gonna allow me to kinda connect similar things together inside of the graph. So it's, it's a little bit more complicated, but it's, it's the same exact concept.
- 6:56
Um, and basically the entity extraction workflows we use, um, are pretty, um, self-explanatory. They use, um... If I was to go here, I use Pydantic classes to do that.
- 7:08
So I have concept of enumerations on the types of accomplishments and domains that I want and work types as well. I define my things. I define how someone does a thing through an accomplishment.
- 7:19
Um, and then basically I put that through, um, another workflow. Um, I think I use LangChain in this case, uh, to basically decompose those documents and spit out a bunch of JSON.
- 7:31
And inside of that JSON, for example, for this person, I have their skills, right, that I get in here, and I also have their accomplishments that I get inside of here.
- 7:40
Um, so I can go ahead and load that as well into my graph, and now I have a much more expressive data model. So if I go back to here and scroll up
- 7:54
and look at this guy, this is now kind of what my data model looks like, right? I have my people, but now you see how they're connected by all of these different skills that they have, as well as the things that they're actually working on and how those things connect to higher level concepts like whether it's, you
- 8:10
know, um, building something for a system or shipping code, doing all those sorts of things. And now, because I have that expressive data model, I'm able to start having a lot more precision around the way that I get my questions, uh, basically answered.
- 8:27
So what I do here, after all this graph construction, which I already talked through,
- 8:32
is I create this other agent, give it a similar set of instructions. I tell it a little bit about my data model in here, and then I'm actually gonna be using this MCP server that allows it to read the schema and also generate Cypher statements.
- 8:48
Um, so this is an MCP tool that we just have, you know, out on GitHub that you can pull. Now, when I ask how many developers I have, now I can actually do a query that's gonna match on person node skill Python.
- 9:01
And because of that, I get an answer that's much closer to correct, which is twenty developers, right? That's very simple. That's just aggregation. But now I can ask a similarity question, right, like I did before.
- 9:12
Who is most similar to Lucas Martinez, and why? So this is the same exact question. And when I went to go, uh, calculate that, I got an answer that it's Sarah.
- 9:23
And it will explain the reasoning that it did. It searched for people w-- who knew, um, the same skill sets. Sometimes when I ask this, it will also search for people who have similar accomplishments as well.
- 9:34
Um, and it will explain exactly like, "Hey, like I did an overlap calculation in the graph to figure out basically, you know, given the number of skill sets they had and the number of overlap, this is the person that I think is the closest."
- 9:47
So the benefit of doing this is that you have much more control, and you can go in and filter exactly what skills people have. So, for example, if I knew someone actually didn't have a certain skill or did have a certain skill, I can audit that.
- 9:59
I can adjust the graph to be able to make that work. Um, and then similarly, as we go down, to summarize a technical talent distribution, um, again, I can match on those skills, and I can start to answer these questions and actually get numbers between how many people know different skills.
- 10:16
Um, and it can also break down different accomplishments and other things of that nature. So you just get much more refinement in the types of answers, uh, that you get for your questions.
- 10:25
Um, I can also add additional tools. Uh, so instead of just generating, uh, Cypher kind of, um, on the fly with the language model, I can also-- and I'll show you what some of these look like in, uh, my bigger screen here.
- 10:42
I can go ahead and, uh, move this up.
- 10:48
So this is an example of finding people with similar skills here that I'm about to show you. And basically, right, I can do these very flexible queries in a graph database where I can say, "Hey, go from person ID to this other person ID."
- 11:04
And as I do that, basically what I'm saying in that top syntax there is go out some, you know, zero to three hops, basically. And so what that allows me to do is I can traverse over both the skills, over the common systems, over the common domains they work at and all of their accomplishments.
- 11:21
Um, and if I wanted to add something else to that data model, maybe there's a collaboration link or another project link, that would all get picked up inside of that query.
- 11:29
So there's a lot of flexibility and also higher performance, um, in a graph database when you start wanting to do those types of complex traversals. Um, and that allows me then, when I go to find similar people again.
- 11:42
So if I was just to scroll down to my, uh, question where I define my agent again, I give it more tools, and then I can actually look at who is most similar to Lucas Martinez and why, and it will start doing these queries.
- 11:56
So what you see it get back is, like, all of the results of what I was just showing you earlier. And what that will help with, if I scroll down to the response, is now what will help me get all of these specific numbers around the skills and then also the domains now, um, between the different AI
- 12:12
and analytics and data engineering and things that they were working on. So there's more explainability with the way that these questions are being, uh, answered. The last part that I wanted to show you, and I only have a few minutes left, so I'm gonna go very quick, is what happens now when you wanna add more data to
- 12:27
your graph, right? So basically, say that we had this resume data, but now we have this internal data that comes from a human resource intelligence system, and this tells me different projects that people are working on together and collaborating on.
- 12:41
So I have basically the same people that came from, uh, resumes earlier, but now I can see different projects that they were working on together. And the great thing about graph is that ll- it allows you to add these things very flexibly.
- 12:54
So if I go back to my, um, to my notebook here, when you expand a data model with something like if you're, if you're in sort of RDBMS or tables, one of the assumptions that I made when I was ingesting the resumes initially was it was one person...
- 13:10
an accomplishment only had one person. It was sort of this one-to-one relationship, or really it was one to many, but an accomplishment only had one person because it was just listed on the resume.
- 13:20
But now that I, um, am doing this thing with this internal system, I can actually see people who are, uh, co-collaborating, and what that would mean in a tabular environment is I would have to create another join table, right?
- 13:32
So I'd have to do some sort of data model refactor. But the great thing about graph is that I don't have to do that at all. I can just sort of create new relationships.
- 13:42
So this is very useful when you're going from one to many to many to many, or when you're introducing completely new node and relationship types. It's very easy to do that, which is super important as we move very, very fast, right, with our agents, and we wanna ingest new data quickly and kind of build out our systems
- 13:57
and pivot and all that sort of stuff. Um, and once I have that information, right, I can start asking questions about who's collaborating with each other. Um, so what I'm gonna do is I'm gonna create...
- 14:10
This is sort of what the tool creation looks like. This is a lot of the same tools that I had before. Um, but the tool that I can create here to find collaborators will basically do this match, um...
- 14:22
It's all the way down here. It will do this match to find people who are working on the same thing, um, within a certain set of domains. Uh, so that's kind of what the graph looks like that I get returned.
- 14:32
And when I-- Now, when-- Since I've added that tool, basically what it means is that when I ask a question, like which individuals have collaborated with each other to, and this says, "Deliver the most AI things," right, it can go ahead and leverage that tool, um, and then it can now return an answer that's much more, um,
- 14:52
you know, exact and based on my data. So now I know that Sarah and Amanda have accompl-- have collaborated on very specific, um, projects, and as well as I have other collaborators here with supply chain and such.
- 15:06
Uh, so that was my short presentation. I hope it was helpful. Uh, if you have any more questions, I would be happy to meet you at the booth, and we can talk more.
- 15:14
Um, but that's it for me today. Thank you, everyone. [clapping] [outro jingle]