Blog/From LangChain to Deep Agents
March 30, 2026Β·9 min readΒ·El Mahdi EL AIMANI

From LangChain to Deep Agents

Everything you need to understand LangChain, master LangGraph, and build autonomous Deep Agents β€” your complete guide from zero to production.

~25 min read    πŸ›  Python code included    MIT Licensed

What is LangChain?

LangChain is an open-source framework that provides pre-built agent architectures and 1,000+ integrations for any model or tool. It's the fastest way to build AI agents that can interact with LLMs, call tools, search the web, query databases, and perform complex reasoning β€” all without vendor lock-in.

Core Concepts

Concept Description
Chains Compose LLM calls, tools, and logic into reusable sequences. A chain is a pipeline: input β†’ process β†’ output.
Agents Autonomous entities that decide which tools to call and in what order. Built on the ReAct pattern: Reason β†’ Act β†’ Observe.
Tools Functions the agent can call: web search, calculators, APIs, databases, file operations β€” anything with a Python function.
Memory Short-term (conversation buffer) and long-term (vector stores) memory to maintain context across interactions.
# quickstart.py β€” A simple LangChain agent in ~10 lines
from langchain.chat_models import init_chat_model
from langchain.agents import create_agent
from langchain_community.tools import DuckDuckGoSearchRun

model = init_chat_model("anthropic:claude-sonnet-4-20250514")
tools = [DuckDuckGoSearchRun()]

agent = create_agent(model, tools)
result = agent.invoke({
    "messages": [{"role": "user", "content": "What happened in AI this week?"}]
})
print(result)

πŸ’‘ Key insight: LangChain agents are built on top of LangGraph. You can start with LangChain's high-level APIs and seamlessly drop down to LangGraph when you need more control β€” no rewrite required.


LangGraph β€” The Agent Runtime

LangGraph is a low-level orchestration framework for building stateful, multi-step AI agents. It models your agent as a state graph: nodes are functions, edges are transitions, and state is checkpointed after every step. This is what separates a prototype from production.

Why LangGraph?

Traditional chains are linear and stateless. When your agent needs loops, branching, human approval, crash recovery, or multi-agent coordination β€” you need LangGraph. It's the engine behind companies like Klarna, Replit, Elastic, Uber, and LinkedIn.

Feature Description
Cyclic Graphs Unlike DAGs, LangGraph supports loops. Agents can retry, validate, refine, and iterate β€” just like human reasoning.
Durable Execution Server crashes mid-workflow? LangGraph resumes from the exact checkpoint. No lost work, no starting over.
Human-in-the-Loop Pause execution for human review. The agent waits β€” seconds or days β€” then resumes from that exact state.
Persistent Memory Short-term working memory for ongoing reasoning. Long-term persistent memory across sessions via MemoryStore.

Core Concepts

Concept What It Does
StateGraph The container graph. Defines your agent's structure and flow.
State A shared TypedDict β€” the "notebook" every node can read and write.
Node A function that receives state, does work (LLM call, tool, logic), and returns updated state.
Edge A transition between nodes. Can be unconditional or conditional (branching).
Checkpointer Saves state after each node execution. Enables replay, resume, time-travel debugging.
Interrupt Pauses execution at a specific node for human approval or input before continuing.
# langgraph_basics.py
from typing import TypedDict
from langgraph.graph import StateGraph, END
from langchain_openai import ChatOpenAI
from langchain.schema import HumanMessage

class State(TypedDict):
    question: str
    answer: str

llm = ChatOpenAI(model="gpt-4o", temperature=0)

def research(state: State):
    res = llm([HumanMessage(content=state["question"])])
    return {"answer": res.content}

def refine(state: State):
    prompt = f"Improve and verify this answer:\n{state['answer']}"
    res = llm([HumanMessage(content=prompt)])
    return {"answer": res.content}

graph = StateGraph(State)
graph.add_node("research", research)
graph.add_node("refine", refine)
graph.set_entry_point("research")
graph.add_edge("research", "refine")
graph.add_edge("refine", END)

