LangGraph框架:StateGraph-Node-Edge-Checkpoint


一句话:** LangGraph 是把 Agent 工作流建模成有向图的框架——StateGraph 定义图结构,Node 是处理步骤,Edge 是连接关系,Checkpoint 在每个节点后自动存档。底层是图论,上层是Agent 编排


一、先搞清楚:为什么需要 LangGraph?

你已经用 LangChain 写出了 prompt | model | parser 的管道。管道是线性的——数据从左流到右,一条路走到底。

但 Agent 不是线性的:

 
用户问"帮我查订单" →
 
  LLM 判断:需要先查数据库 →
 
    查到结果了 → 生成回答 →
 
    没查到 → 换一个查询方式重新查 →
 
      还是没查到 → 告诉用户"查不到"
 

这是一棵决策树,不是一条管道。LangGraph 用**图(Graph)**来建模这种分支和循环。


flowchart LR

    subgraph 管道["LangChain LCEL 管道"]

        A1["Prompt"] --> A2["Model"] --> A3["Parser"]

    end

    subgraph 图["LangGraph StateGraph"]

        B1["Node A<br/>LLM决策"] -->|"需要工具"| B2["Node B<br/>执行工具"]

        B2 --> B1

        B1 -->|"直接回答"| B3["Node C<br/>生成最终回答"]

    end

管道是单向线,图可以有循环和分支。这就是 LangGraph 存在的理由。


二、四个核心概念

2.1 State(状态)—— 所有节点共享的”黑板”

 
from typing import TypedDict, Annotated
 
from langgraph.graph.message import add_messages
 
class AgentState(TypedDict):
 
    """
 
    State 是贯穿所有节点共享的 TypedDict。
 
    每个节点读取它、修改它,传给下一个节点。
 
    """
 
    messages: Annotated[list, add_messages]  # 对话历史(自动追加)
 
    next_action: str                          # 下一步做什么
 
    tool_results: list[dict]                  # 工具调用结果
 
    final_answer: str                         # 最终回答
 

大白话: State 就像手术室里挂在墙上的白板——每个医生(Node)进来看一眼、写上自己的发现、传给下一个医生。所有医生看的是同一块板。

2.2 Node(节点)—— 一个处理步骤

每个 Node 是一个 Python 函数,签名为:

 
def my_node(state: AgentState) -> dict:
 
    """接收 State,返回要更新的字段(partial State)。"""
 
    # 处理逻辑
 
    return {"next_action": "call_tool"}  # 只更新 next_action 字段
 

Node 可以是:

Node 类型做什么例子
LLM 调用让模型做决策判断用户意图、生成回答
工具执行调外部 API / 数据库查天气、查订单
条件判断纯逻辑分支检查结果是否为空
人工介入暂停等审批退款确认

2.3 Edge(边)—— 节点之间的连线

两种 Edge:


flowchart LR

    subgraph 普通边["普通边(Direct Edge)"]

        N1["Node A"] -->|"固定 →"| N2["Node B"]

    end

    subgraph 条件边["条件边(Conditional Edge)"]

        N3["Node A"] -->|"路由函数"| D{"判断"}

        D -->|"条件1"| N4["Node B"]

        D -->|"条件2"| N5["Node C"]

    end

  • 普通边:A 执行完,一定去 B(固定路线)

  • 条件边:A 执行完,由路由函数决定去 B 还是 C(LLM 说了算)

2.4 Checkpoint(检查点)—— 每步存档

LangGraph 在每个 Node 执行后自动保存 State 快照。这就是 Checkpoint。

 
Node A 执行前: State v1
 
Node A 执行后: State v2 → Checkpoint(自动保存)
 
Node B 执行前: State v2
 
Node B 执行后: State v3 → Checkpoint(自动保存)
 

用途: 调试(回溯每一步的状态)、断点续传(从某个 checkpoint 恢复)、人在回路(暂停→审查→继续)。


三、完整的 StateGraph 代码示例

一个带条件边的 3 节点 Agent:

 
"""
 
用 LangGraph 搭建一个简单 Agent:
 
用户提问 → LLM 决定是否需要工具 → 需要则调工具 → 生成最终回答
 
"""
 
