📱

Get Our Mobile App

Take your business learning on the go!

Download on the App StoreGet it on Google Play

I Built the ULTIMATE n8n RAG AI Agent Template

Cole Medin34:01

Transcription

Retrieval Augmented Generation (RAG) is the most popular tool to give AI agents access to your knowledge base, essentially making them domain experts for your documents. And it's really easy to implement RAG and no-code tools like n8n as well because it is so widely adopted and supported.

But I'm going to be honest, a lot of times RAG sucks for me. And the reason for that is mostly because it relies on a lookup that often times can miss key context and related information. Good luck trying to analyze trends in a spreadsheet when the RAG lookup only pulls a fourth of the chunks for the table, and you need the whole thing. And I find it so frustrating when I ask it to do something like summarize a meeting, but then it pulls the meeting notes from the wrong date. Like, come on, the date for the meeting is right there in the title of the document, why can't you get the right one?

And not to mention that RAG often struggles to connect different documents together to give you that often necessary broader context. Really, this boils down to two things. First, RAG isn't able to zoom out to entire documents or sets of documents unless the context is small enough. And then secondly, RAG has no concept of proper data analysis.

So now the question is, how do we overcome these limitations? And there are a couple of ways to do it, but my absolute favorite is Agentic RAG. And in this video, I'll show you what that is, why this solves our problems, and I'll show you exactly how to build an Agentic RAG agent in n8n. Plus, this workflow that I walk you through, I'll have as a downloadable template for you to bring into your own n8n instance in minutes.

So this is the bird's eye view of the Agentic RAG agent in n8n that I'm going to walk you through right now. And I will be the first one to admit, there's a good amount going on here, but don't worry, I will walk you through everything because this is what it takes to make a good Agentic RAG setup, including I'll be walking through the RAG pipeline as well, so you understand everything going from our files in Google Drive all the way to extracting from the different file types and adding into our Superbase knowledge base.

And I do want to make a local version of this as well using the local AI package. So let me know in the comments if you'd be interested in that.

And this entire workflow is sort of the version three of the n8n RAG agent that I've been working on. This is the last version that I covered on my channel previously. This is a much simpler implementation, so a good starting point that handles some different file formats and everything, but it doesn't work with tabular data very well. As we'll see later in this video, you need to add tables differently from CSVs and Excel files to the knowledge base compared to other things. You can't just treat it as a text document because you have to be able to query that table.

And also, this agent only has RAG for its tool. You can see based on this tool node here, there's nothing else that it has. So if the RAG lookup fails to get the information it needs, the agent has no other way to explore the knowledge in Superbase. It's just stuck and it has to tell the user that it doesn't have the answer, even though there are other ways you can look at these documents to potentially get the answer in a different way.

And that is what we're doing in this workflow right here. So let me zoom in on this a little bit so you can see the tools that we have for our RAG agent. So we still have the RAG lookup tool, just like we had in our previous example, which, by the way, this is an improved version that can cite its sources. So even that is a step up. But then we also have all these other Postgress tools for our RAG agent, so that can do other things to look at our knowledge.

And so that gets into our definition for Agentic RAG. All Agentic RAG is is giving agents the ability to reason about how they explore the knowledge base. Instead of just giving it a single tool, it also includes agents being able to improve the RAG lookup queries and choose different tools to answer different user questions.

So in the old version of our Agentic workflow here, we do have the ability to improve the RAG lookup because we have RAG as a tool. The agent could decide to invoke it a second time with a better query. So we have that part at least. But there's no way for it to explore the knowledge base in different ways or figure out based on a user's question, "Oh, I need to look at the data in this way."

But with these three Postgress tools right here, we are giving it to our Agentic RAG agent in this upgraded version because it can list out all of the documents that are available in the knowledge base, and then it can get the file contents of specific ones. So if a RAG lookup fails for whatever reason, then instead of doing that lookup, we can look at the files available to us and then reason about which document or documents we might want to look at to get that answer.

