Your AI Agent Prompts Are Wrong - Here's The Fix

Nate from FreeSchool explains why static prompts fail and introduces reactive prompting: start minimal, then add tool descriptions, rules, and examples only after you see errors. He walks through an n8n demo building a calendar and email agent, showing how to fix problems by inserting specific prompt lines instead of rewriting everything from scratch.
Chapters
Building AI agents and hooking up different tools is fun and all, but the quality and consistency of the performance of your agents directly ties back to the quality of the system prompt that you put in there. If you guys don't know me, my name's Nate. I've been building agents for a while now, and I also run a school community that's all about building AI agents with NN. We've got different deep dive topics in there like building AI agents, vector databases, APIs and HTTP requests, and also doing step-by-step builds of all the videos shown on my channel. And if it's something you're interested in, check out the link in the description. Anyways, today what we're going to be talking about is what actually goes into creating an effective prompt so that your agents perform as you want them to. I'm going to be going over the most important thing that I've learned while building out agents and prompting them that I don't think a lot of people are doing. So let's not waste any time and get straight into this one. All right, so I've got a document here. If you want to download this one to follow along or just have it for later, you can do so by joining my FreeSchool community. The link for that's down in the description. You'll just click on YouTube Resources and find the post associated with this video, and you'll be able to download the PDF right there. Anyways, what we're looking at today is how we can master reactive prompting for AI agents in N8N. And the objective of this document here is to understand what prompting is, why it matters, develop a structured approach to reactive prompting when building out AI agents, and then learn about the essential prompt components. So let's get straight into it and start off with just a brief introduction. What is prompting? Make sure you stick around for this one because once we get through this doc, we're going to hop into N8N and do some live prompting examples. So within our agents, we're giving them a system prompt, and this is basically just coding them on how to act. But don't be scared of the word code because we're just using natural language instead of something like Python or JavaScript. A good system prompt is going to ensure that your agent is behaving in a very clear, very specific, and a very repeatable way. So instead of us programming some sort of Python agent, what we're doing is we're just typing in, you're an email agent. Your job is to assist the user by using your tools to take the correct action, exactly as if we were instructing an intern. And why does prompting matter? I'm sure by now you guys already have a good reason in your head of why prompting matters, and it's pretty intuitive, but let's think about it like this as well. Agents are meant to be running autonomously, and they don't allow that back and forth interaction like ChatGPT. Now, yes, there can be some human in the loop within your sort of agentic workflows, but ideally, you put in an input, it triggers the automation, triggers the agent to do something, and then we're getting an output. Unlike ChatGPT, where you ask it to help you write an email, and you can say, hey, make that shorter, or you can say, make it more professional, We don't have that, um, luxury here. We just need to trust that it's going to work consistently and high quality. So our goal as prompters is to get the prompts right the first time so that the agent functions correctly every single time it's triggered. So the key rule here is to keep the prompts clear, simple, and actionable. You don't want to leave any room for misinterpretation. Um, and also less is more. I'll sometimes, I'll see people just throw in a novel and that's just obviously going to be more expensive for you and also just more room to confuse the agent. So less is more. So now let's get into the biggest lesson that I've learned while prompting AI agents, which is prompting needs to be done reactively. I see way too many people doing this proactively, throwing in a huge system message and then just testing things out. This is just not the way to go. So let's dive into what that actually means to be prompting reactively. First of all, what is proactive prompting? This is just writing a long detailed prompt up front after you have all your tools configured and all of the sort of, you know, standard operating procedures configured. And then you start testing it out. The problem here is that you don't know all the possible edge cases and errors in advance, and debugging is going to be a lot more difficult because if something breaks, you don't know which part of the prompt is causing the issue. You may try to fix something in there and then the issue originally you were having is fixed, but now you cause a new issue, and it's just going to be really messy as you continue to add more and more, and you end up just confusing both yourself and the agent. Now, reactive prompting, on the other hand, is just starting with absolutely nothing. And adding a tool, testing it out, and then slowly adding sentence by sentence. And as you've seen in some of my demos, we're able to get like 6 tools hooked up, have no prompt in there, and the agent's still working pretty well. At that point, we're able to start adding more lines to make the system more robust. But the benefits here of reactive prompting are pretty clear. The first one is easier debugging. You know exactly what broke the agent, whether that's, I added this sentence and then the automation broke. All I have to do is take out that sentence. Or I added this tool and I didn't prompt the tool yet. So that's what caused the automation to break. So I'm just gonna add a sentence in right here about the tool. This is also going to lead to more efficient testing because you can see exactly what happens before you hard prompt in fixes. And essentially, you know, I'll talk about hard prompting more later, but essentially what it is, is, um, you're basically seeing an error and then you're hard prompting in the error within the system prompt and saying, hey, like you just did this, that was wrong. Don't do that again. and we can only do that reactively because we don't know how the agent's going to react before we test it out. Finally, we have the benefit that it prevents overcomplicated prompts that are hard to modify later. If you have a whole novel in there and you're getting errors, you're not going to know where to start. You're going to be overwhelmed. So taking it step by step, starting with nothing, and adding on things slowly is the way to go. And so if it still isn't clicking yet, let's look at a real-world example. Let's say you're teaching a kid to ride a bike. If you took a proactive approach, you'd be trying to correct the child's behavior before you know what he or she is going to do. So if you're telling the kid to keep your back straight, lean forward, you know, don't tilt a certain way, that's going to be confusing because now the kid is trying to adjust to all these things you've said and it doesn't even know what it was going to do, what he or she was going to do in the beginning. But if you're taking a reactive approach, and obviously maybe this wasn't the best example because you don't want your kid to fall, but You let them ride, you see what they're doing, you know, if they're leaning too much to the left, you're gonna say, okay, well maybe you need to lean a little more to the right to center yourself up. And only correct what they actually need to have corrected. This is gonna be more effective, fewer unnecessary instructions, and just more simple and less overwhelming. So the moral of the story here is to start small, observe errors, and fix one problem at a time. So let's take a look at some examples of reactive prompting that I've done in my Ultimate Assistant workflow. As you can see right here, I'm sure you guys have seen that video by now. If you haven't, I'll link it right up here. But I did a ton of reactive prompting in here because I have one main agent calling 4 different agents. And then within those sub-agents, they all have different tools that they need to call. So this was very, very reactive when I was prompting this workflow or this system of agents. I started with no persistent prompt at all. I just connected a tool and I tested it out to see what happened. So an example would be I hooked up an email agent, but I didn't give it any instructions. And I'm running the AI to see if it will call the tool automatically. A lot of times it will, and then it only comes to when you add another different agent that you need to prompt in, hey, these are the two agents you have, here's when to use each one. So anyways, adding prompts based on errors. Here I have my system prompts, so if you guys wanna pause it and read through, you can take a look. But you can see it's very, very simple. I've got one example, I've got basically one brief rule, and then I just have all the tools it has and when to use them. And it's very, very concise and not overwhelming. And so what I want you guys to pay attention to real quick is in the overview. Right here I said, you know, you're the ultimate personal assistant, your job is to send the user's query to the correct tool. That's all I had at first. And then I was getting this error where I was saying, hey, write an email to Bob. And what was happening is it wasn't sending that query to the email tool, which it's supposed to do. It itself was trying to write an email, even though it has no tool to write an email. So then I reactively came in here and said, you should never be writing emails or creating event summaries, you just need to call the correct tool. And that's not something I could have proactively put in there because I didn't really expect the agent to be doing that. So I saw the error and then I basically hardcoded in what it should not be doing and what it should be doing. So another cool example of hardcoding stuff in is using examples. You know, we all understand that examples are gonna help the agent understand what it needs to do based on certain inputs and how to use different tools. And so right here you can see I added this example, but we'll also look at it down here 'cause I basically copied it in. What happened was the AI failed in a very specific scenario. So I added a concrete example where I gave it an input, I showed the actions it should take, and then I gave it the output. So in this case, what happened was I asked it to write an email to Bob, and it tried to send an email, or it tried to hit the send email agent, but it didn't actually have Bob's email address, so the email didn't get sent. So what I did here was I put in the input, which was send an email to Bob asking him what time he wants to leave. I then showed the two actions it needs to take. The first one was use the contact agent to get Bob's email, send this email address to the email agent tool. And then the second action is use the email agent to send the email. And then finally, the output that we want the personal assistant to say back to the human is, "The email has been sent to Bob. Anything else I can help you with?" The idea here is you don't need to put examples in there that are pretty intuitive and that the agent's going to get right already. You only want to put in examples where you're noticing common themes of the agents failing to do this every time. I may as well hardcode in this example input and output and tool calls. So step 4 is to debug one error at a time. Always change one thing and one thing only at a time, so you know exactly what you changed that broke the automation. Too often I'll see people just get rid of an entire section and then start running things, and now it's like, okay, well, we're back at square one because we don't know exactly what happened. So you wanna get to the point where you're adding one sentence, you're hitting run, and it's either fixing it or it's not fixing it, and then you know exactly what to do, you know exactly what broke or fixed your automation. And so one thing honestly I wanna admit here is I created that system prompt generator on my FreeSchool community, And really the idea there was just to help you with the formatting because I don't really use that thing anymore because of the fact that doing that is very proactive in the sense that we're dropping in a sort of a query into ChatGPT, the custom GPT I built. It's giving us a system prompt and then we're putting that whole thing in the agent and then just running it and testing it. And in that case, you don't know exactly what you should change to fix little issues. So just wanted to throw that out there. I don't really use that system prompt generator anymore. I now always like handcraft my prompts. Anyways, from there, what you want to do is scale up slowly. So once you confirm that the agent is consistently working with its first tool and its first rule and its prompt, then you can slowly add more tools and more prompt rules. So here's an example. You'll add a tool, you'll add a sentence in the prompt about the tool, test out a few scenarios. If it's working well, you can then add another tool and keep testing out and slowly adding pieces. But if it's not, then obviously you'll just hard prompt in the changes of what it's doing wrong. And how to fix that. From there, you'll just test out a few more scenarios, and then you can just kind of rinse and repeat until you have all the functionality that you're looking for. All right, now let's look at the core components of an effective prompt. Each agent you design should follow a structured prompt to ensure clarity, consistency, and efficiency. Now, there's a ton of different types of prompting you can do based on the role of agent. Ultimately, they're gonna fall under one of these three buckets, which is tool-based prompting, conversational prompting, or like content creation type prompting. And then categorization slash evaluation prompting. And the reason I wanted to highlight that is because obviously if we're creating like a content creation agent, we're not going to say what tools it has if it has no tools. But, um, yeah, I just wanted to throw that out there. And another thing to keep in mind is I really like using Markdown formatting for my prompts. As you can see these examples, we've got like different headers with pound signs and we're able to specify like different sections. We can use bulleted lists, we can use numbered lists. I've seen some people talk about using XML for prompting. I'm not a huge fan of it because, um, as far as human readability, I think Markdown just makes a lot more sense. So that's what I do. Anyways, now let's talk about the main sections that I include in my prompts. The first one is always a background. So whether this is a role or a purpose or a context, I typically call it something like an overview. But anyways, just giving it some sort of background that defines who the agent is, what its overall goal is. And this really sets the foundation of, you know, sort of identifying their persona, their behavior. And if you don't have this section, the agent is kind of going to lack direction and it's going to generate really generic or unfocused outputs. So set its role. And this could be really simple. You can kind of follow this template of you are a blank agent designed to do blank. Your goal is blank. So you are a travel planning AI assistant that helps users plan their vacations. Your goal is to provide detailed, personalized travel itineraries based on the user's input. Then we have tools. This is obviously super, super important when we're doing sort of non-deterministic agent workflows. Where they're gonna have a bunch of different tools and they have to use their brain, their chat model, to understand which tool does what and when to use each one. So this section tells the agent what tools it has access to and when to use them. It ensures the AI selects the right tool for the right task, and a well-structured tools section prevents confusion and obviously makes AI more efficient. So here's an example of what it could look like. We have like the markdown header of tools, and then we have like a numbered list. We're also showing that the tools are in bold. This doesn't have to be the way you do it, but Sometimes I like to show them in bold. And it's, you can see it's really simple. It's not too much, it's not overwhelming, it's not too, you know, it's just very clear. Google search, use this tool when the user asks for real-time information. Email sender, use this tool when the user wants to send a message. Super simple. And what else you can do is you can define when to use each tool. So right here we say we have a contact database. Use this tool to get contact information. You must use this before using the email generator tool. Because otherwise it won't know who to send the email to. So you can actually define these little rules, keep it very clear within the actual tool layer of the prompt. And then we have instructions. I usually call them rules, as you can see. Um, you can maybe even call it like a standard operating procedure, but what this does, it outlines specific rules for the agent to follow. It dictates the order of operations at a high level. Just keep in mind, you don't want to say do this in this order every time, because then it's like, why are you even using an agent? The whole point of an agent is that it's, you know, it's taking an input and something happens in this black box where it's calling different tools. It may call this one twice, it may call this one 3 times, it may call them none at all. The idea is that it's variable, it's not deterministic. So if you're saying do it in this every time, then you should just be using a sequential workflow. It shouldn't even be an agent. But obviously the rules section helps prevent misunderstandings. So here's like a high-level instruction, right? You're greeting the user politely. If the user provides incomplete information, you ask follow-up questions. Use the available tools only when necessary. Structure your response in clear, concise sentences. So this isn't saying like, you do this in this order every time. It's just saying, when this happens, do this. If this happens, do that. So here's an example for AI task manager. When a task is added, you confirm with the user. If a deadline is missing, ask the user to specify one. If a task priority is high, send a notification. Store all tasks in the task management system. So it's very clear too. Um, we don't need all these extra filler words because remember, The AI can understand what you're saying as long as it has like the actual context words that have meaning. You don't need all these little fillers. You don't need these long sentences. So moving on to examples, which, you know, sample inputs and outputs and also actions within those between the inputs and outputs. But this helps the AI understand expectations by showing real examples. And these are the things that I love to hard code in there, hard prompt in there. Because like I said, there's no point in showing an example if the AI was already going to get that input and output right every time. You just want to see what it's messing up on and then put an example in and show it how to fix itself. So more clear guidance, and it's going to give you more accurate and consistent outputs. Here's an example where we get the input that says, can you generate a trip plan for Paris for 5 days? The action you're going to take is first call the trip planner tool to get X, Y, and Z. Then you're going to take another action, which is calling the email tool to send the itinerary. And then finally, the output should look something like this. Here's a 5-day Paris itinerary. Day 1, day 2, day 3, day 4, day 5. And then I typically end my prompts with like a final notes or important reminders section, which just has like some miscellaneous but important reminders. It could be current date and time, it could be rate limits, it could be, um, something as simple as like don't put any emojis in the output. Um, and sometimes why I do this is because something can get lost within your prompt. And sometimes like I, I've thrown the today's date up top, but then it only actually realizes it when it's in the bottom. So Playing around with the actual, like, location of your things can be sometimes help it out. Um, and so having a final notes section at the bottom, not with too many notes, but just some quick things to remember, like always format responses as Markdown. Here's today's date. If unsure about an answer, say I don't have that information. So just little miscellaneous things like that. Now I wanted to quickly talk about some honorable mentions because like I said earlier, the prompt sections and components varies based on the actual type of agent you're building. So in the case of like a content creator agent that has no tools, you wouldn't give it a tool section, but you may want to give it an output section. So here's an output section that I had recently done for my voice travel agent, which if you want to see that video, I'll drop a link right here. But what I did was I just basically included rules for the output because the output was very specific with HTML format and it had to be very structured and I wanted horizontal lines. So I created a whole section dedicated towards output format, as you can see. And because I used 3 pound signs for these subsections, the agent was able to understand that all this rolled up into the format of the output section right here. So anyways, I said the email should be structured as HTML that will be sent through email. Use headers to separate each section. Add a horizontal line to each section. I said what, what should be in the subject. I said what should be in the introduction section. I said how you should list these departure dates, return dates, flights for the flight section. Here's something where I basically gave it like the HTML image tag and I showed how to put the image in there. I showed to make, I said like make an inline image rather than an attachment. I said to have each resort with a clickable link. I also was able to adjust the actual width percentage of the image by specifying that here in the prompt. So yeah, this was just getting really detailed about the way we want the actual format to be structured. You can see here we have activities that I actually misspelled in my agent, but it didn't matter. And then finally, just to sign off. And then just some final additional honorable mentions, something like memory and context management, some reasoning, some error handling. But typically, I think that these can be just kind of 1 or 2 sentences that can usually go in like the rules or instructions section. But it depends on the use case, like I said. So if it needs to be pretty robust, then creating an individual section at the bottom called memory or error handling could be worth it. It just depends on like I said, the actual use case and the goal of the agent. Okay, cool. So now that we've got through that document, let's hop into NN and we'll just do some really quick examples of some reactive live prompting. Okay, so I'm gonna hit tab. I'm gonna type in AI agent. We're gonna grab one and we're gonna be communicating with it through this connected chat trigger node. Now I'm gonna add a chat model real quick just so we can get set up, up and running. We have our 4o Mini. We're good to go. And just a reminder, there is zero system prompt in here. All it is is that you are a helpful assistant. So what's the first thing to do is we want to add a tool, test it out. So I'm going to add a Google Calendar tool. I'm just going to obviously select my calendar to pull from. I'm going to, you know, fill in those parameters using the model by clicking that button. And I'm just going to say this one's called Create Event. So we have Create Event. And so now we're going to do our test and see if the tool is working properly. I'm going to say, create an event for tonight at 7 PM. So we'll send this off. We should see the agent's able to understand to use this Create Event tool because it's using an automatic description. But now we see an issue. It created the start time for October 12th, 2023, and the end time for also October 12th, 2023. So this is our first instance of reactive prompting. It's calling the tool correctly, so we don't really need to prompt in like the actual tool name yet. It's probably best practice just to do so. But first, I'm just going to give an overview and say, You are a calendar. Actually, no, I'm just gonna say you are a helpful assistant because that's all it is right now. And we don't know what else we're adding into this guy. But now we'll just say tools is create event just so it's aware. Use this to create an event. And then we wanna say final notes. Here is the current date and time because that's where it messed up is because it didn't know the current date and time. Even though it was able to call the correct tool. So now we'll just send this same thing off again, and that should have fixed it. We reactively fixed the error, and we're just making sure that it is working as it should now. Okay, there we go. It just hit the tool, and it says the event has been created for tonight at 7 PM. And if I click into my calendar, you can see right there we have the event that was just created. So cool. Now that's working. What we're gonna do now is add another tool. So we'll drag this one over here, and let's say we want to do a Send email tool. We're gonna send a message. We're gonna change the name to send email. And just so you guys are aware, like how it's able to know right here, tool description, we're setting automatically. If we set manually, we would just say, you know, use this tool to send an email, but we can just keep it simple. Leave it as set automatic. I'm gonna turn on to subject and message as defined by the model. And that's gonna be it. So now we just wanna test this thing again before we add any prompts. We'll say send an email. To bob@example.com asking what's up. We'll send this off. Hopefully it's hitting the right tool, so we should see— there we go, it hit the Send Email tool and the email got sent. We can come in here and check, everything was sent correctly. Although what we noticed is it's signing off as Best Placeholder Your Name, and we don't want to do that. So let's come in here and let's add a tool section for this tool, and we'll tell it how to, how to act. So Send Email, that's another tool it has. And we're gonna say, use this to send an email. And then we're gonna say, sign off emails as Frank. Okay, so that's reactively fixing an error we saw. I'm just now going to send off that same query. We already know that it knows how to call the tool, so it's gonna do that once again. There we go, we see the email was sent, and now we have a sign off as Frank. So that's two problems we've seen, and then we've added one super short line into the system prompt and fixed those problems. Now, let's do something else. Let's say in Gmail, we want to be able to label an email. And in order to label an email, as you can see, add label to a message, we need a message ID, and we need a label name or an ID for that label. And this is— we could choose from a list, but more realistically, we want the label ID to be pulled in dynamically. So, if we need to get these two things, what we have to do is first get emails and also get labels. So first I'm gonna do get many. I'm gonna say this is using, you know, we're calling this tool get emails, and then we don't want to return all, we wanna do a limit, and we also wanna choose from a sender. So we'll have this also be dynamically chosen. So, cool. We don't have a system prompt in here about this tool, but we're just going to say, get my last email from Nate Herkelman. So we'll send that off, it should be hitting the get emails tool, filling in Nate Herkelman as the sender, and now we can see that we just got this email with the subject "Hello." We have the message ID right here, so that's perfect. And now what we need to do is we need to create a tool to get the label ID. So I'm gonna come in here and I'm gonna say, um, get many, and we're gonna go to label. We're going to do, um, actually we'll just return all, that works. There's not too many labels in there. Um, and we have to name this tool of course, so we're gonna call this get labels. So once again, there's no tools in or no prompt in here about these two tools at all. And we're gonna say, get my email labels. We'll see if it hits the right tool. There we go. It did. And it is going to basically just tell us, you know, here they are. So here are our different labels. Um, and here are the ones that we created. So promotion, customer support, high priority, finance and billing. Cool. So now we can try to actually label an email. So that email that we just got from, um, from Nate Herkelman that said hello, let's try to label that one. So I'm going to add another Gmail tool, and this one's going to be add a label to a message, and we need the message ID and the label ID. So I'm just going to fill these in with the model parameter, and I'm going to call this tool add label. So there's no prompting for these 3 tools right here, but we're going to try it out anyway and see what happens. So add a promotion label to my last email from Nate Herkelman. Send that off, see what happens. It's getting emails. It tried to add a label before, so now we're kind of, we got in that weird loop. As you can see, it tried to add a label before it got labels, so it didn't know what to do, right? We'll click into here. We'll see that I don't really exactly know what happened. Category promotions. Looking in my inbox, anything sent from Nate Herkelman, we have the email right here, but it wasn't accurately labeled. So let's go back into our agent and prompt this thing a little bit better to understand how to use these tools. So I'm going to basically go into the tool section here and I'm gonna tell it about some more tools that it has. So get emails, right? This one was, it was already working properly and we're just saying use this to get emails. Now we have to add get labels. We're just saying use this to get labels. Um, and we know that we want it to use this before actually trying to add a label, but we're not going to add that yet. We're going to see if it can work with a more minimalistic prompt. And then finally, I'm going to say add labels. And this one is use this tool to add a label to an email. Okay, so now that we just have very basic tool descriptions in here, we don't actually say like when to use it or how. So I'm gonna try this exact same thing again. Add a promotion label to my last email from Nate Herkelman. Once again, it tried to use add label before, and it tried to just call it twice, as you can see. So not working. So back into email, I just refreshed, and you can see the email is still not labeled correctly. So let's do some more reactive prompting. What we're gonna do now is just say, in order to add labels, so in the description of the add label tool, I'm gonna say, you must first use get emails to get the message ID. And actually, I want to make sure that it knows that this is a tool. So what I'm going to do is I'm going to put it in a quote, and I'm going to make it the exact same capitalization as we defined over here. So you must first use get emails to get the message ID of the email to label. Then you must use get labels to get the label ID of the email to label. Okay. So we added in this one line. So if it's still not working, we know that this line wasn't enough. I'm gonna hit save and I'm gonna try the exact same thing again. Add a promotion label to my last email. So it's getting, now it's getting labels, and now it still had an error with adding labels. So we'll take a look in here. It said that it did it successfully, but obviously didn't. It filled in label 127 blah blah blah. So I think the message ID is correct, but the label ID is not. So what I'm going to try now is reactively prompting in here. I'm gonna say the label ID of the email to label. We'll try that. We'll see if that fixes it. It may not. We'll have to keep going. So now, we'll see it's gonna, at least it fixed the order, right? So it's getting emails and getting labels first. And now, look at that. We successfully got a labeled email. As you can see, we have our, oop, maybe we didn't. We'll have to go into Gmail and actually check. Okay, never mind, we did. As you can see, we got the promotion email for this one from Nate Herkelman that says hello. And, um, yeah, that's just going to be a really cool, simple example of how we sort of take on the process of running into errors, adding lines, and being able to know exactly what caused what. So I know the video was kind of simple and I went through it pretty fast, but I think that it's going to be a good lesson to look back on as far as the mindset you have in approaching reactively prompting and adding different tools and testing things. Because at the end of the day, building agents is a super, super test-heavy, iterative, you know, refining process of build, test, change, build, test, change, all that kind of stuff. So as always, really appreciate you guys making it to the end of this video. If you learned something new or if you enjoyed it, please leave a like. It definitely helps me out a ton, and I will see you guys in the next one. Thanks so much, everyone.










