news 2026/8/31 7:06:40

LangGraph实战指南:用状态图编排可控的Agent流程

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
LangGraph实战指南:用状态图编排可控的Agent流程

LangGraph不是又一个模型调用库,它是把Agent应用流程画成状态图、再按图执行的编排框架。简单说,过去你用普通Python函数一步步把LLM、工具、文本处理串起来,现在你把每个处理步骤拆成“节点”,用“边”控制它们怎么流转,包括分支、循环、并行和子流程。这套思路适合已经写过几轮LLM调用、开始觉得代码难以维护的人,也适合想把RAG、工具调用、多轮记忆整合到一个可控流程里的开发者。最值得先了解的不是它有哪些API,而是它背后的状态机设计:每个节点只做一件事,状态集中管理,分支和循环都变成图上的显式路线。

下面按“先搞清关系→搭最小环境→吃透核心机制→跑一个能落地的Agent→排查问题→梳理学习路径”的顺序拆一遍。内容偏工程实践,不会只讲概念。

1. 先搞清楚LangGraph在LangChain生态里解决什么问题

1.1 LangChain和LangGraph的分工不同

LangChain本质上是一个组件集合,封装了模型调用、Prompt模板、输出解析、向量数据库、文档加载、工具调用这些高频动作。LangGraph则往上走了一层,它关心的是“这些组件按什么顺序执行、在什么条件下跳转、中间状态怎么保存”。可以这样理解:LangChain负责把单个零件做好,LangGraph负责把整条流水线装配起来。

很多人会问LangChain是不是过时了。这个问题其实不太准。LangChain作为组件库依然有用,很多LangGraph节点内部还是会用到LangChain的模型封装和消息结构。LangGraph并不是替代LangChain,而是在LangChain之上或旁边提供流程编排能力。如果你的项目只是单次问答,用LangChain链就够了;一旦出现多轮工具调用、条件分支、退出循环,直接写链式代码会越来越难维护,这时候才需要LangGraph。

1.2 LangGraph的能力边界:它不负责模型,只负责流程

LangGraph本身不会替你调用大模型,也不会决定用哪个模型。它提供的是状态管理和执行引擎。所谓状态,就是一个被图里所有节点共享的字典对象。每个节点读取当前状态,计算后返回需要更新的字段,LangGraph再把更新合并回状态里,然后根据边决定下一步执行哪个节点。

这意味着图里的节点可以是任意函数,里面可以做LLM调用、普通计算、数据库查询、HTTP请求、文件读写、工具调用。LangGraph只保证执行顺序和状态一致,不限制你在节点里做什么。这点很重要。很多人一开始以为LangGraph会自带Agent决策能力,实际上它只提供“框架”,真正让Agent聪明的还是模型、Prompt、工具和你的流程设计。

1.3 MCP在中间扮演什么角色

MCP是一个开放协议,目标是让LLM应用能够以统一方式发现和调用外部工具、数据源。它解决的不是流程控制,而是工具接入标准化问题。一个MCP Server把某个工具封装成标准协议,Agent通过协议去调用,不必给每个工具单独写一套集成代码。

所以LangGraph和MCP不是二选一的关系。LangGraph里可以写一个节点,这个节点去调用某个MCP Server暴露的工具;也可以让LangChain工具管理器去封装MCP工具。真正的流程控制仍然在LangGraph的图里。了解这个关系之后,学习路径会清楚很多:先学图结构,再学怎么把外部能力接进节点。

2. 环境准备与最小LangGraph应用

2.1 建议的Python环境和依赖

先准备Python环境,常见要求是Python 3.10及以上。用虚拟环境跑比较省心,避免和系统Python混在一起。依赖方面至少需要langgraph,如果计划接入大模型,还需要对应的模型SDK,比如langchain-openai,或者直接用openai库。安装命令很简单:

pip install langgraph langchain-openai

如果你的机器网络下载慢,换成国内镜像源是常规操作。安装完成后,建议先跑一下版本确认:

python -c "import langgraph; print(langgraph.__version__)"

能正常输出版本号,说明环境基本可用了。后面如果代码里某个API找不到,先确认你安装的版本是否比较新,不要一上来就怀疑代码写错了。

2.2 最小案例:节点、State和图

LangGraph的核心API围绕三类对象:State、节点函数、图。