So if we ask it to summarize the meeting notes for February 23rd and the RAG lookup fails for whatever reason, maybe it pulls from the wrong date, whatever it might be, then we can instead just look at the documents and see, like, "Oh yeah, the title of this document is literally February 23rd meeting note." So I'm going to pull that, get the contents for it, and then use that to answer the user's question.

So you can already see how it's able to, in different ways, look at the knowledge base, use RAG, look at the entire document. It has all of that in its tool belt. And then we also have this tool to query Excel and CSV files as if they are SQL tables. Super, super cool. This is a bit of a fancier part of the implementation, but it makes it so powerful to be able to get things like sums and maximums over tables that you typically can't get with RAG because it's never just pulling in an entire CSV file unless it's really small.

So now it is time to take our agent for a spin. We'll ask it some tougher questions that maybe the old version could have answered with just RAG, maybe not. But the most important thing I want to show you is it using these different tools to explore the knowledge base in different ways depending on the question that I ask.

So I have these six documents in my Google Drive, some that are spreadsheets, some that are regular documents, and I already have this all in my Superbase knowledge base. And I'll walk through getting this all set up later as well. So we have our documents table that includes things like our embeddings for RAG, metadata, and the contents for each of these chunks. Then we have the document metadata table that I'll explain more later. This has the high-level information for our documents, like the URLs for citing sources and the titles as well. And then we have our document rows table. This is how we take our CSV and Excel files and store them in Superbase where they can be queried with SQL queries, even though we don't actually have to create a dedicated SQL table for each CSV or Excel file. It's very, very neat.

And so I'll go back over and let's go ahead and ask it a question for one of our documents. Actually, first, I'll open one of these. I'll just show you the data and the question that I'm going to ask. So we'll go into the "2024 Revenue Metrics by Month." This is all fake data generated by Claude, by the way. Um, and we'll ask it a simple question like, "Which month do we get the most new customers?" And maybe you could pull in this entire table with RAG because it is small enough, but we want to see our agent write a SQL query to fetch this. Because if this table was big enough, we wouldn't be able to pull the entire thing in with RAG because it would just take the number of chunks that it would accept, and that might only be like a fourth of the table. And so we might not even pull in the record that has the most number of new customers, and then it would give us the wrong answer.

So let's go back and actually ask that question here. So I'll say, "Which month did we get the most new customers?" And my goal here is to see it invoke the tool to write a SQL query. Yep, there we go, it did. So I'll even click into this so you can see this is the query that it decided to write. A little bit more complex, we won't get into that right now, but yeah, look at that, 129 new customers in the month of December. And that is the right answer. So we got everything back and yep, right here it says the correct answer.

All right, so next question. I'm going to have a blank slate for the conversation for each one. So I cleared that. Let's go back over to Google Drive and open up a text document this time. So "Areas for Improvement." This is a customer feedback survey. I'm going to ask it, "How can we improve?" and then see if it can pull this from this document specifically without me calling it out explicitly. So I'll go back here and I'll just ask, "What are areas we could do better with?" And I specifically don't want to use the word "improvement" because I want to make sure that this lookup isn't just relying on the fact that we kind of just say word for word "areas for improvements." So I'll just say, "Areas we can do better with." And it, yeah, it used RAG for this time around. "Mobile access, integration capabilities, and reporting customizations." And that is exactly right. So boom, we got the right answer.

So now I'll go back, clear the conversation again. And this time, I wanted to explicitly look at the contents of a file instead of performing RAG. And surprisingly, this can be tricky to get it to do when you're in a test environment with only this much data. It's hard to make RAG fail. So it needs to actually pull the contents of an entire file. So I'm going to be explicit here. I'm going to tell it to use this tool just so you can at least see it in action. But trust me, from my experience with RAG in general, this kind of functionality certainly is necessary because RAG isn't always reliable because of what we were talking about earlier on.

So let me open up this "Product Team Meetings Minute." I'll tell it to look at this file specifically to then pull the action items that we have. So let me go back over to n8n for this test. I'll also have it cite its source. But first, let's ask it to get the file contents of the product meeting minutes and then tell me the action items. So I'm explicitly asking it. And there we go. Yep, it called the tool to get the file contents. It returned the entire document here. And yeah, this answer looks good. "Marcus to provide a timeline." That looks good. Everything else matches up. Yep, that looks perfect.

