Implementing deepagents: a technical walkthrough

LangChain · Intermediate ·🤖 AI Agents & Automation ·11mo ago

Key Takeaways

The video demonstrates the implementation of deepagents, a Python package for building Deep Agents, which are agents that can plan over longer time horizons and go deep into different parts of a complex problem. It showcases the under-the-hood workings of Deep Agents, including the planning tool, virtual file system, and detailed prompts.

Full Transcript

Deep agents are agents that can plan over longer time horizons and go deep into different parts of a complex problem. In the last video, which I'll link to in the description, we chatted about what they are and some of the characteristics that make them up, including a planning tool, access to a file system, using sub agents, and a detailed system prompt. In this video, I want to walk through some of the code for an implementation of deep agents that we have in this GitHub repo. You can of course pip install it and use it off the shelf with pip install deep agents. And I'll show in future videos how to just use this offtheshelf, but for now I want to walk through the underlying code and show how we implemented these various components on top of langraph. So I've cloned the deep agents repo here and in order to start walking through it I'm going to look in graph.py. So deep agents is built on top of langraph. If you're not familiar with langraph it's our agent runtime and I'll link to it in the description below as well. But as part of langraph you create agents as graphs. And so if I look in graph.py I I'll see that I import a few things. And the main thing that I import from lingraphph is this create react agent. So what exactly is that? If you remember from last video when we talked about the core algorithm that deep agents use under the hood, it's nothing more than this simple agent loop where you make an LLM call and that either decides to stop or take an action. And if you take an action, you then go take that action, you get some feedback and you pass it back to the LLM. And so this loop is often times called a react agent. And we have a pre-built wrapper in Langghraph that implements exactly this. And so that wrapper is what I'm importing. And I'll see down below that I will just actually pass different arguments to this agent and then use the create react agent to do this loop. So that's going to be the the the the core algorithm of this agent. The other important part to know before we dive into some of the code is the state of the agent. So the way that agents work in langraph is that you define a state for them to use. And this is things that the agent can track and add to over time. And so I see here that I have this deep agent state. And so this is a state object that I created for deep agents. And you can customize that and we'll show that below. But it should always inherit from this deep agent state. So if we go to the definition, we'll see a few things. one it inherits from agent state and so this is defined in langraph and this is built for the react agent thing that I showed above so let's go down another hole and let's look what's in this agent state if we look at the agent state here we can see that it has three attributes the first and most important one is a list of messages and so this is how the agent does things and has conversations over time and so these messages can be human messages that come from the user They can be AI messages when the model makes a call or they can be tool messages that come from the result of executing tools. And so there's this messages list that will get usually appended to but sometimes modified over time. The other two attributes are is last step and remaining steps. And so these are used to track the iteration of the agent. So one of the things that we do in this create react agent which runs this loop is we do track how many steps are being taken. And so then if it passes thumb threshold that the user defines, we'll we'll we'll stop and return. Great. So deep agent state inherits from that agent state. It adds in two more things. One is a to-dos attribute. And so this is a list of to-do objects. To-do objects you can see we define up from up here. To-dos have a content which is a string and a status which is pending, in progress or completed. And so this will help with the planning tool. So, one of the key components of deep agents is this planning tool. And to-dos will track the status of a to-do list, which will which will be how the agent plans. The last thing we have in deep agent state is files. And so, we can see that we represent the the file system as just a dictionary of strings mapping to strings. So, this is a a virtual file system. So, we're not actually going to be using a real file system. We're rather going to use this this dictionary which we're storing in the in the agent state. We're using this as a virtual file system rather than a real file system because it's a lot easier to scale this. I don't actually have to have separate directories with separate files. I can just track them with this mock with this virtual file system. You'll notice here that I have a file reducer. So this is used to reduce elements that come in and and this basically says hey when I get an update from uh from one node of the graph how do I apply it to the value that's already in the files and so we can see here that what we do is we actually combine those two dictionaries now now why why did I do this I did this because sometimes in lingraph you can have things that work in parallel So you can have two agents running at the same time. Now if they both write to new files when you try to combine them, there's going to be some issues if you just take one or the other because if you just take A, then you're losing any files that B created and if you just take B, you're losing any files that A created. And so this will actually just merge them and add any new files together. Now if you if you think carefully, there are still some edge cases that this doesn't cover. So what if A and B both edit file C? So right now we don't have a way to resolve that conflict. And we'll probably add something to handle that in future iterations of this deep agent architecture. But right now we're just going to do this pretty simple file reducer. If we go back here, the next thing we see is this base prompt. And so this is actually kind of a simple prompt. If you remember, I said we wanted a pretty detailed and descriptive system prompt. So, so what's going on here? Why is this a simple base prompt? The TLDDR is that a lot of the detailed prompts actually come in the form of the tool descriptions. And so, we'll see that later on when we implement the file system and the planning and the sub agent tools. Okay, let's look at create deep agent. What does it take in? So, it takes in a few things. And this is how you use create deep agent. And so we'll cover this in a future video in a little bit more detail, but the core components are that users can specify custom tools. And so this is how you give the deep agent a search tool or a calculator or anything like that. Custom instructions. And so this is how you customize it for the task that the deep agent is supposed to be doing. A custom model. So this is not required. And so we'll see that we use a model by default under the hood. Uh but you can pass in a custom model. And we've already had some people open up PR showing how to use it with OLAM in other local models. So that's really cool. Sub aent. So this is where you define the sub aents that the main agent has access to. We do define one general purpose sub aent by default. And I'll show that later on. And then state schema. And so this is what I mentioned earlier. This has to inherit from the deep agent state. But you can customize it to add in more things to track if if you want. So now let's look how it's created and we can see at the end we we call create react agent and we pass into create react agent the model the prompt the tools and then the custom state schema and so all that we're doing in these 10 or so lines here are defining those four attributes. So let's maybe look at the model first. So model if model is none we call get default model. What does that do? So we can see here that by default we return chat anthropic and we're using claude sonnet for and we're setting max tokens equal to a pretty high number. And the reason we're doing this is oftent times I ask deep agent for things that require a a lot of writing. So like writing a long research report. And so I really want to make sure that I can give it the maximum output tokens that it wants. Okay. So model is easy. Let's now look at prompt. So prompt we just combine the instructions that the user passes in with the base prompt defined above. And so again this base prompt isn't that complicated. We'll actually see a lot of the complexity come in the form of tool definitions. But this is the this is the prompt that we provide. State schema again pretty simple. We either use the state schema that's passed in or the deep agent state. So all that's left is the tools. And these are the main parts of deep agent. So we're going to spend a lot more time focusing on this. So we'll see that by default we have five built-in tools. Write to-dos which is our planning tool and then four tools for interacting with the file system. Write file, read file, ls which lists files and then edit file. Great. Let's take a look at write to-dos first. Okay. So we can see a few things here. First we're passing in a description, a custom description to this right to use tool. Let's go read this and then we'll see what exactly the tool does. So we can see here that this is a pretty long and detailed tool description. This is 140 180 180 lines in total. And so we have a bunch of information about when to use this tool, when not to use this tool, examples of when to use this tool, uh examples of when not to use the tool, and then and then generally how to think about task states and management. So we use these states to track the progress. And so that's pending and progress completed. You and then we we tell the agent to basically update task status in real time as you work. And and there's a bunch of other information here that I encourage you to go and read. And this is pretty detailed information about how to use this planning tool. If we go back to what the planning tool does, what it basically does is it updates the state in two ways. First, it sets the to-dos thing which is an attribute we have on on the deep state. We set the we set the to-dos parameter to be equal to whatever is passed in. So the LLM will generate this payload. And importantly, the whole to-do list is set equal to that payload. So it's not actually doing any smart updates on the to-do list. just overwriting it every time. And this is kind of simple, but it doesn't actually matter. It it helps the agent kind of like remember the the full to-do list and and it's pretty easy. And so that's why we're doing it. And a lot of this is based off of claude code, by the way, and how that works. And so this is taken from there. And then we also update the message list. So we return something that says we updated the to-do list to be blah blah blah. And this will get inserted in the agents context window. So it will see this and it will acknowledge that the to-do list is updated. So this is the right to-do tools. We also have the tools for interacting with the file system. So ls this is list tools. This is pretty simple. All it does is basically it looks in the state for this files key and then it returns a list of the keys. So this will return a list of the files names. Pretty straightforward. Read file. Okay. So read file. We can see that we actually have a tool description that's pretty detailed. So let's go take a look at that. So this uh reads a file from the local file system. There's some interesting points here that I want to call out. So, uh, by default, it reads up to 2,000 lines starting from the beginning of the file. You can specify line offsets and limits, although you don't have to. And then that that'll kind of like change the window of lines that's read. Any lines longer than 2,00 characters will be truncated. We specify the format it's returned. You can call this multiple times. And then something about empty file. And so this is uh uh this is also taken from cloud code. And if we go to the tool definition of it, we can basically see that it's doing exactly what it said in in in the uh dock string that we use. So we get this mock file system which again is just this files parameter in the state. We handle some empty files. Then we split it into lines. We apply the offset. We handle some edge cases. And then we basically go through and format this in the format we said it would. And then we return this. So this is this is our read file tool. And it's more complicated than just returning the value of the key. That's that's kind of like the the main thing I want to impart. Write file. Okay. So write file also pretty simple. We can see that there's not really a complicated doc string. What we do is we just get the the mock file system. We then set the whole file uh path to be equal to the content that we pass in. And then we return uh the updated files here. And so this will get merged into the state. And then we also return a tool message that says that we updated the file with the file path name. And then the last tool here is this edit file tool. So let's go look at this description. And so this performs exact string replacements in the files. So this is kind of interesting. Um, and so this is taken from there's an edit file tool that cla models are actually train. So if we go here, we can see that this is a a built-in tool that cla models are trained on. And so again, this is a built-in tool payload. So it doesn't actually do anything. But if we go to stir replace, this is this is what we're basically using as the edit tool. There's uh the path to modify and then the old string and then the new string. So it actually uh replaces the exact kind of like text. And this is kind of interesting. It's not it's not really applying a patch to any particular lines. It's using this stir replace thing. Um and this might seem a little bit counterintuitive. I I honestly expected something more like edit edit uh kind of like um you know lines 1 through 10 to be this. Uh but for whatever reason anthropic kind of like train their models on on this function and because the models are trained on this, we're going to use that because the models are going to be better at that. So if we go back to the the definition of uh the edit file tool, we can see again it's pretty simple. We we get the file system. We check whether it exists. We get the current file content. We check whether the the string even exists. And if it doesn't, we we throw an error. And then basically there is this parameter called replace all which uh if you want to replace multiple instances of this of the string, you have to set it to be equal to true. So basically we check that um if this is false then we check whether the content is unique. If it's not unique then we then we throw an error. Um and uh then we do the replacement. Uh so basically we if if replace all is true we we go through and we replace stuff and then uh we return the updated file system which has the new content. So this is the new content with the the modified uh uh old string replaced by the new string. And then we send back this tool message that says that we updated the file path. So these are built-in tools for the planning tool and for the file system tool. If we go back to the graph, there's still one tool that we have to create the task tool and this is the sub aent tool. So let's go take a look at this one. And this is the last tool and the last real part of the codebase that we're going to explore. Okay, so create task tool. What does it take in? It takes in a list of tools, instructions. So, and and so these are uh these are all the tools that we had before. Instructions, sub aents, this is the main new thing. So, these are going to be the custom sub aents that we create and then the model and the state schema. And these are the same as before. So, what is a sub aent? A sub aent is nothing more than a dictionary that describes the the name of the sub aent. And this is going to be how the main agent calls that sub aent, a description of the sub aent. And so this is going to be how the main agent knows what that sub agent does, the prompt of the sub aent. And so this is now going to be passed to the model in the sub agent itself. And then a list of tools that the sub aent can use. And we we can see that this is uh you specify the tools by name. And this is not required. So this could be missing. And if this is missing, we're just going to use all tools. So what exactly does this tool does this create task tool do? It's basically going to return this tool. And how do we create that tool? The first thing we're going to do is create a mapping of agents from their name to an actual agent. So we can see here that we have one agent in there by default. It's general purpose. And so this is just going to be a general purpose sub agent. And what it's going to be, we're going to create react agent. So this is the same algorithm that I mentioned before. It's the same tool calling loop. And we're going to pass in the model, the instructions, and the tools. And so this is just a general purpose sub aent that it can use. But there are also custom sub aents. So the first thing we're going to do is create a mapping of tool name to the actual tool. And so this will be used to uh just filter down the tools that the sub aents have access to. We're then going to loop through the sub aents that we pass in or rather the definition of the sub aents that we pass in because remember at this point in time these are just dictionaries. So we're going to loop through these. Um, we're going to check whether the tools parameter is specified as part of this sub agent. And if it is, then we're going to filter down the tools to only be the tools that are specified. And if it's not, we're going to use all tools. And then we're going to add an element to this dictionary. We're going to add an element uh where the key is the agent name. And then we're going to create React agent. So create another tool calling loop. That's going to be the sub agent using the prompt of the agent and the tools which we filtered down above. And then what we're going to do is we're now going to create the description of the tool. So we're going to get a nice little string that's that specifies the other sub aents. And so this is just going to be a bulleted list of their name and their description. Again, taken from all these dictionaries that that specify the sub aents. We are going to pass this in as a description. And there's and there's also two other hard-coded uh tool description things that we're going to be passing in. So let's go to the definition. So we've got this prefix which basically just uh is a quick prefix describing that this tool launches a new agent and then it lists the agent types here including general purpose and then we have the uh the suffix and the suffix is longer and so this suffix describes all how to use the the agent tool, when to use it, when not to use it, usage notes, so launch multiple agents concurrently whenever possible. When the agent is done, it will return a single message back to you. So we'll we'll go see this when we look at the implementation of the tool. Um each email's invocation is stateless. So again we'll see this when we look at the invocation of the tool. You should trust the agent's output. Clearly tell it uh whether you expect it to create content, perform analysis um and then some example usage as well. So let's go back to the sub aent tool that we were creating. So we can see that when the maid agent calls this tool, it's going to pass in the sub aent type. And again, these are things like general purpose or the agent's name. And then it's going to pass in a description of the task. And so this is going to be what we want the sub agent to do. So then inside the tool, we look up the sub agent that we want to use. We then take the state. And so this is the state of the overall agent. And so remember what's in the state of the overall agent? We have the to-do list, the files, and then the messages that come from the main agent state that it inherits from. So, what we're going to do is we're actually going to override the messages to just be a list of one element and it's just this user message, which has as as the content the thing that we pass into the task. So, what we're going to do is we're going to pass this to the sub aent. And so, what does the sub aent sees? So, it still sees all the files that are in the overall main agent state because those haven't been modified, but the only messages that it sees is this one user message that describes what the sub aent task to do is. So, we're we're wiping out everything that the main agent did before. And the reason we want to do this is we want this sub agent to be really focused just on that one thing. So then we're going to uh run this sub agent. We're going to get back a result. And so then what are we returning? We're returning two things. So first we're going to return as files the files that the sub aent returns. So if the sub aent adds a file, it's going to be in this result object. And then we're going to return that. And remember, we have we have logic in the reducer of of this files parameter that will combine this with any other files that are created. if it's if it's run in parallel. We're also going to return a message. We're going to return a tool message and we're going to return the last message and and just the content from the last message. So what what the main agent will see it will see that it called this sub aent tool and then it will get back something that has this content but this content is just the last message that the sub aent did. So any other work that the sub aent did that's not going to be passed to the main agent. And so this is really important and if you notice um in in the description of the tool we say that as well. So if we go to here uh we say um yeah when the agent is done it will return a single message back to you. The result returned by the agent is not visible to the user. So there's more things there. So uh this is really important. The the sub aent any of the work it does only the final message is returned. So if the sub agent's doing a bunch of work, you want to prompt the sub agent to return all the information as as its final message. So that's the final tool that we create. We then create this list of all the tools. So the built-in tools, the the uh the list of tools that the user passes in, and then the sub aent tool. And we pass all of this to create React agent. And that's how we get our deep agent. So that's a walkthrough of how we created a deep agent on top of langraph. If you just want to use this, there's a code snippet here. So you can pip install this with pip install deep agents. And then we can see here that in this usage snippet, we create our custom tool. And so this is the search tool. We don't need to like recreate these file tools or or this to-do list tool or the sub aent tool. Those are already built in. But we create this this search tool. We create our custom instructions. And so these will these are the instructions that will tell it how to how to be a researcher. And then we create the deep agent. And so you can see here that we just pass in the list of custom tools. We pass in the custom instructions. And then we can just invoke this like we would any other any other langraph graph. So this is a real kind of like simple snippet. In a future video, I'll walk through a more complicated example and how we create a full deep researcher on top of this deep agents package. But that's a future video. Thanks for watching.