State用TypedDict定义,表示整个流程共享的数据结构。节点函数接收当前state,返回一个字段更新字典。图中通过add_node注册节点,通过add_edge定义节点之间的连线。下面是一个最简单可运行的例子:

from typing import TypedDict from langgraph.graph import StateGraph, START, END class State(TypedDict): input_text: str output_text: str def process_start(state: State) -> dict: return {"output_text": state["input_text"].upper()} # 创建图 graph = StateGraph(State) graph.add_node("process", process_start) # 连线 graph.add_edge(START, "process") graph.add_edge("process", END) # 编译 app = graph.compile() # 调用 result = app.invoke({"input_text": "hello langgraph"}) print(result)

这个例子做了三件事:定义状态、注册一个处理节点、让流程从START进入节点再结束。执行结果是一个字典,包含input_text和output_text两个字段。先跑通这个最小案例,后面加分支、循环和外部调用时才不会被状态更新问题干扰。

2.3 为什么先跑最小案例而不是直接上复杂Demo

很多人学LangGraph时,第一件事就是找一个带Agent、工具调用、向量检索的完整Demo来跑。这个思路能让你快速看到效果,但一旦报错,你很难判断是环境问题、状态字段问题、还是模型调用问题。

我更建议把第一次测试拆成三步:先确认环境,再跑最小案例,最后才往里面加模型和工具。最小案例的价值在于验证三件事:依赖能正常导入、图能正常编译、invoke能正常返回。只要这三件事成立,后续绝大部分问题都能定位在业务逻辑和参数上。实测中很多“为什么模型没被调用”“为什么分支没走对”的问题,最后都回到最基础的图结构和state字段上。

3. 核心机制:节点、条件路由、循环、子图与并行分支

3.1 节点函数怎么写更清晰

节点函数是LangGraph的基本执行单元。它接收当前state,返回需要更新的字段。这里有一个很容易踩的坑:返回的内容代表“对状态的更新”,而不是“完整的新状态”。你可以只返回要改的字段,LangGraph会做合并。

def call_model(state: State) -> dict: return {"messages": state["messages"] + ["model reply"]} def tool_node(state: State) -> dict: return {"messages": state["messages"] + ["tool result"]}

节点里不要写太多东西。一个节点只做一件事,比如“调用模型”“检索文档”“调用工具”“汇总结果”。因为LangGraph的优势就是让你用图的方式观察每个环节,节点里塞太多逻辑,图就退化成普通函数链了。

3.2 conditional_edge:条件路由怎么玩

条件路由是LangGraph最常见的进阶功能。它解决的问题是:下一步不一定固定,需要根据当前状态判断走哪个节点。实现方式是注册一个路由函数,这个函数读取state,返回某个节点名或节点key。

from typing import Literal def route_after_think(state: State) -> Literal["need_tool", "need_answer"]: if state.get("need_tool"): return "need_tool" return "need_answer" graph.add_conditional_edges( "think_node", route_after_think, { "need_tool": "tool_node", "need_answer": "final_node", }, )

这里第二参数是路由函数,第三参数是路由结果到节点名的映射。注意映射的key必须和路由函数返回的字符串完全一致,否则会报找不到节点。

条件路由的意义在于:它把if-else从代码里提出来,变成图上可见的一条判断边。调试时只要看状态里哪些字段影响路由函数,就能还原决策路径。很多教程里专门拆开讲conditional_edge,确实值得重点练一遍,因为它是Agent能否灵活决策的关键。

3.3 循环:Agent为什么能反复调用工具

循环是LangGraph区别于普通链式调用的关键能力。典型场景是Agent循环:模型判断需要调用工具→执行工具节点→回到模型节点继续判断→直到模型给出最终答案。用图表示,就是从某个节点画一条边回到前面的节点,形成一个环。

# 简单示意:工具节点执行完回到模型节点 graph.add_edge("tool_node", "model_node")

光有环还不够,必须考虑退出条件。否则模型一直判断“还需要工具”,流程就会卡死。LangGraph本身有递归深度限制。通过invoke参数可以传recursion_limit,也可以在自己维护的计数器中控制最大轮数:

result = app.invoke( {"input_text": "帮我查一下天气然后回答"}, config={"recursion_limit": 10} )

更稳妥的做法是在循环中维护一个步骤计数,达到上限后强制进入最终输出节点。这里不要急着调大递归上限,因为卡死通常不是上限不够,而是退出条件没有设计好。

3.4 子图、并行分支与状态合并

