Skip to content

Deepagents is an agent harness built on langchain and langgraph. Deep agents are equipped with a planning tool, a filesystem backend, and the ability to spawn subagents - making them well-equipped to handle complex agentic tasks.

License

Notifications You must be signed in to change notification settings

langchain-ai/deepagents

Repository files navigation

🚀🧠 Deep Agents

Agents can increasingly tackle long-horizon tasks, with agent task length doubling every 7 months! But, long horizon tasks often span dozens of tool calls, which present cost and reliability challenges. Popular agents such as Claude Code and Manus use some common principles to address these challenges, including planning (prior to task execution), computer access (giving the able access to a shell and a filesystem), and sub-agent delegation (isolated task execution). deepagents is a simple agent harness that implements these tools, but is open source and easily extendable with your own custom tools and instructions.

deep agent

📚 Resources

🚀 Quickstart

You can give deepagents custom tools. Below, we'll optionally provide the tavily tool to search the web. This tool will be added to the deepagents build-in tools (see below).

pip install deepagents tavily-python

Set TAVILY_API_KEY in your environment (get one here):

import os
from deepagents import create_deep_agent

tavily_client = TavilyClient(api_key=os.environ["TAVILY_API_KEY"])

def internet_search(query: str, max_results: int = 5):
    """Run a web search"""
    return tavily_client.search(query, max_results=max_results)

agent = create_deep_agent(
    tools=[internet_search],
    system_prompt="Conduct research and write a polished report.",
)

result = agent.invoke({"messages": [{"role": "user", "content": "What is LangGraph?"}]})

The agent created with create_deep_agent is compiled LangGraph StateGraph, so it can used it with streaming, human-in-the-loop, memory, or Studio just like any LangGraph agent. See our quickstarts repo for more examples.

Customizing Deep Agents

There are several parameters you can pass to create_deep_agent.

model

By default, deepagents uses "claude-sonnet-4-5-20250929". You can customize this by passing any LangChain model object.

from langchain.chat_models import init_chat_model
from deepagents import create_deep_agent

model = init_chat_model("openai:gpt-4o")
agent = create_deep_agent(
    model=model,
)

system_prompt

You can provide a system_prompt parameter to create_deep_agent(). This custom prompt is appended to default instructions that are automatically injected by middleware.

When writing a custom system prompt, you should:

  • ✅ Define domain-specific workflows (e.g., research methodology, data analysis steps)
  • ✅ Provide concrete examples for your use case
  • ✅ Add specialized guidance (e.g., "batch similar research tasks into a single TODO")
  • ✅ Define stopping criteria and resource limits
  • ✅ Explain how tools work together in your workflow

Don't:

  • ❌ Re-explain what standard tools do (already covered by middleware)
  • ❌ Duplicate middleware instructions about tool usage
  • ❌ Contradict default instructions (work with them, not against them)
from deepagents import create_deep_agent
research_instructions = """your custom system prompt"""
agent = create_deep_agent(
    system_prompt=research_instructions,
)

See our quickstarts repo for more examples.

tools

Provide custom tools to your agent (in addition to Built-in Tools):

from deepagents import create_deep_agent

def internet_search(query: str) -> str:
    """Run a web search"""
    return tavily_client.search(query)

agent = create_deep_agent(tools=[internet_search])

You can also connect MCP tools via langchain-mcp-adapters:

from langchain_mcp_adapters.client import MultiServerMCPClient
from deepagents import create_deep_agent

async def main():
    mcp_client = MultiServerMCPClient(...)
    mcp_tools = await mcp_client.get_tools()
    agent = create_deep_agent(tools=mcp_tools)

    async for chunk in agent.astream({"messages": [{"role": "user", "content": "..."}]}):
        chunk["messages"][-1].pretty_print()

middleware

Deep agents use middleware for extensibility (see Built-in Tools for defaults). Add custom middleware to inject tools, modify prompts, or hook into the agent lifecycle:

from langchain_core.tools import tool
from deepagents import create_deep_agent
from langchain.agents.middleware import AgentMiddleware

@tool
def get_weather(city: str) -> str:
    """Get the weather in a city."""
    return f"The weather in {city} is sunny."

class WeatherMiddleware(AgentMiddleware):
    tools = [get_weather]

agent = create_deep_agent(middleware=[WeatherMiddleware()])

subagents

The main agent can delegate work to sub-agents via the task tool (see Built-in Tools). You can supply custom sub-agents for context isolation and custom instructions:

from deepagents import create_deep_agent

research_subagent = {
    "name": "research-agent",
    "description": "Used to research in-depth questions",
    "prompt": "You are an expert researcher",
    "tools": [internet_search],
    "model": "openai:gpt-4o",  # Optional, defaults to main agent model
}

agent = create_deep_agent(subagents=[research_subagent])

For complex cases, pass a pre-built LangGraph graph:

from deepagents import CompiledSubAgent, create_deep_agent

custom_graph = create_agent(model=..., tools=..., prompt=...)

agent = create_deep_agent(
    subagents=[CompiledSubAgent(
        name="data-analyzer",
        description="Specialized agent for data analysis",
        runnable=custom_graph
    )]
)