Original Description

We recently released `deepagents`, a Python package making it easier to build "Deep Agents". This comes with built in sub agent support, a planning tool, a virtual file system, and detailed prompts. In this video, we will walk through what exactly is the under the hood of Deep Agents! Previous video on what deep agents are: https://www.youtube.com/watch?v=433SmtTc0TA `deepagents` GitHub repo: https://github.com/hwchase17/deepagents Learn how to build Deep Agents on LangChain Academy: https://academy.langchain.com/courses/deep-agents-with-langgraph/?utm_medium=social&utm_source=youtube&utm_campaign=q4-2025_youtube-academy-links_aw Observe, evaluate, and deploy agents with LangSmith: https://smith.langchain.com/?utm_medium=social&utm_source=youtube&utm_campaign=q4-2025_youtube-links_aw
Watch on YouTube ↗ (saves to browser)
Sign in to unlock AI tutor explanation · ⚡30

Playlist

Uploads from LangChain · LangChain · 0 of 60

← Previous Next →
1 Chat With Your Documents Using LangChain + JavaScript
Chat With Your Documents Using LangChain + JavaScript
LangChain
2 LangChain SQL Webinar
LangChain SQL Webinar
LangChain
3 LangChain "OpenAI functions" Webinar
LangChain "OpenAI functions" Webinar
LangChain
4 LangSmith Launch
LangSmith Launch
LangChain
5 LangChain x Pinecone: Supercharging Llama-2 with RAG
LangChain x Pinecone: Supercharging Llama-2 with RAG
LangChain
6 LangChain Expression Language
LangChain Expression Language
LangChain
7 Building LLM applications with LangChain with Lance
Building LLM applications with LangChain with Lance
LangChain
8 Benchmarking Question/Answering Over CSV Data
Benchmarking Question/Answering Over CSV Data
LangChain
9 LangChain "RAG Evaluation" Webinar
LangChain "RAG Evaluation" Webinar
LangChain
10 Fine-tuning in Your Voice Webinar
Fine-tuning in Your Voice Webinar
LangChain
11 Tabular Data Retrieval
Tabular Data Retrieval
LangChain
12 Building an LLM Application with Audio by AssemblyAI
Building an LLM Application with Audio by AssemblyAI
LangChain
13 Superagent Deepdive Webinar
Superagent Deepdive Webinar
LangChain
14 Lessons from Deploying LLMs with LangSmith
Lessons from Deploying LLMs with LangSmith
LangChain
15 Shortwave Assistant Deepdive Webinar
Shortwave Assistant Deepdive Webinar
LangChain
16 Cognitive Architectures for Language Agents
Cognitive Architectures for Language Agents
LangChain
17 Effectively Building with LLMs in the Browser with Jacob
Effectively Building with LLMs in the Browser with Jacob
LangChain
18 Data Privacy for LLMs
Data Privacy for LLMs
LangChain
19 "Theory of Mind" Webinar with Plastic Labs
"Theory of Mind" Webinar with Plastic Labs
LangChain
20 LangChain Templates
LangChain Templates
LangChain
21 Using Natural Language to Query Postgres with Jacob
Using Natural Language to Query Postgres with Jacob
LangChain
22 Building a Research Assistant from Scratch
Building a Research Assistant from Scratch
LangChain
23 Benchmarking RAG over LangChain Docs
Benchmarking RAG over LangChain Docs
LangChain
24 Skeleton-of-Thought: Building a New Template from Scratch
Skeleton-of-Thought: Building a New Template from Scratch
LangChain
25 Benchmarking Methods for Semi-Structured RAG
Benchmarking Methods for Semi-Structured RAG
LangChain
26 LangSmith Highlights: Getting Started
LangSmith Highlights: Getting Started
LangChain
27 LangSmith Highlights: Debugging
LangSmith Highlights: Debugging
LangChain
28 LangSmith Highlights: Datasets
LangSmith Highlights: Datasets
LangChain
29 LangSmith Highlights: Evaluation
LangSmith Highlights: Evaluation
LangChain
30 LangSmith Highlights: Human Annotation
LangSmith Highlights: Human Annotation
LangChain
31 LangSmith Highlights: Monitoring
LangSmith Highlights: Monitoring
LangChain
32 LangSmith Highlights: Hub
LangSmith Highlights: Hub
LangChain
33 SQL Research Assistant
SQL Research Assistant
LangChain
34 Getting Started with Multi-Modal LLMs
Getting Started with Multi-Modal LLMs
LangChain
35 Build a Full Stack RAG App With TypeScript
Build a Full Stack RAG App With TypeScript
LangChain
36 Auto-Prompt Builder (with Hosted LangServe)
Auto-Prompt Builder (with Hosted LangServe)
LangChain
37 LangChain v0.1.0 Launch: Introduction
LangChain v0.1.0 Launch: Introduction
LangChain
38 LangChain v0.1.0 Launch: Observability
LangChain v0.1.0 Launch: Observability
LangChain
39 LangChain v0.1.0 Launch: Integrations
LangChain v0.1.0 Launch: Integrations
LangChain
40 LangChain v0.1.0 Launch: Composability
LangChain v0.1.0 Launch: Composability
LangChain
41 LangChain v0.1.0 Launch: Streaming
LangChain v0.1.0 Launch: Streaming
LangChain
42 LangChain v0.1.0 Launch: Output Parsing
LangChain v0.1.0 Launch: Output Parsing
LangChain
43 LangChain v0.1.0 Launch: Retrieval
LangChain v0.1.0 Launch: Retrieval
LangChain
44 LangChain v0.1.0 Launch: Agents
LangChain v0.1.0 Launch: Agents
LangChain
45 Build and Deploy a RAG app with Pinecone Serverless
Build and Deploy a RAG app with Pinecone Serverless
LangChain
46 Hosted LangServe + LangChain Templates
Hosted LangServe + LangChain Templates
LangChain
47 LangGraph: Intro
LangGraph: Intro
LangChain
48 LangGraph: Agent Executor
LangGraph: Agent Executor
LangChain
49 LangGraph: Chat Agent Executor
LangGraph: Chat Agent Executor
LangChain
50 LangGraph: Human-in-the-Loop
LangGraph: Human-in-the-Loop
LangChain
51 LangGraph: Dynamically Returning a Tool Output Directly
LangGraph: Dynamically Returning a Tool Output Directly
LangChain
52 LangGraph: Respond in a Specific Format
LangGraph: Respond in a Specific Format
LangChain
53 LangGraph: Managing Agent Steps
LangGraph: Managing Agent Steps
LangChain
54 LangGraph: Force-Calling a Tool
LangGraph: Force-Calling a Tool
LangChain
55 LangGraph: Multi-Agent Workflows
LangGraph: Multi-Agent Workflows
LangChain
56 Streaming Events: Introducing a new `stream_events` method
Streaming Events: Introducing a new `stream_events` method
LangChain
57 Building a web RAG chatbot: using LangChain, Exa (prev. Metaphor), LangSmith, and Hosted Langserve
Building a web RAG chatbot: using LangChain, Exa (prev. Metaphor), LangSmith, and Hosted Langserve
LangChain
58 OpenGPTs
OpenGPTs
LangChain
59 Open Source RAG with Nomic's New Embedding Model (and ChromaDB and Ollama)
Open Source RAG with Nomic's New Embedding Model (and ChromaDB and Ollama)
LangChain
60 LangGraph: Persistence
LangGraph: Persistence
LangChain

This video provides a technical walkthrough of implementing Deep Agents, a Python package for building agents that can plan over longer time horizons. It covers the planning tool, virtual file system, and detailed prompts, and demonstrates how to use these components to build autonomous workflows and multi-agent systems.

Key Takeaways
  1. Import necessary modules from Langraph
  2. Create a deep agent state object
  3. Define a planning tool and virtual file system
  4. Implement a tool calling loop
  5. Override messages in the sub agent
  6. Run the sub agent and return files and a tool message
  7. Combine files from parallel runs using reducer logic
  8. Pass only the last message from the sub agent to the main agent
💡 Deep Agents can be used to build autonomous workflows and multi-agent systems by leveraging the planning tool, virtual file system, and detailed prompts.

Related Reads

Up next
Agentic AI System Design- Complete Roadmap
Aishwarya Srinivasan
Watch →