当流程越来越长,可以把一部分逻辑抽成子图。子图本质是一个可以被整体当作节点来执行的小图。适合用来封装“检索+生成”“多轮对话”这类可复用流程。LangGraph官方文档和不少示例都支持这种组合方式。

并行分支则适合“同时处理多个相对独立的子任务”。从同一个节点分出多条边到不同节点,这些节点会并行执行,最后再合并到一个节点。并行分支的坑在于状态合并。多个节点同时往state里同一个字段写值,可能出现互相覆盖或行为不确定。建议让不同并行分支更新不同字段,最后用一个合并节点汇总。

并行很诱人,但不要一开始就上。先跑单条任务,确认每个分支单独执行都正确,再验证并发下的状态合并。很多看似“功能不支持”的问题,实际上是并行分支之间在互相覆盖返回值。

3.5 核心参数与判断标准

在学习和调参阶段,我会关注这几个点:

  • recursion_limit:控制整条链路最多执行多少步,防止死循环。
  • 并发参数:不同后端可能有不同并发配置,先小并发验证。
  • checkpointer:是否保存会话状态,决定多轮对话是否记忆。
  • debug开关:是否输出详细日志。

判断流程图跑得对不对,不是只看最终结果。更有效的指标是:每个节点的输入输出是否符合预期、路由函数走到了哪条分支、循环结束在第几步、状态里最终保留了哪些字段。把这些观察点记录下来,排查问题会快很多。

4. 把一个真正可用的Agent跑起来:记忆、RAG、MCP

4.1 多轮对话记忆和checkpointer

LangGraph的state默认只在一次invoke内有效。要让多轮对话记住历史,需要给图配置checkpointer。checkpointer是LangGraph里用于保存和恢复状态快照的组件。本地学习时可以用内存型实现,进程一重启就没了;生产环境需要换成文件存储或数据库存储。

配置方式一般是在compile时传入checkpointer:

from langgraph.checkpoint.memory import MemorySaver checkpointer = MemorySaver() app = graph.compile(checkpointer=checkpointer) # 多轮调用时传入同一个thread_id app.invoke( {"input_text": "你好"}, config={"configurable": {"thread_id": "session-1"}} )

多轮对话的关键是thread_id。同一个thread_id下,后面调用能读到之前保存的状态。如果你没有传thread_id,每次调用会被当成新会话,记忆自然不生效。遇到“怎么没有记住刚才的话”时,第一时间检查的就是这个。

4.2 把RAG检索作为一个独立节点

RAG在LangGraph里可以很自然地拆成多个节点:用户输入→向量化→检索→组装上下文→生成回答。检索作为一个独立节点的好处是,你可以单独替换向量库、单独调试召回结果,甚至可以在检索后加一个“是否需要重新提问”的判断节点。

一个常见的误区是:把检索和生成写在一个节点里。短期看省事,但当你需要观察检索结果、调整Prompt、或者增加多轮检索时,就会后悔。LangGraph的价值就是让这些环节之间可以插入判断和循环,你只有把它们拆开,才能用上这种能力。

4.3 通过MCP接入外部工具

MCP的价值在工具数量多、工具类型杂的时候最明显。传统做法是给每个工具写一套专用调用代码,MCP把工具接入变成标准化握手:Agent通过MCP协议发现工具有哪些、看描述、用统一格式传参数、再接收结果。

在LangGraph图里,MCP工具通常不是图的顶层概念,而是被封装在一个工具调用节点里的执行能力。流程大概是:

  1. 在外部启动或配置一个MCP Server,它暴露工具的调用入口。
  2. 在LangGraph应用里配置MCP客户端,让Agent能发现工具。
  3. 在工具节点里根据模型返回的工具调用指令,执行具体工具。
  4. 把工具结果作为新消息写回state,回到模型节点继续判断。

这里的细节不少,但先把握住核心:MCP负责“工具怎么暴露、怎么调用”,LangGraph负责“什么时候调用、调用失败后怎么走、结果回到哪里”。两者结合,才能构成完整的Agent工具调用闭环。

4.4 MCP和Agent Skill到底有什么区别

这个问题热度很高。简单说,MCP解决的是工具接入的协议问题,是一个“接口层”;Skill(或者叫Agent Skill、技能包)解决的是任务执行模板问题,是一个“能力层”。