See the subagents documentation for more details.

interrupt_on

Some tools may be sensitive and require human approval before execution. Deepagents supports human-in-the-loop workflows through LangGraph’s interrupt capabilities. You can configure which tools require approval using a checkpointer.

These tool configs are passed to our prebuilt HITL middleware so that the agent pauses execution and waits for feedback from the user before executing configured tools.

from langchain_core.tools import tool
from deepagents import create_deep_agent

@tool
def get_weather(city: str) -> str:
    """Get the weather in a city."""
    return f"The weather in {city} is sunny."

agent = create_deep_agent(
    model="anthropic:claude-sonnet-4-20250514",
    tools=[get_weather],
    interrupt_on={
        "get_weather": {
            "allowed_decisions": ["approve", "edit", "reject"]
        },
    }
)

See the human-in-the-loop documentation for more details.

backend

Deep agents use pluggable backends to control how filesystem operations work. By default, files are stored in the agent's ephemeral state. You can configure different backends for local disk access, persistent cross-conversation storage, or hybrid routing.

from deepagents import create_deep_agent
from deepagents.backends import FilesystemBackend

agent = create_deep_agent(
    backend=FilesystemBackend(root_dir="/path/to/project"),
)

Available backends include:

  • StateBackend (default): Ephemeral files stored in agent state
  • FilesystemBackend: Real disk operations under a root directory
  • StoreBackend: Persistent storage using LangGraph Store
  • CompositeBackend: Route different paths to different backends

See the backends documentation for more details.

Long-term Memory

Deep agents can maintain persistent memory across conversations using a CompositeBackend that routes specific paths to durable storage.

This enables hybrid memory where working files remain ephemeral while important data (like user preferences or knowledge bases) persists across threads.

from deepagents import create_deep_agent
from deepagents.backends import CompositeBackend, StateBackend, StoreBackend
from langgraph.store.memory import InMemoryStore

agent = create_deep_agent(
    backend=CompositeBackend(
        default=StateBackend(),
        routes={"/memories/": StoreBackend(store=InMemoryStore())},
    ),
)

Files under /memories/ will persist across all conversations, while other paths remain temporary. Use cases include:

  • Preserving user preferences across sessions
  • Building knowledge bases from multiple conversations
  • Self-improving instructions based on feedback
  • Maintaining research progress across sessions

See the long-term memory documentation for more details.

Built-in Tools

deep agent

Every deep agent created with create_deep_agent comes with a standard set of tools:

Tool Name Description Provided By
write_todos Create and manage structured task lists for tracking progress through complex workflows TodoListMiddleware
read_todos Read the current todo list state TodoListMiddleware
ls List all files in a directory (requires absolute path) FilesystemMiddleware
read_file Read content from a file with optional pagination (offset/limit parameters) FilesystemMiddleware
write_file Create a new file or completely overwrite an existing file FilesystemMiddleware
edit_file Perform exact string replacements in files FilesystemMiddleware
glob Find files matching a pattern (e.g., **/*.py) FilesystemMiddleware
grep Search for text patterns within files FilesystemMiddleware
execute* Run shell commands in a sandboxed environment FilesystemMiddleware
task Delegate tasks to specialized sub-agents with isolated context windows SubAgentMiddleware

The execute tool is only available if the backend implements SandboxBackendProtocol. By default, it uses the in-memory state backend which does not support command execution. As shown, these tools (along with other capabilities) are provided by default middleware:

See the agent harness documentation for more details on built-in tools and capabilities.

Built-in Middleware

deepagents uses middleware under the hood. Here is the list of the middleware used.

Middleware Purpose
TodoListMiddleware Task planning and progress tracking
FilesystemMiddleware File operations and context offloading (auto-saves large results)
SubAgentMiddleware Delegate tasks to isolated sub-agents
SummarizationMiddleware Auto-summarizes when context exceeds 170k tokens
AnthropicPromptCachingMiddleware Caches system prompts to reduce costs (Anthropic only)
PatchToolCallsMiddleware Fixes dangling tool calls from interruptions
HumanInTheLoopMiddleware Pauses execution for human approval (requires interrupt_on config)

Built-in prompts

The middleware automatically adds instructions about the standard tools. Your custom instructions should complement, not duplicate these defaults:

  • Explains when to use write_todos and read_todos
  • Guidance on marking tasks completed
  • Best practices for todo list management
  • When NOT to use todos (simple tasks)
  • Lists all filesystem tools (ls, read_file, write_file, edit_file, glob, grep, execute*)
  • Explains that file paths must start with /
  • Describes each tool's purpose and parameters
  • Notes about context offloading for large tool results
  • Explains the task() tool for delegating to sub-agents
  • When to use sub-agents vs when NOT to use them
  • Guidance on parallel execution
  • Subagent lifecycle (spawn → run → return → reconcile)

About

Deepagents is an agent harness built on langchain and langgraph. Deep agents are equipped with a planning tool, a filesystem backend, and the ability to spawn subagents - making them well-equipped to handle complex agentic tasks.

Resources

License

Stars

Watchers

Forks

Packages

No packages published