And then I'll also ask it to cite its source. So, "Cite your source." So I want a link to the document because I want to maybe go and check then to make sure I had the right answer if I don't have the document pulled up already. And there we go, gives us a link right here. I can click on this and then boom, we have the document open right from our agent. Look at that.

The sponsor of today's video is Unr, an open-source no-code LLM platform to create APIs and ETL pipelines to turn unstructured documents into structured data. And this is so important for AI agents, especially with RAG, because you're not always going to have simple CSV and text documents for your knowledge base. So you can easily just extract all the text and dump it in. Sometimes you're going to have PDFs where you have to pull specific tables from, or you're going to have images that you need to extract information from for something like a receipt. And that's what Unr can help you with. And you could even turn it into an API endpoint to put into something like an n8n workflow to handle your more complicated documents.

So here is the GitHub repository for Unr. And you can think of this platform as being three distinct parts. First, you have the Prompt Studio. This is where you can engineer your prompts to work with the LLMs and make sure they know how to extract the information from your unstructured documents. And then you take those prompts and you add them into workflows. This is where you build these flows to automatically extract the information from your documents. Then you can deploy the workflows as data APIs and ETL pipelines. And they have fantastic documentation that I'll have linked in the description for how to work with all these different components for the things like API deployments and ETL pipelines.

And I also just want to call out the Prompt Studio really quick because it is just fantastic how easy it is to upload a file like this receipt that I just pulled off Google and then define prompts to extract all the different key pieces of information you want, like the line items and the tax amount and the dollar amount at the bottom. And it just does so well extracting all this. So you define your prompts here, figure out exactly what you need, and then go on to build your workflows.

So if you have more than just simple CSV and text documents that you could extract with a single node in n8n, I would highly recommend checking out Unr. It just solves so many problems that we have working with our more complex documents and it's so important for a huge variety of use cases, including RAG agents. So I'll have a link in the description below to Unr. Definitely recommend checking them out if you want to work with all of your data and not just what's simple.

So now you know at a high level how this Agentic RAG setup works. So I want to drill down now into the different components so that you have what it takes to take my template and extend it to your specific use case. This is a very good starting point, but I don't expect it to be an out-of-the-box solution for you. I do want you to work on the prompting and the tools and the pipeline, change things up to work with your specific knowledge base.

And so zooming in here, I'm going to show the first part of this workflow, and that is running all the nodes in this red box to set up your Superbase database. Because we have these three different tables here, and we have to create each one of them. So the first node is to create our documents table. And if you've set up RAG with n8n before, this query probably looks very familiar to you, because this is in the setup instructions for Superbase. So you might already have this. You could always just use what you already made or rename the documents table and the query here. But this builds our documents table where we store the embeddings for RAG, the metadata, and all the contents of each file as well.

And then we have the second node to create the metadata table. And this table is what stores the higher-level information for our documents, so that our agent is able to look at things at a higher level compared to just a dead RAG lookup, decide based on the title if it wants to analyze an entire file, like the revenue metrics for example. And it also has the URLs so that it can cite its sources, both RAG and the entire file lookups here on these tools for the agents that cite its sources when it calls those.

And then the last thing that we have that I'll explain more later is the schema. So for just the spreadsheet type files, we define the schema here, and that tells it what fields there are when it queries the data for that table in the document rows table. Which, speaking of that, that is the third node here, is creating the document rows. And all of the data for each row is stored in JSONB in this row data column right here. That is how we're able to essentially create SQL queries for our table data, but not have to create a brand new SQL table for every file that we ingest, because it's all done within this JSONB, which is flexible. We can have any kind of schema stored in the row data right here. So that is kind of what we see right here, like for example, this file we have cohort, initial customers, all these different things. But then for this spreadsheet, we have CAC, LTV, MRR, all that different data is stored in row data. And then the schema right here tells the agent how to query it, what columns are available to it.

And it's not the perfect setup because it doesn't tell you things like the type of the data. So it might try to do a sum over something that actually has dollar signs for each number, so it's a string. So not a perfect implementation, again, this is just a template to get you started. Um, but it does show the concept, very powerful in a simple way. And that's the main thing that I'm trying to do with this agent.