Skill通常包含:这个技能适用什么场景、需要哪些提示词、固定流程是什么、可能调用哪些工具、输出怎么整理。它关注的是“怎么把一个复杂任务拆成步骤并稳定复现”。MCP Server只是这个流程里可被调用的其中一个工具来源。两者可以配合:Skill定义任务怎么做,MCP Server提供Task里需要的工具。

如果一个人只装了MCP Server,但没有定义任何Skill,模型仍然可以按工具调用的方式去用它;如果一个人只写Skill,不通过MCP接入工具,他用普通函数调用也能实现。所以它们不是同一个层级的东西,不要混为一谈。

4.5 怎么验证Agent真的可用

一个Agent项目能跑起来,不代表可用。我建议用一组验收用例来判断:

  • 普通问答:不调用工具,能否直接回答。
  • 工具调用:问题需要查数据,能否正确选择工具并传参。
  • 多轮对话:前一轮结果是否影响下一轮。
  • 失败处理:工具返回错误或超时,流程能否降级。
  • 长流程:超过10步时,是否稳定、是否出现状态漂移。

验收时不只看最终答案,还要看日志和中间状态。把这组用例跑完,基本就知道这个Agent离“能交付”还差多远。

5. 开发调试与排查链路

5.1 观察图的执行过程

LangGraph给了状态、节点、边这些概念,调试时就要用好它们。最简单的做法是在节点函数里打印当前state的关键字段,或者把中间结果写入日志。如果图比较复杂,可以输出图的Mermaid结构,直观确认边的走向。还有不少项目会接入可观测性工具,把每次调用的节点执行序列和token消耗记录下来,适合后期做性能分析。

学习阶段不用追求完整链路,至少保证两点:能看每个节点的输入输出,能看路由函数实际返回了哪个分支。有了这两点,绝大多数流程问题都能定位。

5.2 常见报错和排查顺序

我把LangGraph初学者最容易遇到的问题整理成一张表:

现象优先排查点补充建议
启动或导入报错Python版本、依赖版本、安装环境用虚拟环境重装依赖,确认langgraph版本
invoke后没有任何输出图是否编译成功、输入state字段是否齐全先跑最小案例,排除环境问题
报找不到节点节点名拼写、conditional_edges映射key是否一致用映射字典比对函数返回值
分支没走预期路线路由函数读取的字段是否被更新在路由函数里打印state
模型调用失败API key、模型名、上下文长度、网络先单独测试模型SDK调用
流程长时间不结束退出条件、recursion_limit把递归上限调小,先暴露问题
工具没有被调用工具描述是否清晰、参数Schema是否匹配用最简工具先验证
并行结果丢失多个分支写同一个state字段给每个分支独立字段,最后合并

排查顺序我一般是这样:先看现象,再看输入,再看日志,再看代码逻辑,最后才怀疑框架本身。很多时候看起来像是框架的问题,实际是state字段没传对、路由key写错或者模型返回格式不符合预期。

5.3 从Demo到生产要注意的边界

本地Demo跑通之后,直接拿去生产会遇到另外一层问题:

  • 持久化:内存型checkpointer不能用于生产,需要换数据库或对象存储。
  • 超时:模型、HTTP工具、长流程都可能有超时,需要单独设置。
  • 重试:工具调用失败后的重试策略要明确,否则会出现重复写入。
  • 并发:批量和多用户并发时,资源占用会明显上升,先压测。
  • 日志:要有能追踪单次完整链路的结构化日志。

这些不是LangGraph本身能帮你解决的,需要在使用它的应用层去设计。如果只是学习和实验,内存方式完全够用;如果是上线服务,这些问题必须在第一天就想清楚。

6. 学习路线:从入门到能自己画流程

6.1 分阶段突破

LangGraph学起来最忌讳一上来就啃全部概念。我建议按下面顺序推进:

  1. 最小案例:理解state、节点、边、invoke。
  2. 条件路由:用一个二选一分支练手。
  3. 循环:实现一个简化版Agent,让模型决定是否调用工具。
  4. 子图和并行:把检索、生成拆成子流程。
  5. 加记忆:用checkpointer实现多轮对话。
  6. 接真实工具:从普通HTTP接口开始,再到MCP Server。

每一步都保留一个可运行的最小项目,不要急着把所有功能堆在一起。我见过不少人一天之内把所有Demo都跑了一遍,但换一个新需求仍然不会设计图结构,就是因为缺少分阶段的独立思考。

6.2 常见误区

