Chapter 01

为什么需要 LangGraph:LLM 工作流的状态图思维

当 Agent 需要循环、分支、回溯、持久化,"一条 Chain 跑到底"就撑不住了。LangGraph 把工作流画成有向图,让复杂 Agent 变得可观测、可回放、可组合。

从 Chain 到 Graph:线性思维的终点

最早我们都是这么写 LLM 应用的:

# 经典 Chain: input → prompt → LLM → parser → output
from langchain_core.prompts import ChatPromptTemplate
from langchain_openai import ChatOpenAI

chain = ChatPromptTemplate.from_template("回答:{q}") | ChatOpenAI()
answer = chain.invoke({"q": "法国首都?"})

但凡你的应用需要做下面任意一件事,Chain 就开始出问题:

这些需求的共同特征:需要状态、需要控制流、需要"图"而非"链"

LangGraph 的定位
LangGraph 是 LangChain 团队推出的、专门处理"有状态 LLM 工作流"的低层库。它不替代 LangChain,而是解决 Chain 搞不定的图拓扑问题。学完你会发现,连 OpenAI Agents SDK、CrewAI 底层的核心思想都与它相通。

一个直观对比:ReAct Agent

同样实现"LLM 决定要不要调工具"的循环,看两种写法:

Chain 风格(难看、难维护)

def run_agent(query, max_steps=5):
    messages = [{"role": "user", "content": query}]
    for _ in range(max_steps):
        rsp = llm.invoke(messages, tools=TOOLS)
        messages.append(rsp)
        if not rsp.tool_calls:
            return rsp.content
        for call in rsp.tool_calls:
            result = run_tool(call)
            messages.append({"role": "tool", "content": result})
    return "超出步数限制"

看起来能跑,但问题是:

LangGraph 风格(声明式、可组合)

from langgraph.graph import StateGraph, START, END
from langgraph.prebuilt import ToolNode, tools_condition
from typing import TypedDict, Annotated
from langgraph.graph.message import add_messages

class State(TypedDict):
    messages: Annotated[list, add_messages]

def call_llm(state):
    return {"messages": [llm.invoke(state["messages"], tools=TOOLS)]}

g = StateGraph(State)
g.add_node("llm", call_llm)
g.add_node("tools", ToolNode(TOOLS))
g.add_edge(START, "llm")
g.add_conditional_edges("llm", tools_condition)   # 有 tool_call → tools, 否则 END
g.add_edge("tools", "llm")                        # 工具返回后回到 LLM

app = g.compile()

同样的 Agent,LangGraph 版给你免费送了:

图结构的心智模型

LangGraph 的核心 3 个概念,就这么点:

State(状态)
整张图共享的可变数据。通常是 TypedDict,描述"目前为止 Agent 知道什么"。每个节点读 state、返回对 state 的 增量更新
Node(节点)
一个函数:接收 state,返回 dict(要更新的字段)。可以是 LLM 调用、工具调用、业务逻辑、人工审批等。
Edge(边)
节点之间的跳转规则。有静态边(A→B 无条件)和条件边(根据 state 决定去哪)。START 和 END 是两个特殊节点。

可视化:ReAct Agent 的图

┌───────┐ │ START │ └───┬───┘ ▼ ┌───────┐ tool_calls 非空 │ llm │─────────────────────┐ └───┬───┘ ▼ │ tool_calls 为空 ┌───────┐ ▼ │ tools │ ┌───────┐ └───┬───┘ │ END │◀─────────────────────┘ └───────┘ (返回 llm)

LangGraph 解决的 6 个真实痛点

痛点Chain 方案LangGraph 方案
多轮对话续上下文手工传 history listCheckpointer + thread_id 自动持久化
Agent 走到一半被打断从头重跑从最近 checkpoint 恢复
某些步骤需审批改代码加 input()interrupt_before,前端能实现审批 UI
多 Agent 协作硬编码 routerSubgraph + Supervisor,可组合
复盘失败 case搞不清楚哪一步错get_state_history 完整回放
流式输出中间步骤每个 chain 自己 streamstream_mode=updates 天然支持

什么时候不要用 LangGraph

别过度设计 如果你的应用就是单次"prompt → LLM → 输出",用 LangGraph 是杀鸡用牛刀。判断标准:
✅ 有循环 / 分支 / 回溯 / 审批 / 多 Agent / 持久化中任何一个需求 → 上 LangGraph
❌ 只是个一次性的文本生成或分类 → 直接 LangChain 或原生 SDK 就够

学习路径

  1. Chapter 2:写出你的第一个 graph,理解 State/Node/Edge 三件套
  2. Chapter 3:条件路由与循环,让图能"思考"
  3. Chapter 4:ReAct Agent,工具调用标准模式
  4. Chapter 5-6:持久化与人工介入,生产化必修
  5. Chapter 7-8:流式与 Multi-Agent,复杂场景
  6. Chapter 9-10:可观测性 + 端到端落地

环境准备

pip install -U langgraph langchain langchain-openai
# 可选(推荐): LangSmith 观测
export LANGSMITH_TRACING=true
export LANGSMITH_API_KEY=ls_...
export OPENAI_API_KEY=sk_...

本书的代码在 LangGraph 0.2+ 和 Python 3.10+ 下验证通过。

本章小结