Deep Agents

What an agent harness is and what LangChain’s deepagents library provides, explained for a developer new to the space. Prerequisites: LLM Tool Calling (the loop underneath everything) and LangGraph vs CrewAI Research (the framework layer this sits on top of). The runtime/framework/harness vocabulary is laid out in Frameworks, runtimes, and harnesses — this note is a worked example of the harness tier.


1. Where a harness sits, and why you already know one

From the earlier notes in this sequence: tool calling is the loop, and a framework like LangGraph gives you primitives to orchestrate loops — nodes, edges, state, checkpoints. But primitives aren’t a product. Every team building a serious agent on raw LangGraph ends up re-implementing the same five or six things: a planner, somewhere to put large outputs, a way to delegate subtasks, something to do when the context fills up. A harness is those things pre-built with opinionated defaults — LangGraph is the engine, Deep Agents is the car.

Here’s the shortcut to understanding it: you already use a harness every day — Claude Code is one. The to-do list it maintains, the scratchpad files it writes, the subagents it spawns for research, the context summarization when a session runs long, the memory directory that persists between sessions — that is the harness feature set. deepagents is LangChain’s open-source library for building agents with exactly that pattern, and the correspondence is nearly one-to-one. Keep that mapping in mind; the five capabilities below will feel familiar rather than novel.

The library is a standalone Python package on top of LangChain/LangGraph, and the entire API surface for the simple case is one function:

from deepagents import create_deep_agent

def get_weather(city: str) -> str:
    """Get weather for a given city."""
    return f"It's always sunny in {city}!"

agent = create_deep_agent(
    tools=[get_weather],
    system_prompt="You are a helpful assistant",
)

agent.invoke({"messages": [{"role": "user", "content": "What is the weather in Mumbai?"}]})

2. Why “deep”: the long-horizon problem

A plain tool-calling agent — one loop, a handful of tools — is shallow: it works beautifully for tasks that finish in a few turns and degrades badly on tasks that take hundreds. The reason is always the same resource: the context window. Every tool result, every intermediate step, every dead end accumulates in the conversation until the model is drowning in its own history — slower, costlier, and dumber, because relevant facts are buried in noise.

So read the five capabilities below as one coherent design, not a feature list: every one of them is a context-management strategy. The memory hierarchy analogy holds up remarkably well — treat the context window as RAM, and everything else as the machinery an OS uses when RAM is scarce.

3. The five capabilities

3.1 Built-in planning (write_todos)

Every deep agent gets a write_todos tool: it breaks the task into steps with states (pending, in_progress, completed), and the list persists in agent state. The point is subtler than “plans are nice”: over a long task, a model’s attention to its original goal drifts. An externalized, re-read to-do list is working memory on paper — the same reason a sysadmin works through a written checklist during a 3 a.m. change window instead of trusting recall. The agent can also revise the plan mid-flight, so it’s a living document, not a rigid script.

3.2 Virtual filesystem — the context window’s swap space

Deep agents ship with filesystem tools (ls, read_file, write_file, edit_file, glob, grep), and the harness uses them for a trick that carries most of the weight: any tool result over ~20,000 tokens is automatically offloaded to a file, and the context gets only the file path plus a short preview. That is paging, literally: RAM (context) holds a pointer and a hot preview; the full data sits on disk (filesystem) and is paged back in only if the agent actually needs it. Backends range from in-memory dicts through local disk to LangGraph Store and sandboxed cloud filesystems — the agent-facing interface is identical.

3.3 Subagent spawning — fork off the noisy work

A built-in task tool lets the agent delegate a subtask to a fresh subagent that runs with its own clean context and returns only a summary. The Unix shape is fork/exec and wait: the child does its messy, exploratory work in its own address space — twenty file reads, a dozen dead ends — none of which pollutes the parent. The parent receives the equivalent of an exit status plus a report. This is the single biggest lever for long tasks: exploration is exactly the phase that generates the most context garbage, so quarantining it buys the parent agent an enormous effective horizon.

3.4 Automatic context compression — log rotation for conversations

When context reaches ~85% of the model’s limit, the harness generates a structured summary (intent so far, artifacts produced, next steps) and replaces the old history with it, while the original messages are preserved to the filesystem in case something needs to be recovered verbatim. The analogy is log rotation with compaction: the live log stays small, the archive keeps everything. It’s the graceful-degradation answer to the question every long-running agent eventually faces — “what happens when the window fills anyway?”

3.5 Long-term memory — a home directory that survives reboots

Via a composite backend, files under /memories/ persist across sessions and threads. Everything above manages one task’s context; this is the tier that survives the process — user preferences, project conventions, lessons learned — the agent’s dotfiles. It’s what turns a task-runner into something that gets better at working with you over weeks.

4. The CLI

The library ships a terminal agent — pip install deepagents, then deepagents — with interactive and pipe (-n) modes and custom skills. Worth ten minutes to see the harness pattern live: watch it write todos, spill research to files, and spawn subagents on a real task, then recognize the identical behaviors in any Claude Code session.

5. When to use it (and when not)

  • Use a harness when the task is long-horizon: multi-step research, large intermediate artifacts, work that outlives one context window or one session. Building those five capabilities yourself is weeks of subtle engineering — offload thresholds, summary quality, subagent protocols — that the harness has already made opinionated choices about.
  • Use raw LangGraph when you need explicit graph topology — regulated workflows, custom approval gates, precise control over every transition (LangGraph vs CrewAI Research §2). Harness defaults are opinions, and sometimes your process disagrees with them.
  • Use neither for shallow tasks. A 1–2 tool-call agent wrapped in a deep-agent harness is overhead with no payoff — the shallow loop from LLM Tool Calling §5 is the right tool.

The layering, bottom to top, for orientation: tool calling → framework (LangGraph) → harness (Deep Agents / Claude Code) → the protocols that connect it outward (Model-Context-Protocol-MCP for tools, A2A-Protocol for peers).

6. Resources