Loading video player...
We rewrote the Langchain deep agents
package on top of the upcoming Langchain
v1 alpha release. In this video, I'm
going to take you through a deep dive on
the changes that we made and how this
updated version of deep agents is even
more extensible.
Now, before I get into the code itself,
let's do a quick recap on what deep
agents are. I like to think of deep
agents as simple tool calling loops with
a few specific bakedin tools and
behaviors out of the box. Specifically,
these are a planning tool with a to-do
list, a file system to offload context
and to later read from, the ability to
spawn sub aents for isolated tasks, and
a very detailed system prompt.
These tools have been shown to be very
helpful in products like Manis and Cloud
Code. And our goal with this deep agents
package is to make it really easy for
developers like you to build powerful
agents. Let's dive into the code. Cool.
Let's take a look at how we can use deep
agents. We have in our repo a create
deep agent function. This is the
pre-built function that you'll use to
create deep agents. Here we can see a
few of the parameters that you might
want to pass in. Of course, you pass in
a few tools for your agent. You can also
pass in custom instructions and you can
also pass in these sub aents that your
deep agent can then call and hand off
work to. Let's go ahead and take a
closer look at how our deep agents are
created.
The function that I really want to focus
on here is our agent builder.
Let's walk through in detail how this
agent builder function works. The first
parameter that we really want to think
about is the model. By default, we're
going to use sonnet 4, but you can pass
in any model here that you want to use.
This iteration of deep agents is built
on langchain v1. And langain v1
introduces a new central concept to
agent building called middleware. We
just released a nice long blog and video
that goes deep into how middleware works
and I'd highly recommend checking that
out if you want to get the full picture
of what you can do with middleware.
As a quick overview, middleware has the
ability to modify a simple React agent
and we'll see how in a second. The first
important thing to note is that
middleware is a stackable abstraction.
By that I mean that you can define as
many middleware as you want and apply
these to create agent which is exactly
what we're doing here.
Like I mentioned before, there are a few
different pillars to what makes an agent
a deep agent. The first is that the
agent has the ability to create and
follow a plan. The second is that the
agent has access to a file system. And
the third is the ability to spawn sub
aents for siloed isolated tasks. What
we've done here is we've written a
custom middleware for each of these
three pieces of functionality. Let's
walk through each of these in detail to
see how it works.
Clicking into our planning middleware,
we can see that it's pretty short, but
it does a lot of things. The first thing
that it does is it extends the state
schema for our agent. And this is a
really important thing to remember.
Middleware is used now to extend the
state schema for agents. And looking at
the planning state, we can see that just
like before, it adds this to-do list.
In addition to extending the state
schema, middleware can also extend the
number of tools and which tools your
React agent can use. In this case, for
planning, we only need a single tool,
the ability to write to that to-do list,
or more specifically to write to that
to-do key that we just added to our
state schema. And so our write to-dos
tool does exactly this. It allows us to
update our state to-dos with the to-dos
that the model creates.
The last thing that we do here is pretty
important as well. We override this
modify model request function and we
append to the end of the system prompt a
custom prompt that we've written with
instructions on how the agent should use
the write to-dos tool. This is crucial.
Just extending the schema and just
giving the model a tool without any
instructions isn't as effective. Here we
have the system prompt that really dives
into how you can use the right to-dos
tool. And this is provided to the agent
as part of this middleware.
Now let's take a look at our file system
middleware. Just like above, the file
system middleware inherits from agent
middleware and that again allows it to
extend our state schema with the file
system state. This state consists of a
single files key which is just a
dictionary. The difference though is
that there are a lot of ways for our
agent to interact with these files as
opposed to just one tool like before.
These are represented with the different
tools that we've added in our file
system middleware. We can list out the
files. We can read a particular file
into the context. We can write new files
to store information. And we can also
edit existing files to update the
information in them. And just like
before, our middleware allows us to
modify the model request itself. We
append here a file system prompt that
gives specific instructions on how to
use those tools to update the local file
system.
It's important to remember that
middleware is stackable and extensible.
You can add different pieces of
middleware to an agent and the
middleware will apply in the order that
it's been added. And so what this means
for us is that our system prompt will
first be extended with our planning
instructions and then our file system
instructions and then our sub aent
instructions.
Let's take a closer look at our sub aent
middleware. Now this one's a little bit
more complex and we can see that it
actually takes in a few parameters.
Specifically, it takes in a list of
default sub aent tools which gets passed
to a default sub aent that we create.
And this also takes in a list of
specifically defined sub aents.
In this middleware, what we do is we
create a task tool and we bind that tool
to our agent to call. This task tool
comes with a task system prompt as well
with additional information on how to
call the task tool and exactly when the
main agent should choose to spawn sub
aents. Now let's take a closer look into
exactly how we define these sub aents
with this middleware. In the create task
tool, we do a few things. First, we
build our comprehensive list of sub
aents. Then we define the actual tool
which gets passed back to our model. The
interesting part here in my opinion is
how we actually define their sub aents.
So let's take a closer look at the get
agents function.
We can see here that we also use this
concept of middleware in our sub aents.
Every sub aent that is created in a deep
agent gets some default middleware which
includes planning file system and also
summarization. We haven't explicitly
talked about summarization yet but what
it does is if the context window
increases past a certain amount of
tokens, we automatically compact our
conversation history by summarizing and
still keep some number of messages that
allow us to see what happened recently.
Now we build our sub agents. Every deep
agent by default gets a general purpose
sub agent that has the same tools as the
main agent. Now, in my experience, there
are two main reasons why we want to
create sub agents in the first place.
One of those reasons is to isolate
context, and this is what the general
purpose sub agent is really useful for.
Like I said, it gets the same tools as
the main agent, but it can be given a
single narrow isolated task to complete.
And when it completes this task, it can
then return a comprehensive response
back to the main agent that fully
answers the question, but without any of
the fluff from intermediate tool calls
or interrupts or other wasteful context.
This helps us save a lot of tokens and
time in the long run.
Now, the second reason I usually create
sub aents is when I want to give a sub
agent a focused domain of tasks to be
really good at.
This usually means a custom narrow
prompt with a specific subset of tools
geared to that specific task. These sub
aents are created from the list that's
passed into create deep agent. Let's go
ahead and take a closer look at these
types.
There are two ways to specify this
domain specific sub aent. One, we can
create a tool calling sub aent from
scratch. This sub aent gets a custom
prompt. It also gets a list of tools
that the sub aent can use. And note that
this list of tools can be completely
different from the tools that the main
agent has access to. You can also
specify a custom model for this sub
aent. And just like I mentioned before,
our sub aents also get middleware. You
can specify whatever pre-built or custom
middleware that you want to extend the
state or give more tools to a sub aent.
You can also create custom sub aents
that are more flexible. One piece of
feedback that we got on deep agents
originally is that a lot of people had
already created langraph graphs and they
wanted to expose these graphs to their
main agents as sub agents. You can do
this by passing in that runnable graph
directly into a custom sub aent. And so
to summarize, what our sub agent
middleware does is it builds a list of
these sub aents and it exposes these sub
aents through the task tool so that
whenever your main agent decides that a
task needs to be kicked off, it invokes
the task tool, specifies which sub aent
it wants to call and passes any relevant
information to that sub aent. Then your
sub agent will go off, complete the
task, and then return a comprehensive
response to the agent without any of
that intermediate fluff.
Cool. Stepping back to our agent
builder, that's the bulk of deep agents.
We just talked through each of those
three different pillars which are now
implemented through the middleware
abstraction.
The beauty here is that we also expose
each of these pieces of middleware
independently. Let's say you've built an
agent and you're pretty sure that for
whatever reason it doesn't require a
file system, but you do think it could
really benefit from some planning. What
you could do is you could import the
planning middleware directly from our
package and add just this middleware to
your agent. We found that all three of
these middlewares are pretty useful, but
there are definitely cases where you may
only need a subset of the functionality.
Our default deep agent also comes with
the summarization middleware which
protects us when the context window gets
too long and allows us to compact the
existing conversation.
Now there are a few more concepts which
I think are interesting to cover and one
of the more interesting ones is this
human in the loop middleware.
A lot of mission critical agents by
definition have to call mission critical
tools and sometimes you might want to
pause the agent and allow a human to
review a prospective tool call. You can
do this easily with the human in the
loop middleware.
Deep agents takes a tool config
parameter which we pass to this
middleware.
Any tools specified in this dictionary
will get interrupted before they're
executed. The config then specifies what
actions a human can take on this tool
call. Maybe before a sensitive tool that
sends an email or escalates an issue,
you can specify a tool config that
allows the human to approve the current
action or edit it or also to respond and
give feedback to the agent on what it
can do differently.
This functionality with human in the
loop is now built directly into deep
agents using middleware.
Final thing that I want to call out here
is that you can add your own custom
middleware to a deep agent. We have some
pre-built things that we think are
generally useful for most agents, but
your use case is your use case. You
might need more state keys. You might
need certain tools. You might need other
modifications before or after the model
gets called. And you can add all of
these by extending the deep agent with
your own middleware.
There's a lot more coming down the
pipeline around deep agents that we're
excited to release. So stay tuned over
the next few days and weeks for more
updates. We want to make it really easy
for developers to quickly build and
iterate on powerful agents. And so any
feedback is really welcome as well.
Thanks for watching.
In this video, we will walk through how we rebuilt DeepAgents on top of LangChain 1.0. It will cover the basics of deep agents (planning, filesystem, sub agents), and show case a real world and practical example using Middleware (new in LangChain 1.0) Code: https://github.com/langchain-ai/deepagents LangChain 1.0 https://blog.langchain.com/langchain-langchain-1-0-alpha-releases Middleware: https://blog.langchain.com/agent-middleware Deep agents https://blog.langchain.com/deep-agents