import os
 
from typing import TypedDict, Annotated, Literal
 
from langgraph.graph import StateGraph, END
 
from langgraph.graph.message import add_messages
 
from langchain_openai import ChatOpenAI
 
# ── 第1步:定义 State ──
 
class AgentState(TypedDict):
 
    """所有节点共享的状态对象。"""
 
    messages: Annotated[list, add_messages]  # add_messages = 自动追加而非覆盖
 
    next_step: str                            # 路由依据:LLM 的输出
 
# ── 第2步:定义三个 Node ──
 
def router_node(state: AgentState) -> dict:
 
    """
 
    Node 1:LLM 决策节点。
 
    让 LLM 判断下一步该做什么——调工具还是直接回答。
 
    """
 
    model = ChatOpenAI(
 
        api_key=os.environ["DEEPSEEK_API_KEY"],
 
        base_url="https://api.deepseek.com",
 
        model="deepseek-v4-pro",
 
        temperature=0.0,
 
    )
 
    # 这里的 prompt 是简化版,生产环境应包含工具描述
 
    response = model.invoke([
 
        {"role": "system", "content": (
 
            "你是 Agent 路由器。根据用户输入决定下一步:\n"
 
            "- 需要查外部信息 → 输出 'tool'\n"
 
            "- 可以直接回答 → 输出 'answer'"
 
        )},
 
        {"role": "user", "content": state["messages"][-1].content},
 
    ])
 
    decision = response.content.strip().lower()
 
    return {"next_step": decision}
 
def tool_node(state: AgentState) -> dict:
 
    """
 
    Node 2:工具执行节点。
 
    实际项目中这里会调 MCP tool / API / 数据库。
 
    这里用模拟数据演示。
 
    """
 
    user_query = state["messages"][-1].content
 
    # 模拟工具调用
 
    tool_result = f"[工具返回] 查询 '{user_query}' 的结果:北京今天晴天,25°C"
 
    return {"messages": [{"role": "system", "content": tool_result}]}
 
def answer_node(state: AgentState) -> dict:
 
    """
 
    Node 3:回答生成节点。
 
    基于所有上下文生成最终回答。
 
    """
 
    model = ChatOpenAI(
 
        api_key=os.environ["DEEPSEEK_API_KEY"],
 
        base_url="https://api.deepseek.com",
 
        model="deepseek-v4-pro",
 
        temperature=0.7,
 
    )
 
    response = model.invoke([
 
        {"role": "system", "content": "基于对话中的所有信息,给用户一个简洁的最终回答。"},
 
        *state["messages"],
 
    ])
 
    return {"messages": [response]}
 
# ── 第3步:定义条件边的路由函数 ──
 
def route_decision(state: AgentState) -> Literal["tool", "answer"]:
 
    """
 
    条件边路由函数:检查 State 中的 next_step 字段,
 
    返回下一个 Node 的名字。
 
    """
 
    if state["next_step"] == "tool":
 
        return "tool"
 
    return "answer"
 
# ── 第4步:组装 StateGraph ──
 
builder = StateGraph(AgentState)
 
# 注册节点
 
builder.add_node("router", router_node)    # Node 1: LLM 决策
 
builder.add_node("tool", tool_node)        # Node 2: 工具执行
 
builder.add_node("answer", answer_node)    # Node 3: 生成回答
 
# 设置入口
 
builder.set_entry_point("router")
 
# 添加条件边:router 节点执行后,根据 route_decision 的结果走不同分支
 
builder.add_conditional_edges(
 
    "router",           # 从哪个节点出发
 
    route_decision,     # 路由函数(返回目标节点名)
 
    {
 
        "tool": "tool",     # 返回 "tool" → 去 tool 节点
 
        "answer": "answer", # 返回 "answer" → 去 answer 节点
 
    },
 
)
 
# 添加普通边:tool 执行完 → 回到 router 重新决策(实现循环)
 
builder.add_edge("tool", "router")
 
# 添加普通边:answer 执行完 → 结束
 
builder.add_edge("answer", END)
 