app = graph.compile()
result = app.invoke({"question": "Explain quantum computing"})
print(result["answer"])

Deep Agents β€” The Big Picture

A traditional chatbot is reactive: you ask, it answers. No planning, no memory, no coordination. Deep Agents are a fundamentally different class of AI systems β€” autonomous agents that can plan complex multi-step tasks, delegate work to sub-agents, manage their own context, and persist memory across sessions.

πŸ”¬ Origin story: Deep Agents was inspired by analyzing what makes Claude Code so effective as a general-purpose agent. The team identified four key primitives β€” planning, filesystem access, sub-agents, and detailed prompts β€” and abstracted them into an open-source, model-agnostic framework.

What Makes an Agent "Deep"?

The core algorithm is the same as any agent β€” an LLM running in a loop calling tools. The difference is what's built in: structured planning, a virtual filesystem, sub-agent spawning, and richly engineered system prompts.

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                   DEEP AGENT (Main)                     β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”‚
β”‚  β”‚ Planning β”‚  β”‚   System     β”‚  β”‚   Memory Store    β”‚  β”‚
β”‚  β”‚ (TODO)   │──│   Prompt     │──│   /memories/      β”‚  β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”‚
β”‚  β”‚  read_file β”‚ write_file β”‚ search β”‚ custom_tools  β”‚    β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β”‚
β”‚        β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”                      β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”           β”Œβ”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”               β”‚
β”‚  β”‚ Sub-Agent  β”‚           β”‚ Sub-Agent  β”‚                β”‚
β”‚  β”‚ (Research) β”‚           β”‚ (Coding)   β”‚                β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜           β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜                β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
             β”‚
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚   Streaming β”‚ Checkpointing β”‚ Persistence β”‚ Studio     β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

The 5 Pillars of Deep Agents

1. Planning First β€” The TODO Tool

Deep Agents include a built-in write_todos tool. It forces the agent to break down complex tasks into structured steps before acting β€” a context engineering strategy directly inspired by Claude Code.

TODO:
  1. [ ] Search for LangGraph documentation
  2. [ ] Read core concepts and architecture
  3. [ ] Collect code examples
  4. [ ] Write structured summary
  5. [ ] Review and refine output

2. Filesystem Access β€” Context Management

Agents have read/write access to a virtual filesystem. Instead of stuffing every result into the context window, the agent offloads large results and notes to storage. Since v0.2, supports pluggable backends β€” S3, local disk, or in-memory.

3. Sub-Agents β€” Divide and Conquer

Complex tasks are split across isolated sub-agents, each with their own context window. The main agent becomes a coordinator while sub-agents go deep on specific tasks.

4. Human-in-the-Loop β€” Approval Gates

The agent pauses before designated actions, waits for your confirmation, then continues β€” or adjusts based on your feedback.

5. Persistent Memory β€” Cross-Session Learning

User preferences and findings are saved in /memories/. The agent builds on previous sessions via LangGraph's Memory Store.

⚠️ Trust model: Deep Agents follows a "trust the LLM" approach. Enforce boundaries at the tool/sandbox level, not by expecting the model to self-police.


Getting Started in 5 Minutes

pip install deepagents

export ANTHROPIC_API_KEY="sk-ant-..."
from deepagents import create_deep_agent

agent = create_deep_agent()

result = agent.invoke({
    "messages": [{
        "role": "user",
        "content": "Research the latest advances in AI agents "
                   "and write a structured report with code examples"
    }]
})

⚑ Pro tip: create_deep_agent returns a compiled LangGraph graph β€” you get streaming, Studio, checkpointing, and all LangGraph features for free.


Building a Custom Deep Agent

from deepagents import create_deep_agent
from langchain.chat_models import init_chat_model
from langchain_core.tools import tool

@tool
def query_database(sql: str) -> str:
    """Execute a SQL query against the analytics database."""
    return execute_sql(sql)