So the second part to our workflow is our RAG pipeline. That's everything in this blue box where we're taking documents from something like Google Drive and bringing it into our Superbase knowledge base. And obviously, we have to do that before we're creating our actual AI agent, because we need a way to test to make sure the tools we're giving it to explore the knowledge base are working. And so I'll walk you through the pipeline right now. I won't cover creating all of the different credentials for things like Google Drive and Superbase, because I have done that before in other videos on my channel, like for this version of the workflow. And if you go to create new credentials, there's always going to be an open doc button that n8n gives you. It brings you to their documentation page that makes it super easy to set up your credentials.

The one thing I will say for the Postgress nodes though, and the credentials for that, is that the n8n documentation is not very clear. You need to use the transaction pooler method for connecting to Postgress. So you go into your dashboard for Superbase, click on connect in the top middle. This will save you a huge headache, by the way. It did for me. You don't want to use the direct connection parameters. These won't work. You want to use the transaction pooler ones where the port is 6543. So this will give you everything you need, obviously, except for the database password, which hopefully you should have.

So with that out of the way, let's dive into the start of this pipeline, which is our Google Drive trigger. So clicking into this node, all we're doing in Google Drive is polling every minute for new files that are created. And you can swap this out for a Dropbox or a local file trigger, which I'll show you that when I make the local AI version of this. This is just an example using Google Drive. So it's watching every minute for files created in a specific folder that I give it in my drive. And then I have a similar trigger for files that are updated as well. So this workflow will handle both files being created and updated.

There isn't a trigger to watch for files that are deleted, unfortunately. It's kind of a big bummer. I hope they add that in n8n, just so that you could clear your knowledge base when you delete a file in Google Drive as well. So currently, that is not supported.

And then one thing that was really missing from my old version of this workflow is it didn't handle properly when multiple files came into the trigger at the exact same time. It would just send one file through this entire workflow and skip the rest of them. But in this version, I am handling that for you. I know that was a big piece of feedback that I got. I added this loop in, so now it can handle when you dump in multiple files within the same polling minute or update multiple. And I even show this here because in my pinned data for my Google Drive trigger, I have two items. I'm sending in two files and handling that in this loop. And so what it'll do here is send one file through this entire flow, just like we saw before, but then it'll loop all the way back and do the same thing for the next file, and the next file, until it gets through everything that the trigger gave into the loop. So I hope that makes sense. Definitely wanted to improve that for you all.

And so now we're zooming in on just a single file level. The rest of this happens for just one file at a time. First of all, I ran everything here already, so we'll see the inputs and outputs because I have a test execution that I went through. That's why you see the green boxes for all these. And so in this first node here, we're setting the stage for the rest of the workflow with all of our important information, like the file IDs for our queries, the file type to determine how we want to extract the content, and then the title and URL as well, which is going to be going into the database.

The next thing you want to do is clear out all the old data for this file in Superbase. And that is if we are updating the file. We're just going to do it every time, in case. And the reason we want to do this, we want a blank slate, because we want no chance that there's any data from an old version of our file left in the knowledge base for our agent to query when it shouldn't be available. And to give you a very clear example of this, let's say you have a file that is initially 10 chunks because it's something like 10 paragraphs, but then you delete the last paragraph. Now it's only nine chunks. If you try to just update the existing chunks in the database instead of clearing them and inserting them new, you're only going to update the first nine, and then that 10th chunk, because the file used to be longer, is going to remain in the knowledge base, even though it's from an old version of the file.

And so the most sure-fire way that's generally recommended is just to delete everything. So we're deleting all of the document rows specifically for this file ID, using that metadata field that I'll show you later on. And then doing the same thing for the data rows as well for all of our tabular files. And again, just based on the file ID that we already set, we're just going to delete all of those records in the Superbase table.

