Back to HomepageAgent Development Guide

From LangChain to LangGraph: Orchestrating Production Agents

A clean mental model for building reliable AI workflows. LangGraph orchestrates multi-step, stateful workflows. LangChain/LCEL builds individual steps. Combine them for production-ready agents.

Architecture Overview

LangChain to LangGraph architecture overview

TL;DR

LangGraph handles the workflow orchestration (nodes, edges, state, control flow).

LangChain/LCEL handles individual steps (prompt composition, model calls, output parsing).

Events are runtime signals (tool_failed, human_approved, etc.) that edges use to decide what happens next.

Use LangGraph when you need loops, retries, human approvals, or state persistence. Use LCEL alone for simple, one-shot prompt→parse flows.

Why LangGraph Exists

Modern AI apps aren't single prompts; they're workflows: plan → call tools → validate → branch → maybe ask a human → retry → finish. LangGraph treats this as a graph with explicit nodes and edges, plus a durable state you can pause/resume, audit, and recover.

Think of your agent as a workflow with multiple decision points, not just a linear chain. You need explicit control flow, state management, and the ability to handle retries, approvals, and recovery.

The Four Primitives (and How Events Fit)

1. Graph

Your app's topology — named nodes and edges that form linear paths, branches, and loops. Makes control flow explicit and testable.

2. State

A persisted, typed dictionary that flows through the graph (messages, plan, observations). Each node reads state and returns partial updates; reducers merge them deterministically.

3. Node

A unit of work: planner, tool call, validator, router, human-approval gate. Internally, a node can use LangChain/LCEL while LangGraph provides orchestration around it.

4. Edges

Explicit control rules: next(A→B), conditional edges (guards), and loop edges. Edges examine state and recent events to decide routing, retries, and recovery.

Detailed Reference

LangChain to LangGraph detailed reference — primitives, LCEL vs LangGraph, and blueprint

The four primitives, when to use LCEL vs. LangGraph, and a 6-step blueprint for reliable agent workflows.

Where “Events” Fit

Events are runtime signals — tool_succeeded, validation_failed, human_approved, timeout_fired. They're inputs that nodes emit and edges consult to branch, loop, or pause/resume the run.

Example: When a tool fails, an edge routes to a retry node with backoff based on the tool_failed event.

Example: When approval is requested, the runner pauses until a human_approved event arrives.

Why Not “Just LangChain” for This

Deterministic Control

Complex branching/loops and guarded routes are clearer in a graph than nested callbacks.

Durability & Observability

Checkpoints, resume after failure, and auditable steps/events are first-class in LangGraph.

Human-in-the-Loop

Clean pauses on events and resumes with updated state are fundamental, not an add-on.

When to Use Which

Choose LangGraph when:

  • Multi-step agents (plan→act→observe) with guarded routing and loops
  • Durability (checkpoints), resumability, and human gates
  • Retries/backoff, idempotent recovery, and time-boxed tasks

Choose LCEL alone when:

  • A straight, stateless pipeline (RAG answer with a parser)
  • Fast to build, no branching required
  • Simple prompt → model → parse workflows

Best Practice — Combine Them:

Use LangGraph for Graph + State + Edges (the workflow brain). Implement each Node with LCEL/LangChain for ergonomic prompt/model/parsing logic. You get step-level developer speed with workflow-level reliability.

Putting It Together: A Reusable Blueprint

1

Initialize State

Seed messages, plan, and context (user query, retrieved docs). Checkpoint.

state = { messages: [user_query], plan: null, observations: [], context: retrieved_docs }
2

Planner Node

Produces a plan (LCEL inside), emits plan_ready event, updates state. Edge guard: if risky action → route to approval.

3

Approval Node

Pauses on approval_requested; resumes on human_approved / human_rejected. Edge chooses proceed or cancel.

4

Act Node (Tools)

Executes a tool call (LCEL/tool wrapper). On tool_failed, edge loops back with exponential backoff; on tool_succeeded, continue.

5

Validate Node

Checks outputs (schema/guardrails). If validation_failed, edge loops to planner or act; else finish. Checkpoint.

6

Finish Node

Collates final messages/result from state and returns.

Quick Decision Table

SituationPickWhy
One-shot prompt → model → parseLCELMinimal plumbing; no branching needed.
Agent with tools, retries, approvalsLangGraphGraph-level guards, checkpoints, events, loops.
Complex workflow, ergonomic step logicBothLCEL inside nodes; LangGraph for orchestration.

Takeaway

1. Model the workflow (Graph/Nodes/Edges) and persist the state; let events move you through the graph.

2. Keep step internals ergonomic with LCEL, but avoid using it to simulate orchestration.

3. For reliability, recovery, and human-in-the-loop, LangGraph is the right abstraction, with LCEL as the implementation detail inside nodes.

Essential Tools

LangGraph

Orchestration framework for stateful, reliable agent workflows.

  • • Graph-based workflow definition
  • • State management with checkpointing
  • • Event-driven control flow
  • • Human-in-the-loop support

LangChain & LCEL

Use inside nodes for prompt composition, model calling, output parsing.

  • • Expressive prompt chaining
  • • Model abstraction (OpenAI, Anthropic)
  • • Output parsers & structured extraction
  • • Tool integration

Observability:

Langfuse for traces, LangSmith for debugging, custom dashboards

State Storage:

In-memory (dev), PostgreSQL (prod), Redis for caching

Quick Start Example

Basic Agent Structure:

from langgraph.graph import StateGraph, END
from langchain_core.prompts import ChatPromptTemplate
from langchain_openai import ChatOpenAI

# Define state
class AgentState(TypedDict):
    messages: list
    plan: str | None
    observations: list

# Create graph
workflow = StateGraph(AgentState)

# Add nodes (use LCEL inside)
def planner_node(state: AgentState):
    prompt = ChatPromptTemplate.from_template("{input}")
    llm = ChatOpenAI()
    chain = prompt | llm
    plan = chain.invoke({"input": state["messages"][-1]})
    return {"plan": plan.content}

workflow.add_node("planner", planner_node)
workflow.add_edge("planner", END)
workflow.set_entry_point("planner")

# Compile and run
app = workflow.compile()

This is a minimal example. In production, add more nodes, conditional edges, error handling, and state checkpointing.

Go deeper with the course

Master AI evals with hands-on projects, real case studies, and production-ready templates. From failure taxonomy to CI/CD quality gates.

Join the Course