Video: Agent Harnesses & Deep Agents 101 | Duration: 2246s | Summary: Agent Harnesses & Deep Agents 101 | Chapters: Welcome and Introduction (0s), Understanding Agents (90.695s), Deep Agents Overview (225.94s), Human in the Loop (320.425s), Sub Agents (411.615s), Building Journal Agent Demo (600.175s), System Prompts (770.975s), System Prompts and Tools (912.58s), Short-Term Memory (1141.69s), Human in the Loop (1301.31s), Sub Agents (1527.515s), Sub-Agent Demo (1628.75s), Assignment & Wrap-up (1798.1s), Resources and Wrap-Up (1929.62s), Q&A and Wrap-Up (2048.155s), Closing Remarks (2173.485s)
Transcript for "Agent Harnesses & Deep Agents 101": Hey, everyone. Thanks for joining us today. Sorry for being a little bit late. I realized I didn't start the session right on the hour. But I'm Jezell, the education marketing manager here at LangChain. And today, I'm joined by Jess and Ishaan, who are both education engineers here at LangChain. Jess will be going over the Colab notebook that I've linked in the chat. So you have if you haven't taken a look at that already, please do as we go over it together. And there will also be an additional take home assignment at the very end for you to work on as well. And as usual, please feel free to use the q and a function to ask your questions, and we'll do our very best to answer them. And this is also our first time running one of these virtual workshops, so I'll also launch a survey at the end to gather some of your feedback in order to help us improve. And so it looks like there's a lot of you who have been waiting. So let's get started, and I'll quickly hand it over to Jess. Yeah. So lovely to meet you all. I see we have people from all over the world. Very, very excited and grateful that you've joined us here. So, yeah, let's get started. Welcome to Agent Harnesses and Deep Agents one zero one. Okay. Our speakers today are me, Jess, and Ishaan, and we're education engineers at Langchain. So if you have any questions, please feel free to go to the q and a section, and we'll try to answer your questions as quickly as we can. And today, we'll go over the basics of deep agents and build one together. There will also be a take home assignment, as Jezell mentioned, and you can work on that later to customize your own deep agent. So first, let's start with what is an agent. Well, one definition of an agent is a model calling tools in a loop until it completes a task and returns a result. You've probably used Claude or Tachibuty and seen it searching for tools while it tries to answer your question. Well, same concept here. You have your input, your question that goes into the model. The model then calls a tool, and the tool result goes back into the model. And this goes back and forth until you get your output and your answer. So that's the whole picture. An agent is just a model calling tools in a loop until it completes the task. And this tool part here is part of something called the harness. And to define what a harness is, let's look at it again in the context of an agent. So another definition of an agent, to further simplify, is just a model plus a harness. So the harness here is the scaffolding around a model. And to visualize that, let's go over this. The model actually cannot do much on its own. A large language model is technically just a word guessing machine, and the harness, which is what surrounds the model, includes things like tools, which I pointed out earlier, sub agents, the system prompt, and so much more. And it's all of this combined together that makes an agent. Now you've maybe seen the memes about just asking Claude or ChattyPT to just make no mistakes, but it's not enough to actually just tell the model that. A good harness is supposed to enforce the behavior that we want so that it actually makes no mistakes. So harness makes sure the model makes the right decisions by getting the model the right context at the right time for the given task. With just the large language model, you're missing a lot of all of these support structures. And the harness provides many things that improve your agent over time. Agents need to work in an environment where they can take action, connect to your data, manage growing context over long runs, parallelize tasks, and connect with a human in the loop, and so much more, all to improve your agent over time. And that brings us to the question of how does deep agents fit into all of this? Well, deep agents is Langchain's opinionated harness. And what this means is that our engineers have built up features with the best practices so that you can improve your agent more efficiently. It's basically a customizable agent harness purpose built for complex real world tasks, and it's a great harness for many reasons. The first of which is that it's provider agnostic or model neutral. And new models come out all the time. I feel like every day in the news, I'm hearing about new things coming out, and you want the ability to swap in and swap out whatever model you wish without having to rewrite all your code. And this way, you're not tied down to a particular vendor, especially if there's pricing changes or you just wanna use other newer better models. And that way, you don't have to rebuild your entire stack. Deep agents is also highly customizable. The deep agents harness has so many components, and the first of which is an execution environment. And this is made up of code interpreters, sandboxes, and file systems, and these take actions and connect to your data. Don't worry if this feels like a lot of information all at once, by the way. We'll go over things again in more detail. And then for context management, we have skills, memory, summarization, context offloading, and prompt caching, and these are all crucial for long running agents. Our harness also ships with delegation capabilities. So as workloads increase, work needs to be distributed and planning and sub agents help with that. We'll actually take a look at sub agents specifically in the demo later. Then finally, human in the loop is built in with middleware. So sensitive tasks like financial transactions or sending an email externally, these need human feedback and approval in real time. And we'll touch on human in the loop in in the workshop a little later, but maybe you've actually already heard of the human in the loop. This is just one way to customize your agent. So you start with your input, which then goes into the model. We've seen this before. But instead of a direct tool call, you see this person icon here? That represents the human in the loop checkpoint. Where normally you'd have a regular tool call, now you pause. So let's say the tool you're trying to call deletes files. This is something you'd wanna be very careful with. With human in the loop, at this checkpoint, you can approve, edit, respond, or reject it. That's an option. But let's say we approve here, then the tool call loads back with the approved response back to the model. And finally, you get your output. So that's the whole picture with human in the loop. Human in the loop is an example of middleware, which are hooks that allow you to customize behavior in the agent loop. So middleware is essentially a custom function that you insert into the loop, and it could go before an agent, before a model, or wrap the model call. All of these are potential middleware options. For human in the loop specifically, it wraps a tool call. So as you can see here, human in the loop gates the tool call. Again, this is just one example of middleware. And remember, we can insert middleware at any point in the agent loop. Alright. Back to the other parts of the deep agents harness. Let's take a look at sub agents. Again, you start with your input, which goes into the model, but I wanna talk about this. The model has something called a context window, and think of it as the capacity of the model. If you give it too much information, things like a lot of chat history, noise, or tool output, the model gradually declines in accuracy, recall, and reasoning quality. And that's why delegating to sub agents, sort of like mini assistants, is super useful. They have their own context windows and separate tools. So let's say your main agent is a newsletter agent and it's in charge of putting together an entire newsletter every single week. Let's make the sub agents here specialize in research. The one on the left, sub agent a, could have specific tools to scrape the web for news articles, and the sub agent on the right, sub agent b, could have specific tools to scrape through video information. They call their respective tools, get the response, and then they give just the final result back to the model. The model doesn't need to know the nitty gritty of which tools the sub agents called and how they got this information. It's not really relevant to the bigger picture here. And because sub agents are working on smaller specialized tasks, you can actually use a cheaper model to do these tasks, which saves a lot of money in the long run. You do not need GPT six Astra for your sub agents to do some basic web scraping. Anyways, now that the model only has the main information it needs, it can generate the final output with much less noise cluttering its context window. If you've seen the double worst product, then this is how I would picture it. You would not bother Miranda Priestly with menial details. As a sub agent, you only wanna get the model the important final information without the boring details. And since sub agents are highly customizable, you can build whatever suits your needs. Okay. Enough of that. As for how DeepAgents is production ready, there are so many challenges that come with deploying an agent to production, and that's what managed deep agents handles. I actually won't cover this in today's workshop, but just as a brief overview, managed deep agents deals with scaling and production. From durable execution and streaming to sandboxes, schedules, MCP connectors, and auth, these are all taken care of so that you can deploy in one CLI command. But let's focus back on deep agents, which is the core agent harness. To ensure agents work with real data durably, deep agents add virtual file system support. And to ensure agents can write and execute code safely, we provide sandboxes. And further than sandboxes, we also provide file system permissions and middleware hooks so that there are multiple safeguards. Human in the loop is just one of them, which is what we looked at earlier. And to ensure agents remember and access knowledge properly, we have memory, skills, and MCP. To complete long horizon work, we have built in context management techniques. And finally, to optimize for provider and model choice, DeepAgent ships harness profiles. So these are per model overrides to the system prompt, toolset, and middleware so that the same harness performs well, whether it's driving cloud, GPT, Gemini, or an open source model like NVIDIA's Nematron, whatever it is. Okay. Lots of talking, but let's get to the fun part. I'm going to demo building a journal deep agent with all the things that I just mentioned. Now Jezell did send out the collab, so feel free to go through that at your own pace. But, honestly, it'll be easier just to watch me and follow along for now. And and there will be a separate take home, which we will get to in a second. Let me okay. So here is our journal agent. Now what this agent does by the end of it, it will be able to log and read journal entries, tag their mood with sentiment analysis, remember conversations across turns, and pause for approval or rejection before acting, and delegate to specialist sub agents. So, yes, I'm going to make us get in touch with our feelings today. So I already ran this code, but this is just, to format it so that text is easier to read. And then we'll wanna start with connecting a model. These are just some things that you need to install, and here is where we set up our model. So I'm using Anthropic to demo here. However, again, LangChain is model agnostic, so feel free to use OpenAI or an open source model, anything you like. If you wanna use anything else, just swap it in here. It's really that easy. So you wanna go into secrets, this little key here, and then add a new secret. You wanna make sure that the name here, since I'm using anthropic, I'll have anthropic, these need to match. So if you wanna use something else, just make sure that all three of these match. And then in the value, you want to put in your actual API key. So I have mine here. Face it in. Great. And then remember, you have to give your notebook access to it. Perfect. So I can just run these. And I'm choosing to use SONNET five here, but, again, feel free to use whatever. You could use Fable five. You could use GPT six. It's totally up to you, but it's super easy to set up. And then let's get back to the harness, which is the whole point of this session. To reiterate, every Deep Agent starts the same way. You have a model wrapped in a harness that already knows how to read and write files and plan and call tools. These come automatically with the base Deep Agent's harness without you needing to do anything. So we've already bundled in all the tools that we think are absolutely necessary to start with, and the rest is customizable. So here is how you actually create your Deep Agent. Create Deep Agent. And this model equals model here is what makes it so easy to swap in whatever you want. I have a bunch of code written later, but none of that needs to change. If I want to change the model, all I have to do is swap what's up here again. So this message is our input into the model. Remember the graph earlier? This is what the model sees and it's basically our question. Now I'm asking it to start a journal markdown file and to log a new data entry with these notes, what I learned today, how I felt, and what's next, and then to read the file back to me. So this human message is exactly the same thing that I wrote in here. This is just printed more prettily so we can go over things in a nice way. So, again, asking it to start this file, and this AI message is basically what's happening behind the scenes with the model. So, oh, what I learned today, there was a caching bug hiding in the entry logic. All of this is stuff that I wrote up here, and it's written it here. So it's created this file by calling the right file tool with all the arguments that I specified. And then the tool message is basically just a plain, plain message that shows what's happening behind with the tools. Then because I asked it to read the file back to me, it specifically calls read file, and that's why you see these lines. Line 11 to 12. Line one to 12. I can't read. So this is exactly what happened. And remember, we did not add any tools here. This is exactly what comes with just the base deep agent's harness. Down here, this is the plain language summary that you normally get. If you've noticed, whenever you chat with Claude or ChattyPT, you normally only get this last part. You don't get to see what's happening in between with all the tool calls. But this is what the DeepAgents harness does. It gives you a little sneak peek into what else is going on. Okay. So that's when we didn't change anything. But let's say we do actually wanna switch things up. We can do that with the system prompt. Now the system prompt is basically a string that controls how the agent behaves on top of whatever other instructions and facts you give it, and this is loaded into the model every single time. So let's say I'm gonna use this example of a melodramatic Victorian child because I love being dramatic, and I think it's a little more fun visually to look at it. But what the system prompt does is it basically shapes how the agent behaves. Now you can do that with giving it a persona. You could make your agent Italian. You can make your agent French. But what you can also do is give it a specific voice. Let's say your company uses a specific voice or persona or branding, you can put that here. Furthermore, you can also set topic constraints. So there was an incident a few years ago where the Chipotle chatbot was being used to answer questions unrelated to Chipotle's products. People were asking it to reverse a linked list or do their physics homework, and it did. And that's something a topic constraint would fix. If I just put in here only answer questions related to my company's products, do not answer anything else, then it would help restrict the model to only do that and that way not waste tokens. So those are just a couple of examples of what you can use with the system prompt. But here, I've given it a fake journal entry about what I learned today, a caching bug, etcetera. And let's take a look. So the model first tried to look at what files there were, and because we haven't written this yet, it doesn't exist. Now it calls write file. And, oh, here we have the voice. What a dreadful and winding mystery unraveled. Wicked little caching bug, and so on and so forth. Oh my goodness. My poor heart was flooded with trembling relief upon its discovery. So as you can see, very visual representation of how it can change. And, yeah, our, oh, collapses dramatically onto the fainting couch. So this is just one example, but let me reset that so that we no longer have this dramatic voice with us. So since I put nothing here, there's no persona. I could put and that would also work. Let's keep it plain. Okay. Now I'm going to move on to tools, and this is something that you'll probably end up customizing the most because it's just so customizable. And before I get into that, let's talk about what it looks like and what a tool even means in the context of deep agents. So if you see this little at symbol, this is called our tool decorator. And if you put this before any function, it turns it into a function that it turns into a tool that the model can then call. And the name and docstring are how the tool how the model decides when to call this tool and when to use it. And then the type hints become its input schema, what arguments it expects. And then finally, the return value becomes what the model sees back. It's easier to see this with an with an example, so let's take a look at this word count tool. Again, we have our tool decorator here, and this is just a plain Python function. Here's the name, word count, and what does it do? It counts the words in a piece of text. And this is the function that does that. It quite literally just splits the text and then counts the words. So that's one example of a tool, and here's another. We have a a mood tag that tags a piece of text with a mood using real sentiment analysis. So now what this does is it'll give a score based on our journal entry, and I've just downloaded some other things so that we can do that. Okay. And in order to add a tool to your deep agent, remember, this is how we create our deep agent. Model plus model equals model. We saw that. We have the system prompt. We add tools in through this. Tools just takes a plain Python list. I could call this something else. I could call this bingus bongus bingus bongus same thing. But tools, this is how we add it in. And if I wanted to add more than just the mood tag, let's say I want to add word count, I could just put it in. Alright. Let's run that. And here's another fake journal entry I've put in. You know? I finally shipped the feature I've been stuck on for a week, etcetera, etcetera. Now let's take a look. Here's the journal entry, our input. And look, under tool calls, we specifically call it new tag. It's given us a score of neutral. I guess there was some relief and satisfaction, you know, finally shipped. Feels good to have it done. But also some mild anxiety. A little worried about whether the fix will hold up under real traffic, some forward looking resolve. So overall, we got this score, and that's what the Mood Tag tool did. Alright. Now let's talk about memory, specifically short term memory. So short term memory for any agent but with LangChain, including deep agents, is managed using a check pointer, and it's what lets an agent remember earlier turns in the same conversation, and it's tracked by something called a thread ID. So first, we'll want to import in memory saver. This is how we actually use the check pointer. And then this, this is where the magic happens. So thread ID, it works like any other ID. If we assign it one, anything associated with thread ID one is one conversation. If I were to change this to two or three or apple, whatever it is, that is no longer part of thread ID one. It would be like starting an entirely new conversation. So that's how if you wanna keep track of the same conversation, you have to keep the same thread ID. So let's see what that looks like. Again, we need to add our check pointer into our deep agent, and then we actually invoke this using this. So remember, we also have to add this configuration configuration line because it's the same as this. So I've given it a little a little message. My name is Jess. Today, I feel elated because my project was launched. Great. This is the model talking back to me. Thanks. Congrats. Congrats. But here, the follow-up message, what's my name? How do I feel? This is how we see the checkpoint or an action. So because we kept the same third ID, it remembered me. Your name is Jess, and you feel elated. However, let's say I wanted to change the threat ID. All I'd have to do is this. So let's run that again. Remember, this is not one anymore. They don't have a clue who I am. Who on earth? There you go. So that's how what you do and how memory works, short term at least. And then human in the loop, this relates to how human in the loop works actually. The human in the loop, as I mentioned earlier in the slides, is very important for if you want to gate specific things that need human approval. So again, financial transactions, sending an email externally, anything that you just want someone to double check with human eyes, this is where you use it. And it works with interrupt on. Now what this does is remember when in the diagram earlier, that human in the loop served as a checkpoint by pausing it before the tool call went through? Interrupt On just pauses the agent mid run so that the human can then approve, edit, reject, or respond to a specific tool call. And then you replay it or resume it with this. So I've created a fake tool here, this shared journal entry. It hypothetically shares a journal entry to an external platform. It doesn't actually just simulate it, but it works the exact same way with human in the loop for our purposes. So, again, in our tools list, we have shared journal entry. We have that here. And then this is how human in the loop works. You need this interrupt on when you have the shared journal entry tool Because if you don't, it's just not going to know when to pause or when to trigger that. And then the check pointer here is how we know where to resume. We want to resume from where we paused because if we just restart it every single time, it would be like setting us back to the beginning every time we called human in the loop. We have this thread ID, and this is, again, just a message about starting another journal entry. And, yeah, and we have to make sure, again, we keep the same thread. Otherwise, it's like restarting over. So let's wait for that. There you go. Pause for approval. Now if we want to approve and let it happen, all we have to do is make sure that we put approve here. There we go. We've read the file. I'm going to set up human in the loop approval today. This is what I said in my journal entry. And look at that. We called share journal entry, and it worked. Share it to Team Stand Up, that fictional platform. However, let's say I don't wanna let it. Rejected. We'll run this again because, remember, we need to get to the point where it pauses for the checkpoint, and then let's wait for it. Dang. Very slow, Okay. Before we share something, I want to flag something. Would you like to review or approve it first? Hold on. What's happened here? Memory saver. There we go. Pause for approval. I don't know what happened there. Anthropic, I'm coming for you. And then when we load it again with reject, user rejected the tool call for shared journal entry. So it was blocked. It did not go through. And what this means is that everything up to that human in the loop checkpoint worked. It's just that specific tool call got gated. So everything before that worked, but it did not share this journal entry to the external platform. So that's how human in the loop works, and there's many, many ways you can customize this. Okay. Now for sub agents, these basically hand work to specialists through a built in task tool. They work very similarly to tools functions because you'll have a name and a description similarly and that's how the model knows when to call for it, but it has its own system prompt and its own context window. So I've created two here, one called life planner, which will turn a repeated complaint into a weekly plan, and devil's advocate, which then surfaces the practical downsides of a decision. So life planner, you know, use this specific sub agent when the user says they feel overwhelmed or burnt out or explicitly ask for help getting organized, and it's a list of what it does. And then in the system prompt, specifically, what role it has, we tell it you are a life planner. Read the journal in full and check whether there's any complaint or chore showing up more than once, etcetera. And then for the devil's advocate sub agent, use this specific sub agent when the user is weighing or asked a decision about a certain thing. Again, with the system prompt, you are a practical, slightly skeptical friend. You can customize this however you want once again. And then I've added this, which just essentially so with every model, there usually are general purpose sub agents that can kind of do a bit of everything, and sometimes the model will default to using those. But since we have our custom built sub agents, which are very specific and good for our purposes, putting this just basically make sure that it calls our sub agents instead of the general purpose sub agent. And just like tools and everything else, it's just one line that you add. We have our life planner and our devil's advocate over here. And here are just some fake entries I've come up with. I'm exhausted today. So much to do at work. I skipped the gym again. I didn't do laundry. You know, the usual. So these are just some fake journal entries, and now we're gonna take a look at what our life planner agent thinks about our journal entries. I'm so overwhelmed with everything I need to do. Can you help me get organized? And let's take a look. And then this other second question is just, should I get a cat? The answer is always yes, but let's see what the devil's advocate sub agent says. And let's let it load. Great. So once again, our input, our model searching for the files, and then writing it because it didn't exist before we wrote it. And then here, under tool calls, we call it our sub agent, life planner. Woo hoo. So laundry, most repeated chore. Yeah. It's flagging all the things that I seem to have issues with. Concrete fix. Stop doing it myself. I would love that. And giving me a day by day plan on what to do. Yeah. And then this is the plain language summary that you always get with the model. As for the cat, let's see. Same pattern. This is our input. And then writing our journal entries, our weekly plan. There we go. Should I get a cat? Should I get a cat? It called the devil's advocate sub agent. It knew specifically to do that. Oh, and it's telling us about the unglamorous side of the cat decision. I don't wanna hear that. But, yeah, they're right. It's a lot of responsibility. Travel gets more complicated, long term commitment. Nothing here says don't do it. It's just giving me both sides of the story. Yeah. So that's just another example of how the sub agent works. We don't need our journal agent to I'm not asking if I need a cat every other day. You know? These are what the sub agents are for. It's for specialized, like, one off instances or not necessarily even one off, just when they need to focus on such a specific task that the main agent doesn't need to be bothered with these details. Again, Miranda Priestley. And to wrap up, we built a file system backed agent with a way to swap personas, a custom tool with real sentiment analysis, short term memory across turns. We looked at human in the loop approval, two sub agents, and, yeah, we did all of this in less than an hour. So if you've been following along, great. But feel free to go over the recording again if you need to slow down and take a look at everything I've said. We also have a deep agents course on all of this. But before we get into that, let's take a quick look at our take home assignment, which is here. So Jezell will send a link in the chat. So if you don't see that, she will send that. But, essentially, what you'll wanna do is make a copy of this Google Colab. Actually, let me get back to the slides real quick so that you can yes. If for some reason you cannot see the link, feel free to copy this QR code. But this is essentially an opportunity for you to play around with customizing your own debatement. It's going to be relatively similar to what you saw me just go through, but not a journal agent so you can customize it to do whatever you want. I've actually added some fun tool options you can play around with. So if you wanna do stock research or if you wanna do a Pokemon API, these are all open to you. The sky's your limit, genuinely. So you have many, many options. And you can scan this QR code, to find that or one second. Let me see. Oh, I am getting request to edit. Okay. For everyone requesting to edit, you should be making a copy of the file instead of editing it directly. If that is not available to you, please go to q and a, and then Ishaan will help out with that. Okay. But let's take a look. Oh my goodness. My notifications are exploding. Let's take a look at the template. So this is, again, make a copy of this collab so that you can actually work in it. But this is, again, blank version. But down here in custom tool, you can see I have a rolling dice tool, password generator, random joke, currency conversion, etcetera, Pokemon lookup, which could be kind of fun. But anyways, with all of this, you can go in and make the edits yourself. Play around with it. No need to rush. But I highly, highly recommend because this was quite a more surface deep dive, you should head over to LangChain Academy. And this is taught by someone really cool. I think she's great. But, essentially, this is a free self paced course on our academy that goes through so much. There are different types of sub agents, synchronous, asynchronous. There's so much to go through, and you can go through this entirely at your own pace. We have videos. We have homework assignments. We have projects to test your skills and so much more. And, again, it's entirely self paced, so you can work through this, as quickly or as slowly as you want. And finally, I wanna shout out Ishaan's new manage deep agent session on October 8. And this workshop is a live instructor format similar to what we have here today, and it goes through manage deep agents, which I went through earlier in those couple of slides. But this is basically this is built on deep agents and is another way to deal with deploying agents in production. Yeah. So thank you so much for joining us today, and I'll hand it back to Jezell. I'm gonna jump in and just mention a couple of quick things. So, first of all, there have been a lot of questions about, whether or not this will be recorded and it will be shared. Yes. It will be. This session has been recorded, and the slide deck will also be shared afterwards in an email. And then lastly, just wanna address some of the common questions we've been seeing in the chat. So a lot of people have been asking, like, what the difference is between an ordinary agent and a deep agent. And the main thing about a deep agent is that the harness is provided for you. Like, Langchain, we've built deep agents for you. We have configured the deep agent's harness. This is custom built with, best practices, and it's open source. So what this means is when you create a Deep Agent, everything that comes with the harness, the skills, the tools, memories, and how the agent calls all of these things, that's all taken care of for you. You don't have to build build that. But if you wanted to, since DeepAgents is open source, you can change it however you want. So that's that's kind of the key distinction right there. Some other main questions. Yes. A lot of people asking about it'll if it'll be recorded. For the take home assignment that we were just mentioning at the end that Jess's Screenshare was showing you, please make a copy of it. The way you do this is you go to file and then save a copy in Drive or save the copy somewhere else. There's a big banner at the top that explains you how to do this. Be sure to make a copy of it. There's some people mentioning that the, QR code for at the end for the academy and the MDA workshop, we're a little bit faulty. We will be sure to send out the correct links in that follow-up email as well. Okay. I think that's pretty much all the questions that I wanted to hit on at the end here. I'll hand it over to Jezell. Alright. Thank you all. Appreciate it. And if you have questions I think we have some outstanding questions here. So, we'll hang out a little bit to try to answer them all. But if you have additional questions, like, feel free to also reach out to us. And then it looks like the QR code for Ishaan session was 404. So I'm actually going to drop that in the link, or in the chat with the link right now. So you can take a look and sign up for that one. But, basically, Ishaan will be covering manage deep agents. And then if you also want to learn a little bit more about what Jess was talking about today, feel free to sign up for the full course on LangChain Academy. It's completely free. It's self paced, so you can kind of just stop and start whenever you want. And, yeah, we'll stay and try to answer the rest of the questions. But thank you so much for joining us for our very first, virtual workshop. I'm actually going to launch the survey now so that I can get some feedback from you guys on how we can improve and maybe come up with more interesting course content in the future.