And then we want to do our first insert, or this is actually an upsert too, because if the file already exists, we're just going to update the metadata. And then if it doesn't exist, we will insert the metadata. And this is just setting the initial stage for our document here with things like the title and the URL. And then later for the tables, we'll be setting the schema. I'll show you that in a bit as well. And we can set this here because this table doesn't rely on having the content for the file yet, because we're going to extract that later. And that's when we'll be able to populate the documents table, because we'll have that content extracted to add in the content column here, create our embeddings, and add those, all that good stuff.

The reason that I'm, I'm using Postgress here and then Superbase here, they're kind of interchangeable, but Postgress offers some better nodes for things like running SQL queries, doing upserts, like perform an update if it's not there, insert it. You don't have those options for the Superbase nodes. But I do want to use Superbase for deleting because it has this filter option that I didn't see with Postgress. So that's just a little aside why I'm kind of mixing and mingling the Postgress and Superbase nodes in this workflow.

So, okay, at this point, we have a blank slate and we inserted the initial metadata. Now we want to extract the content for the rest of this pipeline. So we download the file from Google Drive. So this data field that output is the file itself, like I could download it or view it. So we don't have the content of the file yet, we have the file itself stored in our n8n instance now, so we can extract from it. And then we go on to this switch node. So based on the type of file, there needs to be a different way for us to extract the content from it, because the way that you take content from a PDF or a spreadsheet or a Google Doc, those are all different. And so we have these different branches that are all determined based on this switch right here.

If it's a CSV file, like it is in this test run, then we go down output two, that third branch. Otherwise, if it's a Google Doc, or also the default is the output three as well, then we go down this bottom branch right here. So for my test, we see the green line going to extract from CSV, because this test is working with a CSV file that I uploaded to Google Drive. And it's actually quite simple. If we're extracting from just a PDF or a text document, we just have a single node here. And I'll even show you, if you go to add a new node and search for extract, all these different file types are supported. So if you want to extend this to work with JSON files or extracting from HTML files, you can add these extract nodes in, and then you just need to add another branch into the switch statement here. So it's very easy to extend this for other file types as well. If it's something that's not supported within those options that you saw there, you can always create a custom n8n workflow to extract from different file types too. So the world is your oyster here, the different possibilities are endless for how you can work with really any file type that you want.

And then other file types like Markdown and text documents can also be handled by just extracting from the text document, like this node covers a lot of different file types as well. What I do want to focus on though is extracting from CSVs, because this is where it gets a little bit more complicated, and we want to populate the schema in the metadata and the rows as well. So let's go back into our n8n workflow, I'll show you how this all works for CSV and Excel files.

So in this demo, I'm just running this CSV path right here, but for Excel, it's exactly the same. The rest of these nodes are the same. We just have to have a different extract node. And so first, we are taking the contents from the CSV file and turning it into rows in our n8n workflow. And then we want to do two things at once, because we want the data from our table file to be available in RAG, so we want to turn it into a text document and chunk it, just like the rest of our documents. But we also want it to live in the document rows because we want to be able to query it as if it is a SQL table. We're giving our agent the ability to do that.

So we have two different paths that we are going down here. The first one, for all 15 records that it pulled from the CSV, we are inserting each of those into the document rows table. So like, this is all one file, for example, everything right here, we're inserting all these records within this node right here. And then in parallel, we also want to start to turn it into a text document. So we're going to aggregate everything together. So instead of there being multiple records, it's just a single item, which is an array of all of our rows. And then we want to summarize it, which essentially just turns it into a string, because now we have a text document that we can chunk up, just like if we extracted from a PDF or a Markdown file, whatever you might have in the top and bottom branches right here. And then all of that goes into Superbase, which I'll cover in a second here.

So in the end, the tables are treated just like any other text document. But also, we have this route right here where we're setting the schema. So using this fancy JavaScript that I'm not going to explain in detail right here, we're taking the headers from the CSV and defining that as our schema. And then updating our metadata record, so that the agent can access that schema as well. So this is where we set this piece of information. So we tell it that this CSV file has these headers, and that's how the agent knows, like, it'll read this record first to get the metadata for the customer cohort analysis, it'll see that this is the schema, so then it knows how to write the SQL queries to query the rows here. So I hope that makes sense. So the agent has to look here first, understand the schema, then go and query the rows. And we're making that all possible right here, adding in the schema to that metadata record.