# 编译图
 
graph = builder.compile()
 
# ── 第5步:运行 ──
 
if __name__ == "__main__":
 
    from langchain_core.messages import HumanMessage
 
    result = graph.invoke({
 
        "messages": [HumanMessage(content="北京今天天气怎么样?")],
 
        "next_step": "",
 
    })
 
    # 打印最终回答
 
    print(result["messages"][-1].content)
 

四、图结构可视化

上面代码构建出的 Graph 长这样:


flowchart TD

    START((START)) --> R["router<br/>LLM决策节点"]

    R -->|"route_decision()"| D{"条件判断"}

    D -->|"next_step == 'tool'"| T["tool<br/>工具执行节点"]

    D -->|"next_step == 'answer'"| A["answer<br/>生成回答节点"]

    T -->|"普通边:回到决策"| R

    A --> END((END))

关键点:

  • 循环tool → router 形成了 Agent 的核心循环(ReAct 模式)

  • 条件边router 后的分支完全由 LLM 输出决定

  • 终止answer → END 是唯一的出口


五、StateGraph vs 手写循环

对比维度手写 while 循环LangGraph StateGraph
流程可视化要在脑子里推演图结构一目了然
状态追踪手动 print 调试Checkpoint 自动存档每步
人在回路要自己写暂停/恢复interrupt() 一行搞定
并行节点要自己管理 asyncioSend() API 原生支持
流式输出要自己管理 yieldgraph.astream() 内置
进阶亮点基础能力工程化能力

LangGraph 不是"封装了 while 循环",而是在 while 循环之上加了 可观测性、可恢复性、可编排性——这些都是生产级 Agent 必须的。


六、Checkpoint 机制预览

(详见 下一篇

 
# 开启 Checkpoint 只需一行
 
from langgraph.checkpoint.memory import MemorySaver
 
graph = builder.compile(checkpointer=MemorySaver())
 
# 每次调用带上 thread_id,自动隔离会话
 
result = graph.invoke(
 
    {"messages": [HumanMessage(content="你好")]},
 
    config={"configurable": {"thread_id": "user-123"}},
 
)
 
# ↑ 执行过程中每个节点执行后,State 自动保存到 MemorySaver
 

速记卡(面试闪卡)

Q1:一句话讲清「LangGraph框架:StateGraph-Node-Edge-Checkpoint」到底是什么?

A:LangGraph 把 Agent 工作流建模成有向图:StateGraph 定结构、Node 是步骤、Edge 连线、Checkpoint 每步存档。

Q2:为什么不用管道 —— 怎么理解?

A:像 LangChain 管道是单行道,数据从左到右一条路走到底;但 Agent 是决策树(查到→生成,查不到→换方式重查)。图才有循环和分支,这正是 LangGraph 存在的理由。

Q3:四个核心概念 —— 怎么理解?

A:State 像手术室白板,所有 Node 共享同一块板读取改写;Node 是处理步骤(LLM / 工具 / 判断 / 人工);Edge 分普通边(固定)和条件边(路由函数决定);Checkpoint 每步后自动存档。

Q4:循环与终止 —— 怎么理解?

A:像地铁环线:tool→router 形成 ReAct 核心循环,条件边分支由 LLM 输出决定,answer→END 是唯一出口。Checkpoint 让调试能回溯、断点能续传、人能中途审查。

Q5:比手写循环强在哪 —— 怎么理解?

A:像给裸 while 循环加了仪表盘。LangGraph 之上多了可观测性(Checkpoint 自动存档)、可恢复性(interrupt 一行暂停)、可编排性(Send 并行、astream 流式)。

Q6:核心速记主线有哪些?

  • 图 vs 管道:支持循环与分支

  • State 共享白板,Node 步骤,Edge 连线

  • 条件边路由 + tool→router 循环

  • Checkpoint 自动存档:调试 / 续传 / 人审

口诀

A:LangGraph 建模图,状态白板节点步

普通条件两条边,循环回 router 转

Checkpoint 每步存,调试续传人审看

胜过裸 while,可观测可恢复

相关链接


技术学习路线图 > LangChain + LangGraph