第一个误区是把LangGraph当成普通流水线,把所有节点都设计成“从上往下执行一次”。这样你用不到条件路由和循环,也无法体现LangGraph的价值。设计图之前,先想清楚你的业务有没有分支节点、有没有需要反复执行的环节、有没有需要并行的子任务。

第二个误区是混淆了流程和工具接入。MCP能解决工具接入标准化,但它不能替你设计Agent的决策链。LangGraph是编排引擎,MCP是工具来源之一,LangChain是组件库,三者的边界要先分清。

第三个误区是报错后乱改参数。例如循环卡住,第一反应是调大recursion_limit;内容不对,第一反应是换模型。实际上大部分问题要回到state、路由和工具返回格式上排查。先把日志和状态输出打开,再决定改哪里。

6.3 接下来研究什么

如果前面这些都已经掌握,可以继续往这几个方向深入:

  • 多Agent协作:多个图或子图之间如何通信、如何分派任务。
  • 人工确认环节:在关键节点插入人工审批,适合生产流程。
  • 结构化输出:让模型返回规范JSON,并和state字段绑定。
  • 流式输出:面向交互场景,逐步返回模型生成结果。
  • 可观测性:把节点执行序列、耗时、token消耗统一记录下来。

这些方向在官方文档和社区示例里都有对应场景。学习时不要只盯着新的API,更要理解每个模式是为了解决什么业务问题。LangGraph本身就是一个流程设计的表达工具,能力上限取决于你对业务的分拆能力和对状态流转的理解。

我个人的建议是,不管你看的是哪种形式的教程,最后一定要自己动手画一张跟你业务相关的流程图出来。画不出来,就说明还没真正掌握。LangGraph最值得投入的时间,不在API记忆上,而在“把模糊需求拆成图结构”这件事上。先跑通单节点,再一步一步加条件、加循环、加记忆、加工具,这个过程本身就是最快速的入门路线。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/8/31 7:06:02

Congestion Control System Optimization with Large Language Models

论文《Congestion Control System Optimization with Large Language Models》总结与翻译 一、文章主要内容总结 本文聚焦互联网基础设施中的拥塞控制算法优化问题,提出一种基于大型语言模型(LLMs)自动优化拥塞控制算法的新框架,核心内容如下: 研究背景与挑战:拥塞控制…

作者头像 李华
网站建设 2026/8/31 7:05:59

途虎养车秋招数据分析笔试题解析:业务驱动型考察要点

途虎养车2023秋招数据分析笔试试卷A,我拿到这份卷子是在去年秋招的时候。当时在牛客网上刷到有人分享,顺手存下来做了一套,说实话做完之后感触挺深的。它不是那种大厂通用算法题堆砌出来的卷子,而是明显的业务驱动型出题思路&…

作者头像 李华
网站建设 2026/8/31 7:00:58

第304篇 PPO——最流行的强化学习算法

上篇聊了Actor-Critic框架和各种变体。如果你只能学一个强化学习算法,那一定是PPO(Proximal Policy Optimization,近端策略优化)。它是OpenAI在2017年提出的,现在几乎是RL领域的默认选择——不管是学术研究还是工业应用…

作者头像 李华
网站建设 2026/8/31 7:00:57

2026深度学习框架选型:TensorFlow与PyTorch对比及PyTorch实战

距离我第一次在 CSDN 上写深度学习入门文章,已经过去好几年了。但直到今天,私信里最频繁的问题依然是:“我准备入门深度学习,到底选 TensorFlow 还是 PyTorch?”到了 2026 年,这个问题依然没有被完美解决&a…

作者头像 李华
网站建设 2026/8/31 7:00:12

企业/商户报表统计体系分类体系英文-东方仙盟

本体系用于经营报表、告警提醒、待办优先级统计;不依赖金额、不以收付为核心,只对「事件本身」做归类、方向属性、紧急重要等级划分。 字段说明: event_direction 事件方向:大类枚举:正向|负向&#xff5c…

作者头像 李华
网站建设 2026/8/31 6:55:31

反射内存卡技术解析:从5565系列看微秒级实时同步的实现

多台设备联调,最怕的不是功能不跑,而是时间不同步。做硬件在环仿真时,我曾经遇过这样的情况:一个分布式实时系统由四台工控机组成,每台机器跑一段物理模型,通过千兆以太网交换数据。实验室里单机跑起来一切…

作者头像 李华