A deep agent is an LLM agent built to hold up on long-running tasks. It plans before acting, writes intermediate results to files instead of piling them into its context, and hands the bulky parts off to subagents.
The term isn't standardized: it names a family of architectures, not a spec. LangChain is what put it on the map, taking the patterns shared by tools capable of working for hours on a topic — Claude Code chief among them — and packaging them into an open source library, deepagents. That implementation is the thread running through this article, because it's documented and readable; the same ideas show up elsewhere under different names.
The regular agent and its ceiling
An agent, in the common sense of the word, is a loop. You give the model a goal and some tools, it calls a tool, you hand back the result, it calls another one, until it answers without calling anything. LangChain calls these agents shallow. Over three or four steps they work fine, and that's what the word "agent" covers most of the time in the projects people bring us.
As the turns pile up, two things break.
The first is context. In a minimal agent, tool results are usually appended to the history with no systematic offloading strategy: a page's HTML, a complete API response, the output of a test suite. After many calls the window fills with raw material and the original request drowns in it. The model is then reasoning largely on noise it produced itself.
The second is direction. With no plan written down anywhere, the agent re-decides what comes next on every turn, based on whatever is in front of it. It optimizes locally: it fixes the detail it just saw and drops three quarters of the original request. Nobody notices until the end.
In the architecture popularized by LangChain, a deep agent combines four building blocks to tackle both.
Block 1: a detailed, structured system prompt
The first difference is the least technical and the most underrated. A deep agent's system prompt isn't a one-line role statement. It spells out when to use each tool, gives examples of good and bad responses, states explicit prohibitions, and defines how the agent knows it's done.
Length isn't the point, structure is: a badly organized three-page prompt is worth no more than a ten-line one. LangChain points to the community-reconstructed Claude Code system prompts as the reference here, where most of the agent's behavior lives in those rules rather than in the loop's code. On a ten-minute task, the difference between an agent that lands and an agent that goes off the rails often comes down to three paragraphs of instructions.
Block 2: a planning tool
deepagents ships a write_todos tool that maintains a task list with statuses: pending, in progress, completed.
The interesting detail is that this tool computes nothing. No external call, no side effect: it writes the list into the agent's state, and that's it. Its only value is that the plan reappears in the context on every turn, which re-anchors the model on the whole objective rather than the last ten messages. It's context engineering disguised as a tool, and it remains one of the highest-return additions in the architecture.
Block 3: a file system
The deep agent gets ls, read_file, write_file, edit_file, glob and grep, plus an execute for shell commands when the backend is a sandbox. The backends documentation covers the available implementations.
Files act as working memory. The agent fetches a sixty-page report, writes it to sources/report.md, and keeps only the path in its context. When it needs the content, it reads the relevant slice back with grep. The context carries references instead of content, so it holds up over time.
That file system isn't necessarily a disk. Available backends range from LangGraph state (files live for the length of one conversation) to local disk, a store shared across conversations, or a remote sandbox. The agent's code doesn't change, only the backend does. It's the same decoupling logic as in regular software architecture: the agent talks to an interface, not an implementation.
Block 4: subagents
The last tool is called task. It spawns an ephemeral subagent: clean context, precise mission, one final report back.
The first benefit is context isolation. A subagent sent to dig through documentation can burn thirty tool calls; the main agent sees a single one, with the summary.
Delegation buys you three other things: specialized tooling, since each subagent only gets what its mission needs; parallelism across lines of work that don't need to talk to each other; and tighter permissions, since a subagent that only explores has no business holding write access. You define a subagent with a name, a description (the main agent uses it to decide whether to delegate), a system prompt and its own tool list. A general-purpose subagent exists by default.
Don't make it a reflex, though. The subagent doesn't see the conversation history: all it knows is what the main agent bothered to write down for it. A poorly described task comes back with a report that misses the point, and you've paid twice. Delegation pays off on bulky, well-bounded tasks, much less on ambiguous ones.
What the four blocks have in common
They all answer the same constraint: the context window is a finite resource, and an agent that works for a long time fills it mechanically. Hence three complementary mechanisms, which deepagents ships as middleware.
Summarize: once the history crosses a threshold, it gets compressed automatically into a summary that replaces the older messages.
Offload: large tool results go to files, and only the path stays in memory.
Isolate: expensive exploration happens inside a subagent, and only the result comes back.
Prompt caching sits on top: with providers that support it, it can cut the cost and latency tied to stable conversation prefixes. The actual gain depends on the model, on how stable that prefix really is, and on how the cache is priced, so measure it before you turn it into an argument.
Handing control back to a human
An agent that writes to a database, sends emails or pushes code without review doesn't ship to production. That's often the point that decides whether an agent project makes it past the prototype.
deepagents handles this with an interrupt_on parameter: you list the tools that require approval, and execution pauses before the call. The human-in-the-loop middleware exposes three decisions that cover most cases — approve runs the call as is, edit changes the arguments before execution, reject cancels the call and sends an explanation back to the model.
from deepagents import create_deep_agent
from langgraph.checkpoint.memory import InMemorySaver
agent = create_deep_agent(
model="anthropic:claude-sonnet-4-6",
tools=[web_search],
system_prompt=PROMPT,
interrupt_on={
# file write: the content can be corrected before it lands
"write_file": {"allowed_decisions": ["approve", "edit", "reject"]},
# shell command: it's a yes or a no
"execute": {"allowed_decisions": ["approve", "reject"]},
# reads are harmless, let them through
"read_file": False,
},
checkpointer=InMemorySaver(),
)Two things to know before wiring this up. The checkpointer is mandatory, since the state has to live somewhere while the agent waits for your answer — InMemorySaver is fine in development, but you need a database behind it in production, otherwise a restart loses every pending task. And a rejection with no explanation sends the agent into a loop: it retries the same thing, gets rejected again, and you burn tokens for nothing. A rejection should always carry guidance.
Interrupts can also be conditional. A write inside the working directory goes through silently, a write anywhere else triggers approval. That setting is what makes the agent usable day to day: too many approval requests and the human ends up approving everything unread, which amounts to reviewing nothing.
Memory and skills
Two mechanisms round out the picture.
Long-term memory works through AGENTS.md files stored in a persistent backend. The agent reads them at startup, so preferences, conventions and past decisions survive from one conversation to the next, and it can update them itself.
That last capability deserves a warning. Memory the agent can rewrite is an injection surface: malicious content encountered during a task can plant an instruction that gets read back, and acted on, in every later session. LangChain recommends partitioning memory per user and making files that carry shared policy read-only. Treat those files like code: reviewed before they're written, narrow in scope, and never a shared store any session can edit.
Skills are procedures the agent loads only when it needs them. Rather than bloating the system prompt with fifteen operating procedures, you store them alongside and the agent reads the one that fits the situation. The documentation calls this progressive disclosure: the context holds only what's useful right now.
When a deep agent is worth it
This architecture has a cost. More latency, more tokens, and noticeably more painful debugging: when a subagent returns a shaky report, you have to walk the trace back to work out what it actually saw and what it made up. It isn't free.
Four signals say it's worth the trouble: the number of steps is unknown when you launch the task, the material to process far exceeds the context window, the task calls on genuinely distinct skills, or it runs for minutes or hours. Document research, code audits, and analysis of a heterogeneous document corpus tick those boxes.
Conversely, if your process is deterministic — step 1, then 2, then 3, always in that order — write a regular workflow and call the model where it adds something. You'll get something faster, cheaper and testable. Same verdict if a user is waiting on screen for the answer, or if you need to replay an identical run for an audit: an autonomous agent gives you no guarantee of an identical execution path from one run to the next.
Three questions usually settle it:
- Is the execution path known in advance? If yes, it's a workflow.
- Does the task overflow the context window? If not, a simple agent is enough.
- Are there actions that need approval before they run? If yes, design the human loop from the start, not after the demo.
And if you do go for it, start with a simple agent and good tools. Add planning, files and subagents once you've seen where your agent actually falls over, not before.
To dig into the implementation, LangChain publishes a free 38-lesson course, Introduction to DeepAgents, which walks through these blocks one by one with runnable code.