And then the last part right here is our Superbase. And this one is pretty simple, because n8n takes care of so much for us with all these nodes. It is quite complicated to chunk everything and add it into Superbase, but it's just done with four nodes here. So first of all, we have our "Insert into Superbase Vector Store" node, where we just define the table and the query that we are using for RAG. And then we have our embedding. Which I'm just using OpenAI. Um, by the way, I'm using Text Embedding 3 for my embedding model. And then for all of the LLMs, I'm just using GPT-4o mini, which isn't the most powerful LLM. I just wanted something cheap and fast here. But depending on your use case, you might want something more powerful as well, like GPT-4o or Claude 3.5 Sonnet. Anyway, that's our embedding model.

And then we are just using a default data loaders. This is what's responsible for chunking our documents, getting them ready to insert into Superbase, and defining the metadata as well. Which that is very, very important for the metadata. Here I have the file ID and the file title. And the reason this is so important is because the metadata is how we can query to delete only the records for a specific file when we're at the start of the flow, when we want that blank slate for inserting for RAG. And then the file title itself, we also want in the metadata, because the agent is going to reference this to know what file it's actually looking at when it performs RAG, so that it can cite its source. And we'll get into that later, but in the RAG tool, we actually have it so that the metadata is returned as well. So I have this ticked right here. That's how the agent is able to know what it is looking at.

And then finally, for the text splitter, just have something very simple with a character text splitter. Didn't put a ton of thought into this, because it will depend a lot on your use case how you want to chunk your documents. So just keeping it very, very simple there. But that is everything for our RAG pipeline. And you also saw as I was going through this workflow, I showed you the inputs and outputs for everything. So you basically saw a whole run of this. Um, and I've already done that. So all of the files that I have in my Google Drive for both my spreadsheets and my documents, I have that all ingested already. So I've executed this workflow for every single one of them. I just used the trigger, dumped in my files, and it handled that.

So with the RAG pipeline created and all of our knowledge ready, we can now move on to setting up our agent. And luckily, creating our AI agent is simpler than our RAG pipeline, because we do all the work getting everything set up in our knowledge base and Superbase. And then our agent only needs a few rather simple tools to leverage it. So let's go through that right here.

So first, I have a couple of triggers for this workflow. I have a webhook, so we can turn our agent into an API endpoint. And then I also have a chat trigger, so you can chat with it right here in the n8n workflow. That's what gives us this chat button in the bottom middle here. And then these two nodes output slightly different formats. And so I have this edit fields right here, just a little bit of JavaScript to handle both of these different triggers, so that we have a consistent output for our agent node.

And so going into that right here, our agent is quite simple overall. I just have this system prompt right here that describes to it the different tools that it has to explore the knowledge base. And I give it some instructions for how to leverage these tools, like for example, I tell it to start with RAG and then use some of the other tools if RAG doesn't give you the right answer. And so you can certainly tweak this system prompt. I think that there is a lot of opportunity to make this a much better system prompt. I just have this as an example for you. One thing that helps a lot with these kind of RAG agents is ask it to be honest, like if you don't find the answer from RAG and the other tools that you have, just tell the user instead of trying to make up something yourself. And this alone can reduce a good amount of hallucinations.

And then for our model, we just have GPT-4o mini, like I showed earlier. Setting up a simple Postgress conversation history right here. Which, by the way, this table is created automatically if you don't have it already in the first conversation, which is why I don't create this as a fourth node in the red box. So nice and simple. And and just makes it easy for you.

And then we go on to our tools. So the first tool that we have is RAG. And you'll see here, looking at the old version of the workflow, this is a much simpler version. And it's because n8n has had a lot of really awesome updates for AI agents since I made that last video. And so this tool for the Superbase vector store is much simpler. And there's the option now to include the metadata. So the file ID and the file title that we inserted in the metadata for each record, like I'll show that here. I go to documents and then click in on the metadata field, we'll see here that we have the file ID and the file title. All of this is brought into the results for RAG. And so the agent has access to that information to cite its sources. That is super, super important.

