LangGraph 入门:StateGraph、条件路由与 Agent 的工具调用循环

文章来源声明: 原文作者:flash俊杰; 来源站点:掘金; 原文链接:https://juejin.cn/post/7688988203789467648; 本文基于上述来源整理/加工,觅优补充点评,仅供技术学习交流。版权归原作者所有。
觅优短评

适合已会用 Chain、想搞懂 Agent 运行时的开发者:三张图手写一遍,比直接调 create_agent 更能建立状态机直觉,升级 1.x 时也少踩持久化与归并语义的坑。

LangGraph 入门:StateGraph、条件路由与 Agent 的工具调用循环 -------------------------------------------

脱敏说明:本文为框架教学项目的知识点总结,所有模型名称均以 OpenAI 兼容协议的通用写法呈现,不绑定任何厂商。

一、为什么 Chain 不够,需要 Graph

链式调用(prompt → model → parser)只能表达"一条直线"。但 Agent 的真实运行路径是环形且带分支的:模型可能直接回答,也可能要求调工具,调完工具还要回到模型,是否结束取决于模型上一轮的输出。下一步走哪条边,是运行时根据状态决定的——这正是图编排框架解决的问题。

LangGraph 的三个核心抽象:

  • State:贯穿全图的共享状态(通常是一个带类型的字典)
  • Node:接收 state、返回 state 更新片段的普通函数
  • Edge:固定边,或根据 state 动态决定下一个节点的条件边

二、最小 StateGraph

<span>from</span> typing <span>import</span> TypedDict
<span>from</span> langgraph.graph <span>import</span> StateGraph, START, END

<span>class</span> <span>State</span>(<span>TypedDict</span>):
    question: <span>str</span>
    answer: <span>str</span>

<span>def</span> <span>generate</span>(<span>state: State</span>):
    <span>return</span> {<span>"answer"</span>: llm.invoke(state[<span>"question"</span>])}

graph_builder = StateGraph(State)
graph_builder.add_node(<span>"generate"</span>, generate)
graph_builder.add_edge(START, <span>"generate"</span>)
graph_builder.add_edge(<span>"generate"</span>, END)

graph = graph_builder.<span>compile</span>()
result = graph.invoke({<span>"question"</span>: <span>"解释一下什么是向量检索"</span>})

注意节点函数的返回值是状态更新片段,框架负责把它合并进全局 state——节点不直接改写整个状态,这保证了多节点协作时的状态一致性。

三、条件路由:让 Agent 形成工具调用环

Agent 的标准结构是"模型节点 ↔ 工具节点"的循环,由条件边判断出口:

<span>from</span> langgraph.graph <span>import</span> MessagesState
<span>from</span> langgraph.prebuilt <span>import</span> ToolNode

tools = [search_tool, calculator_tool]
llm_with_tools = llm.bind_tools(tools)

<span>def</span> <span>llm_call</span>(<span>state: MessagesState</span>):
    <span>return</span> {<span>"messages"</span>: [llm_with_tools.invoke(state[<span>"messages"</span>])]}

<span>def</span> <span>should_continue</span>(<span>state: MessagesState</span>):
    last_message = state[<span>"messages"</span>][-<span>1</span>]
    <span># 模型这一轮请求了工具 → 去工具节点;否则 → 结束</span>
    <span>if</span> last_message.tool_calls:
        <span>return</span> <span>"tools"</span>
    <span>return</span> END

builder = StateGraph(MessagesState)
builder.add_node(<span>"llm_call"</span>, llm_call)
builder.add_node(<span>"tools"</span>, ToolNode(tools))
builder.add_edge(START, <span>"llm_call"</span>)
builder.add_conditional_edges(<span>"llm_call"</span>, should_continue, [<span>"tools"</span>, END])
builder.add_edge(<span>"tools"</span>, <span>"llm_call"</span>)   <span># 工具执行完回到模型,形成环</span>
agent = builder.<span>compile</span>()

这张图就是 Agent 运行时最本质的样子:

START → llm_call ──(有 tool_calls)──► tools ──► llm_call (循环)
                  └────(无 tool_calls)──────────────────► END

bind_tools 把工具的 JSON Schema 绑定给模型,模型据此输出结构化的工具调用请求;工具节点执行后,结果以工具消息追加回消息列表。条件路由函数是唯一的"交通指挥员",它只读取状态、不产生副作用。

四、消息状态与归并语义

直接用 TypedDict 时一个字段会被新值覆盖;而消息列表需要的是追加语义。框架提供的消息状态内置了归并器(reducer):每次节点返回新消息,框架自动 append 而不是覆盖。自定义状态也可以声明归并函数,例如用 Annotated[list, add] 表达"这个字段做累加"。理解 reducer,是理解"状态如何在节点间流转"的关键。

五、中断恢复:状态机天然支持审批

在图里插入人工审批节点不需要新机制,就是一个条件边 + checkpoint:

builder.add_node(<span>"wait_approval"</span>, <span>lambda</span> s: interrupt(s[<span>"task"</span>]))
builder.add_conditional_edges(
    <span>"process_task"</span>,
    <span>lambda</span> s: <span>"wait_approval"</span> <span>if</span> s.get(<span>"need_approval"</span>) <span>else</span> END,
)
builder.add_edge(<span>"wait_approval"</span>, <span>"after_approval"</span>)

graph = builder.<span>compile</span>(checkpointer=PostgresSaver(...))

编译时挂上 checkpointer,每个超步执行完自动存快照;恢复时用 Command(resume=...) 从断点继续。状态机 + checkpoint 的组合让"暂停—审批—恢复"成为框架能力,而不是业务代码(上一篇已详述)。

六、调试与可视化

编译后的图可以直接输出结构图(graph.get_graph().draw_mermaid()),对教学和 Code Review 极其友好——流程对不对、环在哪里,一眼可见。配合 checkpointer,可以按 thread_id 逐步回放历史状态,排查"Agent 为什么走了这条路"。

七、技术演进与最新差异(2025—2026)

  1. LangGraph 1.0 已 GA(2025-10-22),且是 LTS 版本。 API 在 1.x 全系列保持稳定,小版本升级无破坏性变更。项目教学脚本若基于 0.x 编写,升级时主要注意导入路径和部分预构建组件的位置调整。
  2. 持久化执行成为核心卖点。 早期 LangGraph 主要被当作"图编排库";1.0 之后定位升级为持久化 Agent 运行时——每步 checkpoint、任务级 pending write 持久化,崩溃与部署中断后精确续跑。新项目设计时应从一开始就接入 checkpointer,而不是事后补。
  3. create_agent 成为更高层标准。 LangChain 1.0(2025-10 GA)提供的 create_agent 底层就是本文这张图,但把"模型—工具循环"封装为开箱即用,并支持中间件。需要标准 Agent 时直接用 create_agent;需要自定义拓扑(子图、多 Agent、专门审批流)时才手搭 StateGraph——两者是上下层关系,不是替代关系。
  4. 生态信号。 选型时注意,部分 2024 年流行的多 Agent 框架已进入维护模式(官方 2025 年 10 月公告),新用户被引导迁移;图式工作流模型已成为业界事实标准。

八、小结

LangGraph 的心智模型就一句话:状态在节点间流动,边决定下一站,条件边让分支运行时生效。必练的三张图:最小直线图、"模型—工具"循环图、带中断的审批图。把这三张图手写一遍,再去用高层 create_agent,你对 Agent 的理解会从"调库"升级为"看得懂运行时"。