@tool
def send_slack_notification(channel: str, message: str) -> str:
    """Send a message to a Slack channel."""
    return slack_client.post(channel, message)

model = init_chat_model("anthropic:claude-sonnet-4-20250514")

agent = create_deep_agent(
    model=model,
    tools=[query_database, send_slack_notification],
    system_prompt="""You are a data analytics assistant.
    Always verify your SQL before executing.""",
)

Adding MCP Server Support

from langchain_mcp_adapters import MCPToolkit

toolkit = MCPToolkit(server_url="https://mcp.asana.com/sse")

agent = create_deep_agent(
    tools=[*toolkit.get_tools(), query_database],
    system_prompt="You manage tasks in Asana and report on data."
)

Deep Agents CLI

curl -LsSf https://raw.githubusercontent.com/langchain-ai/deepagents/main/libs/cli/scripts/install.sh | bash

deepagents
deepagents -n "Refactor the auth module and add unit tests"

Features: interactive mode Β· headless CI/CD Β· custom skills Β· persistent memory Β· human-in-the-loop approvals

πŸ“Š Benchmark: ~42.65% on Terminal Bench 2.0 with Claude Sonnet 4.5 β€” on par with Claude Code on the same model tier.


LangChain vs LangGraph vs Deep Agents

Feature LangChain LangGraph Deep Agents
Role Agent Framework Agent Runtime Agent Harness
Best For Quick prototypes Custom control flow Autonomous long-running tasks
Planning Manual Manual Built-in TODO tool
Sub-Agents DIY Via subgraphs Built-in with context isolation
Memory Basic Full Full + /memories/
Filesystem No No Virtual FS (pluggable)
Streaming Yes Yes Yes (via LangGraph)
License MIT MIT MIT

🎯 Rule of thumb: Start with LangChain β†’ move to LangGraph for custom control flow β†’ use Deep Agents for autonomous, long-running tasks.


Architecture Reference

The Deep Agent Loop

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚   User Message       β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
           β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  System Prompt +     β”‚
β”‚  Custom Instructions β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
           β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚         AGENT LOOP               β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”‚
β”‚  β”‚   LLM   │───▢│  Tool    β”‚    β”‚
β”‚  β”‚  Think  β”‚    β”‚ Execute  β”‚    β”‚
β”‚  β””β”€β”€β”€β”€β–²β”€β”€β”€β”€β”˜    β””β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”˜    β”‚
β”‚       β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜          β”‚
β”‚  write_todos β”‚ read_file        β”‚
β”‚  write_file  β”‚ spawn_subagent   β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
               β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚   Final Response     β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Filesystem Layout

/
β”œβ”€β”€ memories/
β”‚   β”œβ”€β”€ preferences.md
β”‚   └── research/
β”œβ”€β”€ workspace/
β”‚   β”œβ”€β”€ todo.md
β”‚   └── output/
└── skills/
    └── my_skill.md

Production Deployment

from deepagents import create_deep_agent
from langgraph.checkpoint.postgres import PostgresSaver

agent = create_deep_agent(
    model=init_chat_model("anthropic:claude-sonnet-4-20250514"),
    tools=my_production_tools,
    system_prompt=my_prompt,
)

for event in agent.stream(
    {"messages": [{"role": "user", "content": task}]},
    config={"configurable": {"thread_id": "session-42"}}
):
    print(event)

Resources & Next Steps

Resource Link
πŸ“¦ GitHub github.com/langchain-ai/deepagents
Docs docs.langchain.com
Launch Post blog.langchain.com/deep-agents
Academy LangGraph Course
LangSmith smith.langchain.com

Bottom line: Deep Agents makes it possible to build your own Claude Code on your own servers. 100% open source (MIT), works with any LLM. Start building.

El Mahdi EL AIMANI

Senior AI Engineer Β· elaimani.io

← Back to blog
El Mahdi EL AIMANI β€” LLMOps Architect & Senior AI Engineer