Step by Step: RAG AI Agents Got Even Better

Dr. Violet Howard builds a production-ready RAG AI agent using PostgreSQL for chat memory and Supabase as a vector store, replacing earlier setups with Pinecone. The tutorial covers N8N workflows that automatically ingest Google Drive files, split and embed them, and update vectors when files change, then demonstrates the agent answering questions about sample projects.
Chapters
In this video, I'll be walking through step by step how to build out this RAG AI agent system that uses Postgres and Supabase. What we're building today is a little bit more improved version of other RAG builds on this channel, and we'll dive into why you want to set up your foundation like this in order to have a RAG system that's a little bit more production ready. And make sure you guys stick around to the end of this one because I'm going to go over some tricks in setting up the workflow so that anytime a new file is created, it's automatically going to go into your Supabase, as well as if you update any of those old records, it's going to replace them in your Supabase so that you know you can always trust the data that you're talking to. So here's the RAG agent that we'll be working with today. If you're unfamiliar with the term RAG or you've just sort of heard about it, it stands for Retrieval Augmented Generation. And it's as simple as the agent hears our question, it has to go out somewhere to retrieve that information, then it takes that information back, generates an answer, and then gives us that nice clean answer. So retrieval and generation are kind of the two main parts of Retrieval Augmented Generation. You can sort of just think about it as if someone asked you a question and you're not sure, so you go and Google it, and then once you understand the information, you give them back a response. But anyways, here is the system we'll be building today. Here's a look at the old one that uses window buffer memory as well as Pinecone. So I'm going to break down, you know, why I think Postgres is better than window buffer memory, and we'll talk about the differences between Supabase and Pinecone. But before we do that, let's just hop into a quick demonstration. So I've already went ahead and uploaded this document to our vector store, which is just information about a fake project called Project Mountain. So we're gonna hop in here and we'll ask the agent, what are the action items for Project Mountain and who are the parties involved? So we'll send this off, we'll watch it take place. And as this is going on, I just wanted to mention real quick, both of these workflows that we'll be going over today will be available for download in my free school community. Link for that will be in the description. You'll just download that JSON, you'll come up here and then you'll import from file and you'll have the stuff up and running, ready to go. And if you're looking to take AI automations a little further and you want some hands-on learning experience, and help, then feel free to join my paid community. Link for that will also be down in the description. And then if you're sort of a small business or you're looking to have me implement these systems for you, have me build them out for you, then please book a link in my website, which will also be linked down in the description. But let's take a look and see what this agent was able to respond to us with. So it said, here are the action items for Project Mountain and the parties involved as follows. So we have collect feedback samples, we have Sarah doing that, we have metrics, which will be John. It's giving us due dates as well. And then it's basically just summarizing everything that's gonna be going on within this project and sort of the timeline going on with it. So we can go into Supabase real quick, and obviously here's the quick vectorizations of the Project Mountain. And then we also have our Postgres memory in here where we can see the human asked, what are the action items for the Project Mountain, who are the parties involved? And then we can see the AI responded with this information. So that's sort of how this is going to work. Real quick, before we get into the actual step-by-step, we have this interface obviously where we're talking to the agent, and then we have this workflow that's going on in the backend, which is automatically putting stuff into Supabase based on a Google, Google Drive folder. And then also anytime a file in there is updated, it's also updating that record in Supabase as well as deleting the old record so that we're only interacting with relevant up-to-date information. All right, we're about to get into the step-by-step, so if you want to skip this part, feel free. But I'm just going to break down the difference between Postgres, window buffer memory, Pinecone, Supabase at a really high level. So first of all, why is Postgres gonna be better than window buffer memory? The first thing is about data safety and persistence. So PostgreSQL is sort of how we're putting the, you know, the chat memory like we just saw, and it's gonna keep your data safe even if N8N or your system restarts. Because when you use the window buffer memory, it's sort of temporary and then it's gonna wipe everything when closed. So even though window buffer memory is super, super easy to set up, because if you can see in here, if we unconnect this and we go to window buffer memory, that's all it is. It's no credentials. All you're going to do is set your context window length. But you know, in Postgres, you have to connect your credentials and make sure everything's set up, but it's still not too difficult. But that's one of the advantages of the window buffer memory. Second thing about Postgres is that it's scalable for big data. So it's going to handle large datasets more efficiently and you're going to be able to search through them using powerful tools like indexing, which is obviously very important for RAG workflows, especially once you get more documents and more things to chat with. And then finally, easy integration and long-term use. PostgreSQL is going to work seamlessly with N8N's databases. It's obviously got nodes that are gonna support multiple users and it's just gonna be really reliable and, you know, future-proof as you sort of add on to these workflows. Next we're talking about real quick Supabase versus Pinecone. Obviously I've been using Pinecone a lot and it's great, so we're just kind of breaking down the difference. So first of all, the purpose, Supabase is sort of a backend platform with, um, it also has built-in relational databases, whereas Pinecone is sort of more of just fully managed on vector databases. which is really good at, you know, their vector search and similarity queries. For scalability, Supabase is going to be better for small to medium-scale vector storage because they also have those relational queries and relational database integrations as well, whereas Pinecone is going to be more large-scale vector searches, billions and billions of vectors, you know, different indexes, different namespaces to search through, that sort of thing. Hosting, Supabase can be self-hosted or used as a managed service, while Pinecone is going to be sort of a SaaS, so there's no self-hosting option there. And then for the use case, Supabase ideal for, you know, relational data, metadata, vector search, while Pinecone is more for the, like I said, large-scale vector search with sort of minimal operational complexity. So now that we understand that, I hope that makes sense as far as, you know, future use cases when you're trying to figure out what to use here and there, what to plug in. But now let's get into that step-by-step build. All right, just open up a new workflow. The first thing that we're building out here is the RAG agent. So we're going to come in here obviously and grab an AI agent. We will leave this one as a tools agent. And as far as system prompts, for now we will just basically say, your helpful assistant, you will use the vector database to retrieve relevant information and respond to the user's query. And for now that will be simple enough because the only tool we're really plugging in is you know, the vector store. So we'll leave it as this for now. Um, we're going to connect our chat model, OpenAI. I'm going to use 4o Mini for this case. It's, um, you know, it's, it's powerful while being a lot more cost effective than 4o. Um, and for this use case, it will be fine, you know, as we're sort of just demoing. But, you know, as you get more data you need to search through and more complex information, you could probably go to 4o or, um, you know, Claude. So From here we have memory. Obviously we talked about the difference between, um, window buffer memory and then Postgres, so we're going to be doing Postgres in this case. And you need to obviously connect to your account, so what you're going to do here is create a new credential. You'll come in here and you'll see that you have this information to configure, which is definitely a little more daunting than setting up window buffer memory, but it's not too bad. So let's hop into Supabase so that we can get this information we need. So if you haven't created a Supabase account, go ahead and do that real quick. So once you're in Supabase, it's going to prompt you to create a project. So you're going to come in here, you just need to name your project, you need to give it a password, um, make it stronger. Okay, it needs to be even stronger than that. Okay, and then you have to remember this password obviously, so you can copy it. Want to put that somewhere safe because this is going to help you set up stuff in the future. Um, I'm just going to leave this as default and then we'll hit create new project. Okay, it will probably take a few minutes to set up your project. As you can see up here, it's setting it up still. but you can see some things like, um, we have our API keys. So obviously we'll use this later when we're setting up the Supabase vector store tool within N8N, but we're waiting for it to set up some information. As you can see, it just went through. Okay. So once you got that project set up, you're going to go down to the left-hand side, click on project settings. You will go to database right here, and then you'll have this screen pulled up. And this is the information we need to set up the Postgres. So we can see host. We're going to grab that real quick, copy it over, paste it into host. We will go to, um, our port. Grab that, and then this is going to be down near the bottom. We'll plug in the port right here. Um, what else do we need? The database should always be Postgres, so we need to grab our user, which will be right here. We will paste that into there, and then the password— as you can see, this is just, um, the password you typed in earlier. So let me do that real quick. And once you put in your password, hit save, and then you'll see connection tested successfully. Let me just call this one real quick, um, demo. So we have this set up here, and now once that's configured We don't really need to change anything else here. The table name is just going to be the table that goes into our Supabase that we can look at our chat history. So we can leave that as is. And then context window length, just how many interactions the model is going to be looking at for context. So 5 should be fine. If you want to bump it up to 10 or 20, you can do so. Let's just go with 10 for now. And that's basically it. So we have our memory set up. Every time we talk to the agent and the agent talks to us, the memory will be put into our Supabase in a table called nnn chat history, I think it was. Now let's set up the Supabase. So obviously we're gonna be adding a tool and we're gonna type in Vector Store. We can see Vector Store tool right here. We need to name this. So we will just call this, um, what are we pulling in? Project data. So I'll just call this project_data. We will also do the same up here. And then we need to obviously just describe what this tool is. So it's going to retrieve information about the projects. And so that should be good for now. Um, we've got project data. Now we need to obviously connect a model. We're going to go with Floral Mini once again, and then we're going to go into Vector Store, and we're grabbing Supabase, and we need to set up these credentials as well. So we'll click Create New Credential. We need to get a host and a service role secret. So back in Supabase, you might see host here. This is not what you're going to grab. You want to go to the left-hand side, go to Project Settings. You're going to click on API, and then up here, this URL, that's going to be the host. So you copy this You'll paste that right in there. And then in here you need to click on— for your service role secret, you'll click Reveal, you'll copy it, paste that into, um, you know, obviously this section right here. So let me do that real quick. Okay, we got the huge service role secret, paste it into there, we'll hit Save, should go green, we're good to go. And let me also just rename this one Demo. We got the credential set up, and now obviously the operation is— in this case we're retrieving documents, but now we need to set up the table. So if you come in here you will have no results because this current project that you just connected to, you haven't set up the table yet. So what we're gonna do is click on docs right here. It's gonna pull up the N8N docs, and then we have a super quick start for setting up your vector store. So you're gonna click into this and we have this chunk of code right here. All we're gonna do here is hit copy. We'll go back into Supabase and we're gonna go to our SQL editor over here on the left side. We'll paste this in. That's all you have to do is paste it in. You could go in here and change stuff if you want the table to be named something else. If you want to change some of these, matching criteria, but I don't touch anything. You're just going to hit run and you should see success, no rows returned. So now once we go into the table editor, we will refresh and we should see right here a table called documents. So this is our documents vector store that we'll be putting information into. We'll get records filled into here that we can look at once we actually put documents into it. So that's there. And then also another one right here will pop up. That's the one that will be NNChat history, and we can see what we've been than saying to the agent. But anyways, back in N8N, now we need to choose a table. We should see— not yet. So let's refresh N8N real quick. Okay. Now that we've refreshed it, we should be able to come in here, see our table, which will be documents. We're going to grab that. And then we need to add an option of query name and leave it as match documents. So we're good to go here. All we need to do now is set up the embedding. So we're going to set up text embedding 3 small, which is kind of the default right now. So we've got that set up. We'll hit save. If you've watched some other videos with Pinecone, when you're actually setting up your index, you will see an option to choose the embedding that you want in your vector store. So that's when you'd set up embedding 3 small, and then you'd want to choose that one in here as well. But in Supabase, you don't actually go through that process of manually setting that up, but we're going to do embedding 3 small. So hopefully not any confusion there. But this is going to be it as far as the agent. You know, there's no information in there. So if we said like, What are our projects looking like? It's obviously not going to return anything because we haven't built out that workflow that is going to, um, so it actually went and searched, but it's not going to return any actual information. It seems I'm unable to retrieve information about our current projects. So now we need to go through the process of, you know, actually putting information into that vector store. Okay, so in this workflow, we're going to start this one off with a Google Drive trigger. We'll come into Google Drive. The trigger is going to be on changes involving a specific folder. So we'll grab that. You need to set up your credentials. I've walked through this in multiple videos early on, also in my NNN Masterclass. But if you don't understand, you're basically just going to go in here, you can click Open Docs, and it will walk you through exactly how to set up your cloud account, you know, set up your, your credentials, your OAuth consent screen, all that kind of stuff. And it's, it's super simple. So you go into there, do that. The first thing we see is that once this trigger is active— so the workflow is not active yet, so it won't be doing this— but when it, when it is active every minute it will be checking in this folder. So it's going to be looking for changes involving a specific folder, which we will choose Projects. Oops, Projects. As you can see in here, we have my folders called Projects with Project Mountain in it that we used in the demo. And then we're looking for a file created. So anytime a file is created, this will go off and then the logic will take place to upload it into Supabase. And as you can see right here, we've got Project Mountain right there. So this is the the correct folder and we know it's working. And so we can move on to the next step, which is going to be we want to set the ID from, from the file that's being pulled in. We want to make sure that we have the, the ID of the file that's, that's coming through so that we can download it. And then we can also put the ID into the metadata of Supabase so that later when we want to update a file, we can grab that metadata in order to delete those records and then upload the new one. So in here we're gonna be doing a string. We will just call this file_id, and then we're gonna drag in the value. So you have to look through, you know, all the information that's coming back, and it may look intimidating. So we're just gonna close out of this stuff. What we'll be looking for is near the bottom. We're looking for the spaces ID. So you see an ID right here, permission ID. You're not gonna grab that one. That will not actually link to the correct document. And if you want to make sure you're doing it right, we're going to grab spaces ID. But if you want to make sure you're doing it right, you can go to the Google Doc, um, that you're actually pulling into that, um, folder. And in the URL, you will see this ID. So that's how you know that it's referencing the correct document. And also later, if you did the wrong one, you'll be able to tell because when we download it, it's not going to work. But if we test this step, we should see the file IDs coming back. So we're going to go here. So now we actually want to download this file. So we're going to do once again at Google Drive, and then we're going to go down within file actions to download a file. So grab that. Um, so obviously we're downloading a file here, and this is where, you know, typically you could choose from a list to grab all the files or grab a specific file you want, but in this case it's going to be dynamic obviously based on what's coming through. So we want to grab by ID, and then this is where we can grab the file ID earlier that we set in order to, um, you know, grab the right one. And if we test that we should see the actual binary coming through of that document. And so now we see this binary information, and that's how you know you got it right. But also what we want to do here is add options, Google File Conversion, and we want to convert Google Docs to text. You could also do PDF, but we're gonna do text here. So as you can see right now, it's coming through as binary, which is a doc extension. We test this again, and it will come through as text. So if you view it, we should see actual text information coming back rather than that binary. Okay, we've got the text and now we actually want to extract that. So we're going to grab an Extract from File node. We're going to go down to Extract from Text File, which is right here, and basically just want to test the step. And we should see that now it's coming back as actual data that we have in N8N. And then from here, all we need to do is push that into the Supabase vector store. So we're going to add an option here. We're going to type in Supabase, and we don't want to do Supabase, we want to do Supabase vector store. We'll use Supabase later, but for now we are just going to be doing add documents to vector store. We need to set up our credential once again, so we put that in there because we've already set that up. We're inserting documents. We are inserting documents to the table called documents. And then for options, you want to add options and then just leave that there because it's just going to match the documents and it already has that function put in there, so you don't need to touch it. That's all we need to do. And so obviously now we need to add our, our document loader. So in here we're doing JSON, we're just going to load all data input. And then for metadata, this is where it gets important because we want to grab the actual metadata from— or sorry, we want to put in the file ID like I said, so later we can reference it. So if we go to schema, we should be able to grab the set ID right here, which is coming through JSON file ID. And actually this is not correct, I think I just need to update my, my cloud instance. But, um, when you put something JSON dot whatever it is, that means that it's going to reference whatever currently most previous node that it's coming from. So this is trying to look for file ID within this extract from file, which obviously that's not there. All we have would be JSON.data. So, um, actually let's see, if we did JSON.data, it would come back with the, the project, the text that we extracted. So that's not what we want. What we need to do is we need to get the file ID from this set ID node over here that we actually, you know, this is where we grabbed that file ID. So in here, typically you should be able to just drag stuff in and it should be fine. I think this is just a bug right now because it's going as JSON. So what we need to do is reference the node. So in here we type in the curly braces. We can see we have different nodes. We're looking, we're looking through the set ID node, and then within there Now we want to look for the JSON, or actually no, it should be item.json. Move this so we can see.file_id. Okay, now we can see we're getting the actual file ID back, and this is how we want it because now in the metadata of our Supabase we will see a file ID. So that should be good. We've added metadata. We want to add a recursive character text splitter. If you're looking for more information about text splitters, then please go watch my NNN Masterclass. I walk through sort of the difference between the 3 options that we have for text splitters. And then our embedding, once again, we will be doing text embedding 3 small. So at this point, we have this first part of this workflow set up for when a new file is created within our folder. So if you, you know, we got a new project, we wrote out a project brief. and then we drag it into this folder called projects. Once this workflow's active up here, it would automatically grab it and put it in. So let's test this. And then we should go back into our table, which is right here. It's empty. Um, there we go. It just popped through. So now we have these 3 vectorizations of this information. As you can see, um, we've got like the, the information right here. And then if you go into the metadata, each of these, we should see a file ID. So before it would have just had all this information, the source, the blob type. But now we've made sure that we put in file ID so that later we can reference it once again. So we've got this. Also, you can see the chat history, which is earlier we asked what are our products looking like and it was unable to get anything. So we've got that and now we have data in there. And so, you know, we could go chat with this agent. Actually, yeah, let's just do that real quick. We'll go back to the RAG agent. Where we currently ask what they're looking like. And now we will say, give me an overview of Project Mountain, because that's the one we just put in there. So now it will be obviously understanding our question, going to the database to grab that information. It's retrieving it. Now it's generating an answer right here, generating an answer. And then we can pop back into here. It's updating our, um, is it not going to be in here? Yeah, there it is. Um, it updated the chat history, and now we see It's an AI-powered tool being developed by Summit Enterprises. It's giving us goals, features, the team composition, all that kind of stuff. And if we go back into Supabase, we should see in our chat history, once we refresh, now we have this interaction we just had right here. Give me an overview of our projects or Project Mountain, and then it gave us the overview. So that's how that works. And now we just need to set up the second part of this workflow, which is going to be if a folder or if a file is updated, it will change information. So we're gonna add a Google Drive trigger once again. We'll go down to triggers and we'll want on changes involving a specific folder once again. Same thing, we're grabbing the same, same folder, and instead of watching for file created, we'll just be looking for a file updated. So let's real quick go in here and just say file updated. We will come in here and just make this one new file so we understand what's going on in each one. Um, let's also just organize this. We'll call this— this is the actual node that's downloading the file, and then we've got extracting from file and then putting into Supabase. So yeah, let's get working on this, this workflow now. So we've got our file updated, um, Let's actually just— no, for now it's fine. So we'll make a change later and we'll see. But we fetch that event and it's going to grab Project Mountain once again. Um, from here what we want to do is grab a Supabase, and we're not doing VectorStore this time, we're doing actual Supabase, and so that we can delete a row within our table. So we're going to set up the credential again, we're going to be deleting a row, we're going to be looking through documents And then we want to build this as a string. And now we have to type in how we want to make sure that it's— how Supabase should be looking for which rows to delete. Okay, so in here, um, it's going to be sort of a filter, but it might look a little codey. So what we're doing is metadata, because in Supabase we're going to be looking through the metadata right here, obviously. And then in the metadata we want to look for— oh, sorry, we're in chat history. In the metadata of these vectorizations, we're looking through the metadata to look at the file ID. So we're going to be saying like, within metadata, look for file IDs that equal this, and if they equal that, then delete them. So metadata, we're going to do a dash with two arrows, or greater than signs, and then we're going to say file ID because that's what it's going to be looking for. And then we're going to do equals or I'm sorry, equals like period. And then we're gonna go with two asterisks, two stars, and then change this to an expression. And then whatever is going inside of these two stars is what it's actually looking for. So we're gonna, once again, we need to close down to grab the file ID of the document that it's looking for. Once again, don't go to permissions ID, we want spaces ID. So we'll pull this in right here and It comes in as just JSON.ID, and it has the correct information right there. So all we're going to do is go back in here. We can see that there's 3 rows that have that ID. We're going to come back into here and then test this step. And if we did this correctly, we should get this. This is how it should come back. So that's good. It has 3 items because it deleted all 3 of those, those rows. And now we switch back into Supabase. You can see that they just disappeared. So this is good. Now every time something's updated, it's going to delete those old ones so that we can download the new file and then put the new file into Supabase so that we're only interacting with actual accurate information. So we'll save this. Next up here is that we want to grab the, um, the IDs. So we're going to do another set node, and once again, we're just mapping out the actual file ID again so that we can reference it later. At this point it's pretty repetitive, so we're going to grab it, call it file ID, and then do right here. So as you can see, it's referencing the node called file updated, because if it was just to do JSON, it would be looking for— that's actually a great point. If we just did JSON.ID, let's test this real quick so we can see it's pulling back the actual IDs. But if we just did JSON.ID, it would grab this ID right here, so it would be grabbing the ID of the— it would be grabbing basically the row ID of the vector database. So we don't want that. So make sure you specify what code you're looking for. And so now if you can see, we have 3 items coming back because there were 3 rows. So what we want to do here now is limit because we only want 1 to come back. So all we need to do is 1, keep the first item, test that. Now we have 1 ID coming back rather than all 3. I'm not sure if it's like completely necessary, but it keeps things cleaner, and then you're only trying to download like one file. So that's why we're doing that. But anyways, from there we want to actually download the file— not download, we want to grab a Google Drive node right here. We're going to download that file, and this is pretty much the exact same thing as the previous one with an ID and edit fields. We're grabbing in this file ID. So perfect, it's referencing the node, and we'll hit test step. So now we can see the Project Mountain— this would be the updated folder, or sorry, updated file. Once again, we want to do file conversion, text, run that again, and we should see the actual text coming through. As we can see now, it's a text folder or text file, and now we've got this. We also could have easily just copy and pasted this node down here, which probably would have been the smarter thing to do, but Um, nobody's perfect. So anyways, download file 2. So we've got this, and then it's the exact same thing. So we can— this time we'll just copy and paste this node down here to extract from a text file. We'll run that. We can see the information coming through. And then honestly, I think this also can just be duplicated as well because we're just doing the exact same thing. As long as we have— this is the only thing I think we need to change. So We're grabbing it from— let's see, okay, so we just want to call this set ID 2. And so this one right now is looking through a node called set ID, which obviously there's no information there because it's looking through this one. So now we need to make it say, in this case, you'll be looking through set ID number 2. So if we come in here and we just add a number 2 we should be fine. Um, can't determine which item to use. Maybe it's just because it hasn't ran. Let's— okay, let's try something. We'll run this. Now there's an error. Okay, let's just try it again. We'll do it manually. So anyways, why is it doing that? Why is it doing that? Okay, bear with me here. Okay, so now we're grabbing set ID 2. It's working. So what do we do? Item JSON file ID. No, do we not name it the same thing? File underscore ID. Oh, okay, maybe it's because we want to maybe grab it from limit because it's just limiting one. Let's try that. Why does it do that when I— okay, delete that. We're gonna go from limit And we can just maybe say item.json.file_id. Okay, perfect. There we go. Now we're getting the correct ID back that we want to put into the metadata. Once again, we'll hit save and now we'll run this again. Although, yeah, so there's nothing in there right now. We run this again and we should see 3 new vectors pop into there. Let's go and see if we can see it live. We might just have to give it a refresh. Yeah, we'll give it a refresh. There we go. So we've got these, um, 3 new vector stores. So the first ones were 1, 2, 3, deleted those. Now we have 4, 5, 6, and we can see in here we've got the metadata. So it's all working as it should, and this is really it. So one thing I wanted to mention is, you know, ideally you would also have some sort of, you know, a node down here where— let me just show you. So a cool option would be if you wanted to have another trigger down at the bottom, which is going to be changes involving a specific folder. You'd grab that same folder, um, once this loads up. I think I'm overwhelming my computer with, with, um, Supabase information. But, um, let's see, we grab a folder Anyways, my point was it'd be cool if there was like a file removed, file deleted. That way you could just, you know, delete folders once a product's done. But also maybe it's good to give a summary of like a project that's done or whatever it is. But there's probably a use case where you wanted to remove stuff. So in that case, you'd have to probably manually go into your Supabase, delete those vectors. You could also just update your file and say like this project has concluded or this is no longer relevant, or whatever it may be, and it would obviously update that. But the point would be you, you'd grab the ID and then you just have a Supabase thing to delete it, and then it would just literally just be those two nodes. So it would be like a delete row down here, and then maybe like a, you know, at the end of these you could have a notification. You could at the end of all of these workflows have a notification that said like, okay, new file was created and added to Supabase, and then it would just like text you that. Same thing over here, blank was updated and deleted and then re-uploaded to Supabase. And then down here was like Project Mountain was deleted from Supabase. So you could always, you know, add some more stuff off of this, and this one would just delete the file, and then that would all it would do. But I guess a workaround for this could be you could have like a node that is always running to compare the files or the folder, and then you would just see if like a comparison doesn't match up with this one, then it would delete whatever like isn't syncing from Supabase. So that would be like just a quick workaround, but maybe in the future they'll have just an integration in Google Drive where you can just do that right away. So anyways, we're gonna make this workflow active and we're gonna test out some stuff. So got it. So this workflow is now active. It should be looking for within this folder right here if anything new is added. So I'm gonna make a new document real quick, we'll add it in there, and then we'll watch the execution happen. Okay, we're back with a new one. This one's called Project Snow. We were going to put this one into the folder. I don't know if you can tell, but, um, yeah, it's almost winter and I'm looking forward to skiing, so that's what's top of mind. But anyways, Project Snow right here, we're going to drag that into Projects. So now in this folder we have a folder, or we have a new file just got created, just got put into the, the, what's it called, the folder. So here's that execution we grabbed in here. Project Snow, which should be— I always have a hard time finding this. Anyways, we'll go to JSON. Project Snow. I might have scrolled too far once again. Sorry about that. Um, you know what, never mind, we'll see it, we'll see it later. So set ID, downloads the file, extracts from file, and now we can see that the project brief is Project Snow. And then it got put into Supabase. We'll come in here, refresh this. We should see 789. So now we've got these new ones with their unique IDs in there. Um, so yeah, let's go over to the RAG agent and we will talk to the agent about Project Snow. We'll say, um, what is Project Snow's budget? That's simple enough. We'll come in here and see that the Project Snow budget is