And then we are using the exact same embedding model that we use when we insert things into Superbase. That's super important because you just have to make sure that your model has the same number of dimensions for both the inserts and the retrievals.

And then going to our other tools here, the first one we have is to list our documents. So just using a simple Postgress query here, we're pulling all of our documents from the document metadata table. So the agent can read all these and then reason about which files it wants to look at and the IDs of each of them. And also for the table files, the schemas as well. So it knows how to query the document rows table. And I am returning every single document here. So keep that in mind if you have a large, large corpus of documents, you might want to not return everything and find some way to filter the documents that you are pulling, maybe based on a date or having the AI write a query, something like that. Um, but also keep in mind the LLMs can manage very long context links right now. So even if you have like a thousand documents in your knowledge base, you still could pull the files and the titles and IDs for every single one of them and dump that into the prompt for the LLM. So that might even still work.

And then after we list the documents, then the agent might want to pull the contents of specific files. And so I just have this query right here that is essentially given a file ID that it pulls from the metadata table, it can use that to pull the content of all of the chunks for the document and combine that together to give us the full text for that document. And the reason that I'm using the content column in the documents table instead of just having a content column in the metadata table that would have all the content for the file is just because n8n includes this content column by default. It's something that I can't control. So if it's already here, I don't want to duplicate the information by having the content of the file stored in the metadata as well. So I just pull all the chunks together for the content and combine that with this query right here. And the one parameter that the AI decides is the file ID. So it picks that out from the metadata table and then passes that into this tool. So you'll see the agent every single time that calls "get file contents," it always called "list documents" first because it needs to do that to actually know what file ID to pass into the tool to get the contents for it.

And then the last tool that we have here is the one to write SQL queries to query our tabular data. And this is a little bit of a fancier implementation here. It's pretty bare bones as well. There's a lot of room for improvement for the prompt here because what we have right here for the tool description is given as a part of the prompt to the LLM. So it knows when and how to use this tool. I mean, same thing for all the other tools as well. But I have to be a lot more explicit here because I have to help it understand the document rows table. It needs to know how it's structured, how it needs to use the row data JSONB to write these SQL queries for these different files. And I give it some examples as well. And these examples are pretty bare bones. You probably want to improve this more for your specific use case and how you want it to query your tabular data. But I give it examples of how to use the row data JSONB to select certain columns, to do group buys, you could have it, um, understand filtering better, all of that.

And then I have it write the full query. So the parameter, the single parameter here, is the entire SQL query that it wants to write, something like this to query the contents of a specific file. Because the data set ID is the file ID. So that's how it specifies the single file that it wants to query. And then uses the row data JSONB to query and group by specific columns and do all that filtering as well. So that is the last tool, and that is everything. And I know that the tools got a little bit more complex there. So yeah, just let me know in the comments if you have any questions on that.

But this is it for our agent. So we now have everything to do what I did at the start of this video, just like a quick example here. I can say like, "What employees are at the company?" Just something super generic. I mean, this is the kind of thing that like, again, maybe RAG could do, but I'm just showing a random example here. Um, just to show it using all the different tools here. So yeah, in this case, it performed RAG and decided that it didn't get what it needed, so decided to list a few of the documents as well. And so it told us, "Oh, this document didn't give us what we wanted. This document didn't give us what we wanted." But then the "Product Team Meeting Minutes" did. Here are the team members. So look at that. It's so cool. Like, I actually just pulled this example out of my butt just now, but it worked really well because it showed performing RAG and that not working, which kind of makes sense. Like, you wouldn't really know how to find specific names using a vector search just because you're asking for employees. So then it decided to search the files, which is really cool. So yeah, good example.

I hope that this template can get you started super fast with Agentic RAG in n8n. And of course, let me know in the comments if you have any questions as you build out this workflow. It is getting into the more advanced RAG topics. Also, a lot more similar content coming out soon, including a completely local version of this Agentic RAG agent built with the local AI package. So stay tuned for that.

If you appreciated this content and you're looking forward to more things AI agents and n8n, I would really appreciate a like and subscribe. And with that, I will see you in the next video.