Store All Data Types with Agentic RAG in n8n

Dr. Violet Howard demonstrates Agentic RAG in n8n, where an autonomous agent chooses between SQL queries, vector search, and file retrieval to answer questions across mixed data types. The workflow uses Supabase tables to store PDFs, spreadsheets, and metadata, then intelligently routes queries and retries with fallbacks when initial approaches fail.
Chapters
Today I want to talk about Agentic RAG. The conversation around RAG seems to be shifting so fast with, you know, different models releasing larger context windows. Where does the future of RAG really lie? We've heard CAG, we've heard Graph RAG, we've also heard Agentic RAG. So just wanted to come in here and break it down and make sure you stick around to the end of this one because I'm going to be hopping into NN and looking at a super cool template for Agentic RAG. So before we start talking about Agentic RAG, real quick, just got to understand what RAG is. Stands for Retrieval Augmented Generation, and essentially it's just the process of, you know, giving your agent access to some sort of database in order to retrieve information based on the query that you ask it. It's going to get back that context, augment it with the original query, and then generate an answer that is detailed and specific to what you asked. The simplest way I like to think about it is let's say someone asks you a question like, what's the capital of Illinois? And you don't know. You'll take that query that they asked you, You'll do something like you'll Google it, look at the results, and then you'll answer them. One misconception I feel like is when we hear RAG, we immediately think of like a vector database, which that is RAG. However, more broadly, the term of RAG just kind of refers to grabbing context from somewhere else and pulling it back to make an answer. So how does this work with traditional RAG? Let's talk about the most common use case of a vector database. So down here we have a bunch of documents. In this case, we're just looking at one. But let's say we have a ton of documents that are text. What we have to do is we have to somehow get these into a vector database. So how this works is the document is split up into chunks, and this is something that we can play around and test with as far as different chunk sizes and different chunk overlaps. But in general, it's going to get turned into chunks. So right here we can see we have made 3 chunks out of this one document. From there, those chunks get run through an embeddings model, which is basically just turning it into a numerical representation of data so that it fits somewhere within our vector database, which is multidimensional representation of data where the vectors, or each of these little points or dots, are stored somewhere in this space based on the dimensions they're given when they run through this embeddings model. Now the dimensions are basically just a bunch of numbers, and these numbers actually are associated with contextual meaning based on the words that are in this chunk. So let's say, you know, this chunk is associated with company information, so it goes up here. This chunk is associated with finance information. So it goes over here. And then this chunk is associated with marketing information. So it goes down here and they're all placed differently in this vector database. And they'll all be kind of shifting as more information is flooded in so that all of the vectors that are associated with each other and relevant to each other are near each other. All right. Now, when it comes to us actually wanting to query that vector database, we usually use an agent in order to get that aspect of RAG. So this is what the process looks like. I tried to make it as visually simple as possible, but what it starts with is a trigger, which is usually us asking a query to an agent. So let's say in this example, we're asking, what is Company X's mission statement? The agent will then read that question. It will turn it into its own query to send off to the vector database. So in this case, it just says Company X mission statement. And then that query gets embedded using the exact same embeddings model that happened up here in our sort of RAG data pipeline. And obviously we want to use the same embeddings model so that they fit in the same near spaces. So this question got embedded and its dimensions got placed as a vector near the company chunk because they have similar text, right? Similar meaning. So then now that we have our query embedded as a vector, the query is going to grab the nearest maybe 4 or 6 sort of vectors based on the way you configure it. And it's going to grab the near chunks and then pull them back. So now down here, what we're looking at is we get the vector back as a chunk and we can read the content of it. And then we get the query back as well. And then these two things are sort of augmented together with an LLM in order to create that response, which is the output. And that's sort of the end of the process. So with traditional RAG, it's kind of a one-shot query, grab stuff back, here's the response. Now when it comes to agentic RAG, there's just a little more reasoning involved. And it's maybe not always just a one-shot process. It still starts off with a trigger, which is us asking a query to the agent. But now instead of the agent directly turning that into an a dimension and a vector and then pulling that back, it's going to look at this, the context of what it has, and it's going to be a little more aware of the decisions that it can make in order to get the most effective query out there. So it can look at the different databases that it has access to. It can look at the different schemas. So maybe we have a ton of, um, not only text data, but we have relational tabular data somewhere in a different database. And in that case, we want to do a SQL query and we have to look at the schemas. It can also look at all the file content that we have in order to maybe understand, you know, we have 10 documents in here. How do we know which query associates to which document? So it can read file contents, it can look at the actual documents and understand, you know, like the file IDs or the names of the documents coming through. And then once it has that information, it's able to say, okay, I'm going to send this off to the vector database to get embedded and then put in there to grab the information back. Or it's going to understand, okay, based on the question, I'm gonna be looking in like our sales data spreadsheet, which is not going to be vectorized. We want to look at a SQL query. So then I'm gonna make a SQL query in order to hit the right database there. So it's just gonna be a lot more efficient. It's going to be a lot more relevant and we need to understand why. So let's look at these other visualizations. Why does this actually matter? At this point, it may make sense. Oh yeah, like having a reasoning aspect of an agent to before it sends out the query, it sounds great, but what really does that even mean? So let's, let's go back to the vector database example. The agent's going to be taking our query and it's going to make one, and then it's going to be looking in the vector database for chunks, and it's just looking at chunks. So this is going to miss out on the context of the entire document. So maybe, you know, we're looking within a PDF that's 20 pages and we're just looking for specific chunks within that PDF. But if we wanted to be able to read the entire PDF in order to reason which chunks actually make the most sense here, we wouldn't be able to. So it would just be looking for chunks, right? And that's why when Gemini dropped its million context window, that really changed the game because now a model can read the entire document before pulling back the answer. So here's a little more practical example of what this means. Let's say we're asking the agent to summarize the meeting on March 5th. It's going to turn that into a query, which is going to be something like March 5th meeting summary. And if we're looking at a 20-page PDF of March 5th's meeting, we're not going to be able to get all of those chunks back in order to summarize the meeting. It would just be pulling back 5 random chunks and then summarizing just those chunks. So that is why we need the aspect of agentic RAG. And now also let's talk about it in the sense of tabular data real quick. Let's say we vectorize this spreadsheet, which is actually the real example we're going to look at in a sec. We have like weeks, total sales, total units, order value, unique customers, repeat customers. We have all this information for each week, right? And so let's say we ask the agent, what week did we have the highest sales? It would turn that into a query like highest sales. It would then look at the chunks and it wouldn't really be able to grab the ones that are highest sales. And even if it did, it would basically just be grabbing a chunk of rows and then it would be looking, okay, within this chunk, which one's the highest? So maybe it would say, okay, here's in the green, $15,000 total sales. That's the highest out of this chunk. And I'm gonna say that week 6 is the highest total sales. Although if we really look at the data, we can see that, you know, week 19 is higher, week 14 is higher, week 24 is higher. Because the agent wasn't able to make an effective query to go through all of the total sales or look at the whole context of what's going on before it answered. A very similar example down here would be, what is our average order value? It would basically just query something like average or like order value, something like that, right? And once again, it would just grab a chunk and then it would say, okay, out of this chunk, I can try to do the math here. And LLMs are not very good at math, but I can try to do the math here and average these order value data points. And it would give you back an answer and you may think it's right, but it's not because it would not be looking at all 30 rows of your order values. And, you know, a lot of times you're gonna have more than just 30 rows. So the more and more data you get in there, the more essential it's going to be to be able to accurately and efficiently be able to like SQL query through this stuff rather than relying on your vectorizations of your agent to be able to do stuff like average order value, you know, numerical data, numerical analysis, stuff like that. By the way, if some of these concepts are kind of daunting to you and you're looking for a more hands-on approach to learning NNN and vector databases and stuff like that, I would definitely encourage you to check out my paid community. The link for that's down in the description. We've got a classroom section with stuff like building agents, intro to AI automation, deep dives on vector databases and RAG, APIs, HTTP requests, and then I'm doing step-by-step builds of a lot of the videos you see on YouTube, which I think are the best way to learn. So we've also got 5 live calls per week to make sure you're getting in there, getting your questions answered, and never getting stuck. So I'd love to see you guys in these calls, but let's get back to the video. All right, so now we're actually in N8N and we're looking at Cole Meaden's recent template where basically the best Agentic RAG template that I've ever played around with. He makes it super easy because he has these 3 nodes here where you can just run them and it will create your database setups in Supabase. So we're using Supabase right here. We have a documents table, which is our actual vectorizations. Here are, you know, the content of our different documents we're looking at. Here's the metadata. Here are the embeddings. We have the document rows table. So anytime we want to upload a, you know, a tabular form of data like CSV or Google Sheets, it's going to put all the rows in here that the agent's able to query through. So we have all 30 rows of our spreadsheet right here. And then we have document metadata. So we uploaded 3 files. And we get all 3 files as they're each unique rows, which the ID of each one, the title of each one, and then, which is really cool, the sales data is tabular, so it pulls in the schema. And the agent will be able to look at the schema in order to make that SQL query. These 2 are both just PDFs, so there's no schema. But anyways, you'll be able to run those 3 after you connect your credentials and you'll get the table set up, and then the rest of the workflow's gonna work for you. So this is, like I said, probably the coolest template I've ever seen on N8N, and just huge shout out to Cole here. He doesn't need me to help him promote any of his content, he's killing it. But Cole, this is awesome, man. So of course, if you want to get this template to play around with, it'll be available for download for free in my FreeSchool community. But I'll also leave the link in the description to Cole's video about it. He also provides that template for free, of course. And, um, he has a video where he kind of deep dives into like what's going on within this pipeline and also like how he built all this kind of stuff. So definitely go check out that video. One quick thing though, in, in this node where you're setting up the documents table, which is the vector database, if you've already created one before in your Supabase environment, you can get rid of this first line, which enables the pg_vector_extension extension because you don't have to create it again if you've already created it. So do that. And then also if you want to change the name from documents, you'll have to change this and then you want to change the other instances of the word documents within this code. But anyways, you'll run those, you'll get set up and now let's chat with our data. So the 3 docs that we have in here are we have our sales data, which is right here. As you can see, we have 30 rows of sales data. We have our Greengrass AI implementation proposal, and we have our Mountaintop AI implementation proposal, and they're all in here. So the agent has to be able to figure out, okay, which of these 3 docs do I need to look in? If it is the sales data, I probably need to do a SQL query, and it has the different tools like listing documents, getting file contents, query document rows, and then of course the Supabase vector store. So let's try out some queries. Okay, so the first one I'm saying is which week has the highest total sales? We're going to see it update its memory. It's going to list the documents. It's getting the schema, and now it wants to make a SQL query. It failed the first time, it tried to hit it again, and now it's getting the file contents to pull that back. So what we got was the week with the highest total sales is week 4, with total sales amounting to $19,423. If we go into the document, we can see that week 4, that is the correct amount of sales. And if we look through closer, and I obviously could do a Google Sheets function to verify, but that is the highest week of sales. So what happened here was, let's click into the logs. Basically, it tried to— it listed documents and it understood, okay, I need to go to the sales data, which is right here, sales data, and here's the schema. It tried to make a query. So we got a query, it didn't come through right the first time, you know, something was wrong with the numeric data. Hey guys, while editing, I noticed that this errored because there was no value in week 19 for the total sales. So that's why the SQL query failed twice. But it was good to show off the functionality of it fetching file contents if it did error. So it was always a good failsafe. But yeah, that's why it errored if anyone was curious. It tried to make a query again and errored again. So then its failsafe was, okay, I'm just going to grab all file contents of this ID. And it knew to get this ID because earlier it listed documents and it saw the ID of the sales table. And from there it could see this data, see all of it, and then it was able to make the response which was week 4 has the highest amount of sales. Okay, but just to show you that the SQL querying does work, let's try another one. What is our average unique customers per week? So it's going to obviously hit the memory. It's listing documents to get that schema. Now it's gonna be trying to make a query. There we go, we got green. And we got the average unique customers per week is approximately 171. So if we come in here, and real quick I'm just gonna do an average of, what did I say, unique customers. So we'll grab this and we'll see, oops, the answer right there, it made a new column. But the answer is 171.07. Which is exactly what we got here. And we'll click into this query and we can see what it did is that it was able to generate this query. So Cole obviously wrote all this stuff, so great work there again. But what it's doing is it's selecting the average out of all the unique customers from the correct document. Um, and then it's doing that with SQL query math rather than the LLM relying on, or rather than us relying on LLM to do math. So this is why we got the exact answer here, which is what we saw in our Google Sheets. And then one more query we're going to do is how many total units sold from weeks 4 through 10 We'll send that off and it's going to once again probably list the documents to get the schema. And now it's going to create that SQL query. We already got that back and it said the total units sold from week 4 to 12 is 2,139. Real quick, let's just do a quick sum of the total units sold from— what did I say— week 4, week 10, and we get 2,139, which is exactly what our agent said. It queried it by basically saying it wants— I want to sum the total units sold from this ID and the week has to be between 4 and 10. So absolutely amazing. Okay, so now we want to look at— let's see if we can hit the vector database to pull back some information about Greengrass AI implementation proposal, not Mountaintop. So we'll say like, what is going on within the automated email and outreach within our Greengrass project? We'll see what tools it uses. So first of all, it just went straight to the Supabase vector database, and we'll see if we get back something accurate. By the way, using 4.0 4o Mini. Okay, so 4o Mini, this is, and it's already still working really well. Anyways, let's see what we got here. The email outreach within Greengrass project is aimed at automating and enhancing the sales outreach and lead qualification through AI-powered automation. So we have objectives to streamline engagement. It gave us the full scope of work and it gave us expected outcomes, project timeline as well. So it gave us a pretty detailed piece of information back. Come into here and we can see that if we were to cross-check all this, it would be accurate. And now what I wanna do real quick is just hop into the agent, click on its logs, and we'll see exactly what it did as far as the query it sent off to Supabase. So what it did is it queried email outreach Greengrass project. So it was able to pull back this chunk from the Greengrass. It was able to pull back the expected outcomes and pull back just basically this information about our Greengrass project. Okay, we're gonna try something a little trickier. So I'm gonna say, which project is the cost estimate $50,000? So in Greengrass, it's $25,000. Mountaintop, it's $50K. So let's send this off and just see how the agent thinks about it, and we'll see if it hits any of the different tools. It went straight to the Supabase, and it looks like that was already its answer. And it said the project with a cost estimate of $50K is Mountaintop AI implementation proposal. We'll click into the agent, go to its logs, and see what it sent off. And it said cost estimate $50,000 project, and it was able to pull back chunks based on that query, and then it was able to determine that that was the mountaintop project. Okay, gonna try one more thing here, and I'm gonna say give me a concise summary of all of our projects. And that's not a question mark, that's a command. So I'm sending that off, and I'm interested to see this here because as we know with chunks, it would have to pull back a ton of them, right? So it's thinking about it. As you can see, this one thought about it longer. Okay, so it actually— what it did was it used its memory. Okay, so I'm going to clear the memory in Postgres as well. We cleared the chat history within our N8N, so now it has no memory to work off of. And I'm going to say give me a concise summary of all of our projects. So we'll see what it does here. It's hitting the Supabase vector store. I think that's the only thing it's going to do here. So we will see how accurate this is. But okay, so we have Greengrass. It gave us the project name, scope of work, tech stack, um, and then it gave us the exact same thing for Mountaintop except for it didn't give us a tech stack. So what's going on here is if we go to logs, we go to Supabase vector store, it said summary of all projects. So this is one of the limitations, of course, of Exactly what we were talking about earlier with chunking, because it got back, it looks like, 4 chunks. And it did 4 because in here we set the limit to 4. Now if we were to set this limit to— oh, sorry, if we were to set this limit to 10, now it's going to be pulling back 10 chunks. And if we did this again, we would see that we're probably getting more details about our projects because it just has more information to work with. So what we wanted to be doing is probably using get file contents to get all of the information based on the ID. So we'd want it to probably list documents and then get file contents to pull back those two IDs and get everything. As you can see, this is more detailed now because we increased the limit. But as Cole mentioned in the video, it can be hard to get the AI to do that because it's like, it's technically not going to fail and, and this is more of a failsafe. So like as you saw when we tried to do the query and that didn't work, so then it uses as a failsafe. So what I'm gonna do is just explicitly prompt it to, um, give me a summary of the projects. You know, by using get file contents tool. So we'll see if that does anything. Um, okay, so it's listing documents. Now it's gonna hit the get file contents, and now we're gonna have it pull back 2 file contents, as you can see. So it's getting all of the information about our 2 projects, and now it's trying to construct that into a concise summary for us. Um, so we're about to get that answer. Now we have the actual full contents of the project there. And so if we click in here in the logs, we'll see first it listed documents. So it was able to say, okay, here's the ID for our project, here's the ID for our second project, and now I'm going to get file contents. So as you can see, it got everything because it filtered by this ID, and then it did it again for the second project filtering by this ID. And now we have the actual full document. So that's what we wanted to do. Um, and it's hard to make the AI do that without like an actual error over here. But as you can see, that's the way it was able to like look through projects, grab those IDs, and then get everything back. So that's going to be it for this one. Like I said, super, super cool template. He even has a full RAG pipeline down here that handles PDFs, text, or any tabular data, and it will create those rows and it will aggregate it and still push it in. Um, so super, super cool template here. Huge shout out to Cole once again. Thanks for, you know, doing this for the whole N8N community. It's really cool. He also made a local hosted one if you're interested in that. So definitely check out his channel. Like I said, the link will be down below. But, um, thanks guys. I really appreciate you making it to the end of this video. If this was helpful, if you learned something new, then definitely hit that like button. Let me know what else you guys want to see. It definitely helps me out, and I will see you guys in the next one. Thanks.










