
LangGraph 是 LangChain 生态里用来编排 AI Agent 工作流的框架。很多做大模型应用开发的人一开始最容易卡住的不是 Prompt 怎么写而是多条任务之间怎么流转、工具调用怎么循环、失败怎么重试、状态怎么保存。LangGraph 的核心思路就是用图结构把这些流程固化下来让 AI 大模型应用从“一问一答”变成可控制的工程系统。这篇文章按实际动手顺序来写先理清 LangGraph 和 LangChain 的关系再跑通最小样例然后拆 Agent 状态设计、工具调用循环、批量任务、服务化和排错经验。适合正在学 Agent 开发、准备把原型推向企业级场景的开发者。1. LangGraph 和 LangChain 的关系先分清组件库和流程引擎很多人在搜索时会把 LangGraph、LangChain、AI Agent 混在一起。刚开始学确实容易晕因为这三个词经常同时出现。我建议先做一层拆解LangChain 是组件库LangGraph 是流程引擎AI Agent 是基于它们组合出来的应用形态。LangChain 提供的是模型封装、Prompt 模板、输出解析、向量库连接、检索工具、Agent 工具等基础能力。它解决的是“我能方便地调用大模型、也能给模型配上工具”的问题。但模型调用完之后呢如果业务流程是固定的用一个链条就能串起来如果业务流程有分支、有循环、有来回决策链条就不够用了。LangGraph 解决的是流程控制。你可以把一次完整任务拆成多个节点每个节点是一个处理函数函数之间通过状态传递数据节点之间由边连接。边可以是固定跳转也可以是条件跳转。这样做的好处是任务的每一条路径都看得见每个节点都能单独打日志失败时能知道卡在哪一步也方便恢复和重试。1.1 早期 Agent 执行器的问题LangChain 早期有 AgentExecutor 这类工具能把“模型选择工具、调用工具、拿到结果后再交给模型”这个过程包装起来。听起来很方便但实际用到复杂业务时会发现控制力不够。比如要限制工具调用次数、要在某个条件下走人工审核、要保存多个用户的独立会话、要支持断点续跑这些需求在固化执行器里很难优雅实现。LangGraph 把控制权还给了开发者。它不替你假设流程而是让你用节点和边自己定义流程。这也是为什么很多人感觉 LangGraph 学习曲线比普通 Chain 更陡因为你需要真正理解你的业务到底有哪些步骤、哪些步骤可以并行、哪些步骤可能循环。1.2 Agent 为什么需要图结构Agent 的本质是让大模型根据目标自主决定下一步动作。既然是“自主决定”就天然带有不确定性。同一个输入模型这次可能选择调用搜索工具下次可能直接回答。如果流程是线性写死的模型的选择就没有意义。图结构更适合这种不确定流程。你不需要写死“必须先搜索再回答”你只需要定义几个节点判断节点、搜索节点、回答节点然后用条件边告诉系统下一步根据模型的意图去哪个节点。模型说需要搜索就走搜索节点模型认为信息够了就走回答节点。这样就把大模型的动态决策和工程系统的稳定性结合起来了。1.3 哪些人现在应该学哪些可以先等等如果你已经能调通大模型 API也写过简单的 RAG 或单轮 Agent接下来想处理多步骤任务、批量任务、复杂工具调用那 LangGraph 值得投入。它解决的就是这些工程化问题。反过来如果业务只有“用户提一个问题模型返回一个答案”连 Prompt 模板都用得不多那先用最朴素的 SDK 就好。引入 LangGraph 不会让简单任务变快只会增加心智负担。学习任何框架都要看场景是否匹配不是为了追新而追新。2. 环境准备与最小样例先把链路跑通再学概念学习 LangGraph 最容易犯的错是一上来就去读各种高级概念比如持久化、子图、并行分支、人工介入。这些概念本身不复杂但没有跑通最小链路之前你很难理解它们存在的意义。我建议的路径是先把环境搭好用最简单的两个节点把图跑起来然后在代码里观察状态怎么流动。这个最小闭环建立以后再逐步加条件边、加工具调用、加记忆。2.1 Python 环境、依赖和模型接入LangGraph 是基于 Python 的框架建议用 Python 3.10 以上版本。安装前最好先建虚拟环境避免和系统环境或其他项目冲突。python -m venv langgraph-demo source langgraph-demo/bin/activate # Windows 下使用 langgraph-demo\Scripts\activate pip install langgraph langchain-openai这里只装两个核心包就够了。langgraph 提供图和执行的框架langchain-openai 用来对接 OpenAI 兼容协议的大模型接口。其他包等具体功能需要时再装不要一次性装一大堆否则出问题都分不清是哪个依赖导致的。如果你使用的是国内大模型服务很多都提供 OpenAI 兼容接口可以通过设置 base_url 来接入。实际做法一般是配置环境变量export OPENAI_API_KEY你的密钥 export OPENAI_BASE_URL模型服务地址这个配置方式属于常见实践具体变量名以你用的 SDK 文档为准。注意密钥建议通过环境变量或配置文件读取不要硬编码到代码里。2.2 最小可运行的 LangGraph 工作流先用普通函数占位不接真实大模型目的只是把框架链路跑通。from typing import TypedDict from langgraph.graph import StateGraph, START, END class AgentState(TypedDict): question: str answer: str def generate(state: AgentState): return {answer: f这里是示例回答原始问题是{state[question]}} graph StateGraph(AgentState) graph.add_node(generate, generate) graph.add_edge(START, generate) graph.add_edge(generate, END) app graph.compile() result app.invoke({question: 你好}) print(result)这段代码做的事情很小先定义一个状态结构里面有两个字段 question 和 answer再定义一个节点函数函数接收当前状态返回一个字典最后把节点和边拼成图编译后调用。跑通后你能看到输出结果里同时包含 question 和 answer。这看起来简单但它是 LangGraph 的基本模型状态在节点之间传递每个节点根据输入返回增量更新。2.3 第一次跑通后要观察什么我一般会检查三件事。第一图是否成功编译并调用。如果出错优先看 Python 版本和 langgraph 版本不同版本之间 API 有可能变化。第二节点执行顺序是否正确。这是通过加日志来验证的在 generate 函数里打印一行确认程序走到了对应节点。第三状态字段是否按预期更新。如果节点返回的字典里键名写错状态就不会更新最后输出可能缺字段。你不会看到报错但会发现结果不符合预期。跑通最小样例之后再开始研究条件边、循环和工具调用。这里的顺序很重要不要在连最小样例都没跑通时就想着设计复杂的多 Agent 协作。注意先不要研究高级 API。先把“输入 - 节点1 - 节点2 - 输出”这条链跑通再去加条件边和循环。3. Agent 的核心设计状态、节点、条件边和工具调用从最小样例继续往前走下一步要补三个核心概念状态、条件边、工具调用。这三个概念撑起了大多数 Agent 工作流。网上搜索 LangGraph 时经常看到“state”“node”“edge”“conditional edge”这些词。它们不是学术名词而是代码里真实存在的结构。理解它们最好的办法是看它们在一个需求里怎么配合。3.1 状态就是整个任务的唯一信息源状态一般用 TypedDict 定义包含任务输入、中间输出、最终结果、错误信息等字段。节点函数接收当前状态返回一个字典LangGraph 会把返回值合并进状态。这里有一个很容易踩的坑状态字段的更新方式。返回一个字典时默认可能是覆盖整个字段也可能按字段合并。如果你的节点需要累加结果、需要追加日志列表就要了解你用的版本支持什么样的 reducer 或合并策略。举个简单例子如果你让状态里维护一个 messages 列表每次节点都要往列表里追加内容。如果直接返回 {messages: new_message}可能把旧消息覆盖掉如果想保留全部消息需要定义追加语义。具体写法不同版本不完全一样最好的办法是去查当前版本的官方文档不要凭记忆抄旧代码。3.2 条件边和工具调用循环真正让 Agent 像 Agent 的地方是它可以循环调用工具。比如一个写代码的 Agent先生成代码再让执行器跑一下如果报错就把错误信息交给模型修改改完再执行直到通过或达到最大次数。这种循环用普通代码写容易写成一坨 while 循环而且可观测性差。用 LangGraph 的方式是定义几个节点然后用条件边决定是否回到某个节点。def should_continue(state): if state[attempt] state[max_attempts]: return end if state[execution_result].startswith(FAIL): return retry return end这只是伪代码示例目的是说明条件边的核心它根据当前状态返回下一步要进入的节点名称。LangGraph 还提供了预置的工具节点能力可以让模型在调用工具时自动走工具节点不需要自己手写太多循环逻辑。具体用法建议参考 prebuilt 模块的文档。3.3 记忆和持久化单轮对话可以企业级不行很多 Agent 教程会提到记忆。在 LangGraph 里记忆通常通过 checkpointer 实现。简单理解checkpointer 会把每次运行的状态保存下来下次可以从某个节点继续执行也能实现多轮会话的上下文保留。学习阶段用内存型 checkpointer 很方便适合测试。但它只存在于进程运行期间进程一重启保存的内容就没了。企业级场景里如果任务需要长时间运行、需要失败后恢复就要考虑把状态保存到数据库里。LangGraph 支持不同类型的 checkpointer 后端具体怎么配以官方文档为准。这里还要提醒一点不要把“多轮会话历史”直接等同于“Agent 记忆”。只保存原始对话记录在大模型上下文窗口变大后看似省事但 token 成本会不断攀升响应时间也会变长。更合理的做法是只保存结构化信息比如用户目标、已确认条件、关键结果、未完成事项。判断哪些该存、哪些不该存本身就需要对业务有足够理解。4. 从单链路到批量任务并发、重试、队列和幂等学完单个 Agent 工作流接下来通常面临一个现实需求要把 100 条数据、1000 个文件批量跑一遍。这时候很多人会直接写一个 for 循环挨个调用 invoke。几十条数据问题不大一旦数据量上去问题就开始暴露。批量任务不是“循环调用”那么简单。它涉及并发控制、限流、失败重试、输出命名、断点续跑等多个问题。如果只是自己测试默认配置够用如果要跑真实业务数据要单独设计。4.1 不要用 for 循环直接跑大批量我的建议是先跑 20 条小样本确认每条任务的输入输出格式都正常再考虑并发。小样本跑起来后统计三件事单条平均耗时、错误率、输出内容是否一致。单条成功不代表批量成功因为批量环境里会出现超时、限流、资源竞争等问题。你真要跑一千条任务可以先设计一个任务队列。每条任务有唯一 ID输入数据、执行状态、结果、错误信息都记录在表格里。跑完后检查表里有多少成功、多少失败失败的任务再单独重跑。这个表可以简单到是一个 CSV 文件也可以是数据库表。task_id, input_text, status, result, error, retry_count批量任务的核心目标不是“一次跑完”而是“每条任务都有可追溯的结果”。4.2 并发和超时参数并发能显著提高吞吐但也要看模型服务的限流条件。如果你用的是外部大模型 API通常会有限流。盲目增加并发可能换来一批 429 错误。企业级项目里建议在做压测之前先查清楚服务的速率限制再据此设置并发数。超时设置也很重要。一个大模型调用如果长时间没有返回会拖住整个任务。一般建议给每次请求设置合理的超时时间超时后按失败处理并重试。重试时不要立刻重试要用退避策略比如第一次等 1 秒第二次等 2 秒第三次等 4 秒避免加重服务压力。低配置环境跑单条任务成功不代表批量并发下还能稳定。要注意 CPU、内存、磁盘、网络带宽到底够不够这些指标比单纯的代码逻辑更能解释批量运行时的卡顿。4.3 输出命名、幂等和断点续跑批量任务里最容易被忽略的是输出管理。每条任务的结果应该稳定落到一个可预期的地方文件名最好带上任务 ID不要用时间戳。为什么因为失败重跑时时间戳会生成新文件容易产生重复数据用任务 ID 就能保证同一条任务重复执行时覆盖到同一份输出。幂等性是批处理的另一项要求。简单说同一条任务跑一次和跑两次结果应该一致或者至少不会产生副作用累计。如果你的节点会写数据库、发通知、扣服务配额就要特别注意。跑批任务前确认这些副作用操作可以被重复执行否则失败重试时会造成重复发送或重复写入。断点续跑看起来是加分项实际在长耗时任务里很有用。如果 LangGraph 部署了持久化 checkpointer配合任务队列就能在进程重启后从失败节点继续。企业级任务里这个能力能减少大量浪费。注意这里不要一上来就开最大并发。先用一条样例确认输入、输出和日志都正常再逐步加大并发数。5. 企业级化开发日志、监控与接口服务当工作流能够在本地批量稳定跑起来下一步是把它变成可对外提供的服务纳入团队的日志和监控体系。这个阶段的关键词是接口、日志、监控、配置管理。很多教程到这里会直接给你一套部署命令但实际开发中的难点不在部署而在可维护性。一条 Agent 任务跑失败了你能不能从日志里快速定位是哪个节点、调用了哪次模型、传了什么输入、模型返回了什么如果答案是不能那这套系统还停留在 Demo 阶段。5.1 从脚本到 API 服务把 LangGraph 图包装成 HTTP 服务是常见的做法。你可以用 FastAPI 提供一个接口接收请求参数调用编译好的图再返回结果。为了不阻塞服务进程长耗时的 Agent 任务最好放到任务队列里异步执行接口只负责接收任务并返回任务 ID用户通过另一个接口轮询结果。这样设计的好处是服务不会因为某个任务耗时长而占用大量连接也更容易横向扩展。具体代码不在这里展开不同项目的技术栈差异很大。你只需要记住一个原则不要让图对象在每次请求时重新编译。图在启动时编译一次后续复用同一实例否则性能会很差。5.2 日志与可观测性Agent 工作流的日志比普通 Web 服务更复杂因为它会有多节点、循环、工具调用等动态过程。我一般会在每个节点入口和出口打结构化日志包含任务 ID、节点名称、当前状态摘要、耗时、错误信息。结构化日志的意思是每条日志有固定字段方便后续检索和分析。大模型调用的日志要格外留意。Prompt 和模型回复可能很长全量打印到日志里会让日志文件迅速膨胀。建议只记录必要字段模型名称、token 数、耗时、返回状态、是否命中工具、错误码。完整的 Prompt 和输出默认不打需要排查时再针对性记录。5.3 性能与容量判断判断一个 Agent 系统能不能上线不能只看 Demo 演示。要看这几个指标单节点平均耗时、整条工作流 P50 和 P95 耗时、并发下成功率、模型调用 token 消耗、模型服务返回错误率。如果一个配置的上限是每分钟 100 次调用你把并发开到 200系统就会不稳定。资源指标也不能忽略。CPU 和内存是基础但 Agent 任务往往更依赖网络 I/O 和模型服务吞吐。如果你的工作流里还有大量检索和文件读写磁盘 I/O 也会成为瓶颈。容量评估一定要靠压测不能靠感觉。压测时按实际场景准备测试数据观察系统在并发上升时的表现找到瓶颈点再优化。6. 常见的坑和排查链路任何框架用久了都会积累一套排查经验。LangGraph 也不例外。有很多问题看起来是框架报错实际原因可能来自依赖版本、输入数据、模型接口甚至只是字段名写错。我把踩过的坑整理成几条并给出排查顺序供你对照。6.1 启动不起来、报错奇葩先看版本和依赖LangGraph 正在快速迭代不同版本的 API 有差异。如果你安装的是最新版而参考的是几个月前的旧教程很可能代码报错。遇到框架级报错先执行 pip list 看版本再对照官方文档确认 API 是否一致。依赖冲突也很常见。langgraph 依赖 langchain-core而其他库可能对 langchain-core 版本有不同要求。安装时尽量让依赖保持简洁升级时先看 changelog。很多“框架有问题”的结论最后都发现是自己装的包版本太乱。6.2 死循环和无限工具调用Agent 工作流最典型的故障是死循环。模型一直判断还需要调用工具但每次都返回同样的结果图的循环就一直不退出。日志里能看到同一节点被反复执行任务迟迟不结束。解决办法是在状态里维护一个计数器记录循环次数或工具调用次数。达到阈值后无论模型说什么都强制跳转到一个“最终回答”节点。这个限制必须写进图逻辑不能指望模型自己收敛。6.3 状态丢失和输出缺失另一个常见问题是状态字段没有按预期更新。节点返回了值但最终结果里却没有。这类问题多半出在字段更新语义上。检查你定义状态时对该字段使用的合并方式确认它支持追加还是只能覆盖。还有一种情况节点函数里直接修改了传入状态对象而不是返回新字典。在 LangGraph 的设计里状态的更新需要遵循框架约束。不要假定 Python 的 dict 修改会自然生效严格按照框架要求返回更新值。6.4 我自己的排查顺序遇到问题我一般按这个顺序查能省很多时间先看现象报错、卡住、无输出、输出异常、速度过慢。再看输入文件格式、编码、路径、内容是否为空、字段名是否匹配。再看环境Python 版本、依赖版本、虚拟环境、密钥、base_url、权限。再看参数并发、超时、重试、最大步数、模型名称、温度、checkpointer 配置。最后看工具本身官方文档里的已知限制、版本变更、示例代码差异。很多报错不是 LangGraph 的问题而是模型接口返回了意料之外的错误或者输入路径没有权限。先看日志再改代码而不是一上来就换框架、改架构。7. 学习路线建议和边界判断最后聊一下怎么继续往下学以及什么情况应该停下来。框架学习最怕的是方向不对学了一堆概念却没有真正用起来。7.1 怎么学官方文档加源码验证我看资料的习惯是先跑通一个最小样例再去读官方文档对应章节最后用官方源码验证理解。LangGraph 的文档现在很详细但内容多不建议从头到尾刷。你应该带着自己的需求去查比如“我要做一个带工具调用的批量问答”就查相关章节改造成自己的代码。源码是最接近真相的资料。遇到 API 行为不确定的时候直接跳到源码里看类型定义和默认参数。读源码不用读完只看关键函数就够。这样建立的知识体系比刷几十条教程更扎实。7.2 什么场景真的不需要用 LangGraph这里要很明确地说不是所有 AI 大模型应用都需要 LangGraph。如果你的业务只有单轮问答、没有分支和循环直接用模型 SDK 就够。如果你的流程是固定链条用普通 Chain 或简单的函数调用更直接。图结构带来的额外复杂度只有在流程确实动态、需要回溯、需要持久化、需要并发控制时才有价值。还有一种情况是团队还没有工程化基础接口、日志、错误处理都没做好此时不建议直接上多 Agent 框架。先把最小闭环跑稳定再逐步引入更复杂的编排能力这条路更稳妥。7.3 落地时的几个经验如果让我给一个从入门到企业级实战的总结我会说三句话。第一先从最小工作流开始。把一条链路跑通、把状态看清、把日志打全比研究一百个高级功能都重要。第二批量任务要单独设计。并发、重试、消息队列、断点续跑这四件事没想清楚之前不要盲目扩大数据量。第三遇到问题先看环境再改代码。LangGraph 本身迭代快依赖版本不一致是最常见的故障源。真正要做企业级项目的时候最该盯住的不是功能列表而是输入格式、资源占用、失败重试和日志可读性。踩过几次之后我发现很多问题不是工具能力不够而是前置环境和输入材料没有处理干净。把这个基础打牢LangGraph 才能发挥出它真正的价值。