LangGraph 从入门到实战:StateGraph 与 Agent 工具调用循环

发布时间:2026/11/4 9:34:31

LangGraph 从入门到实战:StateGraph 与 Agent 工具调用循环 1. 从零理解 LangGraph它到底解决什么问题1.1 为什么有了 LangChain 还需要 LangGraph很多人第一次接触 LangGraph 都会问同一个问题我已经在用 LangChain 了为什么还要多学一个框架这个问题我当初也纠结过后来在实际项目里踩了坑才真正想明白。LangChain 的核心抽象是Chain也就是一条线性的调用链输入进来经过提示词模板、模型、输出解析器结束。这条链路是单向的、无环的。你让它做一次问答、一次摘要、一次翻译它很好用。但一旦你要做下面这些事情Chain 就开始力不从心了模型输出需要根据内容走不同的分支比如判断用户意图后决定调用哪个工具需要循环执行直到满足某个条件比如 Agent 反复调用工具直到任务完成需要在多个步骤之间维护和更新状态比如对话历史、中间结果、累积的上下文需要人工介入某个中间环节比如审批、修正这些需求的共同点是流程不再是直线而是带分支和环路的图。LangGraph 就是为这个场景设计的。它把整个流程建模成一个状态图StateGraph节点是计算步骤边是流转逻辑状态在节点之间传递和更新。打个比方LangChain 像一条流水线原料从一头进成品从另一头出LangGraph 像一张地铁线路图有换乘站、有环线、有分支你可以根据当前情况决定下一站去哪。1.2 StateGraph 的三个核心概念LangGraph 的 StateGraph 说复杂也复杂说简单也简单核心就三个东西State状态整个图共享的一份数据。它通常是一个字典或者 TypedDict里面放着消息列表、中间变量、计数器等等。每个节点都能读到它也能返回更新后的部分。Node节点一个函数接收当前 State返回对 State 的更新。节点可以是调用大模型、执行工具、做数据转换任何 Python 函数都行。Edge边定义节点之间的流转关系。普通边是固定的 A 到 B条件边conditional edge则根据一个路由函数的返回值决定下一步走哪。理解了这三个概念你就理解了 LangGraph 的 80%。剩下的都是在这三个基础上的组合和变体。1.3 适合谁来学学完能做什么这篇内容适合三类人一是有 Python 基础、想入门 Agent 开发的工程师二是用过 LangChain 但被复杂流程卡住的人三是想理解 Agent 底层编排原理的学习者。学完之后你能独立搭出一个带工具调用循环的 Agent能根据模型输出做条件路由能维护多轮对话状态。这些能力是当前 Agent 开发的基本功面试里也经常被问到 LangGraph 和 LangChain 的区别、StateGraph 怎么设计这类问题。提示LangGraph 的版本迭代比较快本文基于较稳定的 API 讲解核心概念不会变但具体参数名建议对照你安装的版本确认。2. 环境搭建与第一个 StateGraph2.1 安装与依赖选择先把环境弄干净。我强烈建议用虚拟环境因为 LangGraph 依赖的包不少混装容易出问题。python -m venv venv source venv/bin/activate # Windows 用 venv\Scripts\activate pip install langgraph langchain-openai这里有个选型细节值得说langchain-openai是官方维护的 OpenAI 兼容接口包如果你用的是其他模型服务只要它兼容 OpenAI 的接口格式改一下base_url就能用。这样写代码时不用绑定具体厂商迁移成本低。安装完可以验证一下import langgraph print(langgraph.__version__)版本号能打印出来就说明装好了。如果报错八成是 Python 版本太低LangGraph 一般要求 3.9 以上。2.2 定义 State 的正确姿势State 的定义直接决定了你后面写代码顺不顺手。新手最容易犯的错是把 State 定义得太随意用普通 dict结果多个节点更新同一个字段时互相覆盖。推荐用TypedDict加Annotated来定义尤其是消息列表这种需要追加而不是覆盖的字段from typing import Annotated, TypedDict from langgraph.graph.message import add_messages class AgentState(TypedDict): messages: Annotated[list, add_messages] tool_calls_count: int关键在add_messages这个 reducer。默认情况下节点返回的新值会覆盖旧值。但对话消息需要的是追加——新一轮的消息要加到历史后面而不是把历史冲掉。add_messages就是告诉 LangGraph这个字段用追加的方式合并。我踩过的坑一开始没用 reducer结果 Agent 每轮对话都失忆只记得最新一条消息。排查了半天才发现是 State 合并策略的问题。所以这个细节一定要在定义阶段就处理好。2.3 构建最小可运行图先搭一个最简单的图两个节点一条边跑通了再往上加复杂度from langgraph.graph import StateGraph, START, END def node_a(state: AgentState): return {messages: [(user, 来自节点A)]} def node_b(state: AgentState): return {messages: [(assistant, 来自节点B)]} builder StateGraph(AgentState) builder.add_node(a, node_a) builder.add_node(b, node_b) builder.add_edge(START, a) builder.add_edge(a, b) builder.add_edge(b, END) graph builder.compile() result graph.invoke({messages: [], tool_calls_count: 0}) print(result[messages])START和END是两个特殊标记分别代表图的入口和出口。compile()会把图冻结成一个可执行对象之后每次invoke都是一次完整的执行。实测下来这个最小例子能帮你快速确认环境没问题、State 合并正常。别小看这一步很多后续的诡异 bug 都是因为最基础的 State 行为没搞对。3. 条件路由让流程学会看情况走3.1 条件边的工作原理条件边是 LangGraph 从流程图进化成智能编排的关键。它的机制是这样的你提供一个路由函数这个函数读当前 State返回一个字符串LangGraph 拿这个字符串去匹配你预先注册的路径映射决定跳到哪个节点。路由函数本身不修改 State它只做判断。这个职责分离很重要——判断逻辑和执行逻辑分开写代码才清晰。3.2 一个意图分流的实战例子假设我们要做一个客服入口根据用户问题分流到查订单或通用问答两条路def route_by_intent(state: AgentState): last_msg state[messages][-1].content if 订单 in last_msg or 物流 in last_msg: return order return general builder.add_conditional_edges( classify, route_by_intent, { order: order_node, general: general_node, } )add_conditional_edges的第三个参数是路径映射表把路由函数的返回值映射到实际节点名。这样路由函数只管返回语义化的标签具体跳哪由映射表决定改起来很方便。3.3 路由设计的几个经验第一路由函数要尽量纯粹。不要在里面调模型、发请求只做基于已有 State 的判断。需要模型判断的单独放一个节点去做把结果写进 State再让路由函数读。第二路径映射要覆盖所有返回值。如果路由函数可能返回三种结果映射表里就得有三种否则运行时会报找不到路径。我建议路由函数最后加一个兜底 return映射表里也配一个默认分支。第三条件边可以形成环。这正是 Agent 工具调用循环的基础——路由函数判断还需要继续调用工具就跳回模型节点形成循环。下一节详细讲。注意循环一定要有终止条件否则会无限执行下去。常见的做法是在 State 里放一个计数器超过阈值就强制走向 END。4. Agent 工具调用循环的完整实现4.1 工具调用循环的本质Agent 之所以叫 Agent核心就在于它能自己决定调用什么工具、调用几次。这个能力的底层就是一个循环把对话历史发给模型模型返回要么是最终回答要么是我要调用某个工具如果是工具调用执行工具把结果加回对话历史回到第 1 步直到模型给出最终回答用 LangGraph 表达就是两个节点加一条条件边model节点和tools节点条件边判断模型输出里有没有工具调用。4.2 定义工具与绑定模型先定义工具。LangGraph 兼容 LangChain 的工具定义方式from langchain_core.tools import tool tool def get_weather(city: str) - str: 查询指定城市的天气。 fake_data {北京: 晴25度, 上海: 多云28度} return fake_data.get(city, 暂无数据) tools [get_weather]工具的 docstring 很重要模型就是靠它来判断什么时候该调用这个工具的。写得越清楚模型选得越准。然后绑定模型from langchain_openai import ChatOpenAI llm ChatOpenAI(modelgpt-4o-mini, temperature0) llm_with_tools llm.bind_tools(tools)bind_tools会把工具的描述信息一起发给模型模型就知道有哪些工具可用。4.3 构建循环图现在把循环搭起来from langgraph.prebuilt import ToolNode def call_model(state: AgentState): response llm_with_tools.invoke(state[messages]) return {messages: [response]} def should_continue(state: AgentState): last state[messages][-1] if last.tool_calls: return tools return END builder StateGraph(AgentState) builder.add_node(model, call_model) builder.add_node(tools, ToolNode(tools)) builder.add_edge(START, model) builder.add_conditional_edges(model, should_continue, {tools: tools, END: END}) builder.add_edge(tools, model) agent builder.compile()注意builder.add_edge(tools, model)这一行——工具执行完无条件回到模型节点。这就是循环的闭合点。而should_continue决定是继续循环还是结束。ToolNode是 LangGraph 提供的预置节点它会自动读取消息里的 tool_calls执行对应工具把结果包装成 ToolMessage 返回。省了自己写解析逻辑。4.4 跑一次完整调用result agent.invoke({ messages: [(user, 北京今天天气怎么样)], tool_calls_count: 0 }) for msg in result[messages]: print(type(msg).__name__, :, getattr(msg, content, ))你会看到消息序列大致是用户消息 → 模型消息带 tool_calls→ 工具消息天气结果→ 模型消息最终回答。这个序列完整展示了工具调用循环的一次迭代。4.5 循环控制与安全边界生产环境里循环必须加护栏。我一般会做两件事一是限制最大迭代次数。在 State 里放计数器每次进 model 节点加一超过比如 10 次就强制结束。防止模型陷入反复调用同一个工具的死循环。二是给 compile 传 recursion_limitagent builder.compile() result agent.invoke(inputs, config{recursion_limit: 25})recursion_limit是 LangGraph 层面的硬限制超过会抛异常。这是最后一道防线即使你的业务逻辑有漏洞也不会把资源跑爆。提示recursion_limit默认是 25对于大多数 Agent 场景够用。如果你的任务确实需要很多步可以调高但要配合业务层的计数器一起用。5. 常见问题排查与避坑清单5.1 消息不追加反而被覆盖这是最高频的问题。症状是 Agent 只记得最后一轮对话。原因几乎都是 State 里的 messages 字段没加add_messagesreducer。检查你的 TypedDict 定义确认写成了Annotated[list, add_messages]。5.2 条件边报找不到路径报错信息通常是找不到某个节点或路径。排查顺序先看路由函数的返回值再看add_conditional_edges的映射表确认两者能对上。特别注意END这个特殊值映射表里要写成{END: END}而不是字符串END。5.3 工具调用后模型不继续有时候工具执行完了模型却不再生成最终回答。常见原因是工具返回的内容格式不对或者 ToolMessage 的tool_call_id没对上。用ToolNode能避免大部分这类问题因为它会自动处理 id 匹配。如果你手写工具节点务必保证返回的 ToolMessage 带上正确的tool_call_id。5.4 排查速查表症状可能原因解决方向对话失忆messages 无 reducer加 add_messages找不到路径路由返回值与映射表不匹配对齐两者加兜底分支无限循环缺少终止条件加计数器 recursion_limit工具结果丢失tool_call_id 不匹配用 ToolNode 或手动对齐 id状态字段互相覆盖多节点写同一字段明确 reducer 或拆分字段5.5 几个我踩过的坑第一个坑是在节点里直接修改 state 字典。LangGraph 期望节点返回更新量而不是原地修改。原地改虽然有时看着能跑但会破坏框架的状态管理导致难以排查的 bug。老老实实 return 一个字典。第二个坑是把路由逻辑写得太重。我一开始在路由函数里调模型做意图判断结果每次路由都要等一次模型响应慢得离谱。正确做法是把模型判断单独做成一个节点结果写进 State路由函数只读不调。第三个坑是忽略异步。如果你的工具涉及网络请求同步执行会阻塞整个流程。LangGraph 支持异步节点用async def定义节点、ainvoke调用能显著提升并发场景下的吞吐。这个在单机测试时感觉不明显一上量就体现出来了。6. 从能跑到好用进阶优化思路6.1 状态设计的分层当 Agent 变复杂State 会越来越臃肿。我的做法是分层核心对话消息放一层任务相关的中间变量放一层控制类字段计数器、标志位放一层。虽然都在同一个 TypedDict 里但命名上区分开比如messages、task_*、ctrl_*读代码时一眼能看出字段用途。6.2 人工介入节点LangGraph 支持在流程中插入人工确认。做法是在需要确认的地方加一个节点把当前状态暴露出去等外部输入后再继续。这在涉及敏感操作比如自动发邮件、自动下单的 Agent 里非常必要。实现上可以用interrupt机制让图暂停外部恢复后再往下走。6.3 多 Agent 协作的雏形单个 Agent 能力有限复杂任务往往需要多个 Agent 分工。LangGraph 的图结构天然适合这个场景把每个 Agent 做成一个子图用一个调度节点根据任务类型路由到不同的子图。子图之间通过共享的 State 传递信息。这就是多 Agent 协作的基本形态比把所有逻辑塞进一个大 Agent 要清晰得多。6.4 可观测性Agent 跑起来之后你得知道它每一步在干什么。LangGraph 可以配合回调机制记录每个节点的输入输出。我习惯在开发阶段把每个节点的 State 变化打日志出问题时能快速定位是哪一步跑偏了。上线后则关注循环次数、工具调用成功率这些指标。最后分享一个我自己的体会LangGraph 的学习曲线主要卡在状态思维上。习惯了写线性代码的人一开始很难适应节点返回更新量、框架负责合并这种模式。但一旦转过这个弯你会发现用它表达复杂的 Agent 逻辑比手写 if-else 和 while 循环清晰太多。建议从最小的两节点图开始一步步加条件边、加循环、加工具每加一层都跑通再往下走比一上来就抄一个完整 Agent 例子要扎实得多。
延伸阅读

更多相关文章

2026/11/4 9:34:31

Codex Token消耗翻倍排查:config.toml配置与Skill优化实战

1. 休假回来第一件事:先看账单,再看代码休了十天假,回来打开 Codex 的用量面板,我盯着那个数字看了好几秒——Token 消耗比休假前整整翻了一倍。不是涨了百分之二三十,是翻倍。更离谱的是,这十天我一行代码…

2026/11/4 9:29:30

IPD流程中市场地图的构建与应用实践

1. IPD流程中的市场地图价值解析在华为、IBM等标杆企业验证过的IPD(集成产品开发)体系中,市场地图(Market Map)是需求管理环节最直观的战略可视化工具。我曾在智能硬件行业主导过三次IPD流程导入,发现70%的…

2026/11/4 9:29:30

硬件工程师面试题集:Setup/Hold时序与组合逻辑延迟计算详解

简介:这份硬件工程师面试题集面向准备求职或跳槽的硬件工程师、电子相关专业应届生,以及需要系统梳理基础知识的从业者,帮助读者在面试前快速回顾高频考点、查漏补缺。内容覆盖数字电路、嵌入式系统、电子线路、通讯、微电子与半导体等方向&a…

2026/11/4 13:16:14

Qt集成PDF库的ABI对齐指南:MSVC2017+Qt5.12静态链接避坑

简介:本资源是专为Qt开发者提供的PDF功能集成解决方案,基于Google开源pdfium引擎封装,适用于使用Visual Studio 2017编译环境的64位Windows平台Qt应用程序,解决Qt原生缺乏PDF渲染能力的痛点,尤其适合需嵌入文档查看、解…

2026/11/4 13:16:14

DITA 2.0与RAG融合实现智能内容增强

我无法根据您提供的输入内容生成符合要求的博文。原因如下:输入中缺少必要字段:项目正文、关键词、摘要描述三项均为完全空白(仅显示空行或代码块符号),而根据任务定义,这三项是进行专业拆解与延展的唯一依…

2026/11/4 13:16:14

MyDAC v5.10:Delphi/C++Builder 原生 MySQL 协议直连组件

简介:本资源为MySQL Data Access Components(MyDAC)v5.10官方源码包,专为Delphi 7–2007及CBuilder开发者设计,解决原生连接MySQL数据库时依赖ODBC、性能低、事务与存储过程支持弱等痛点,适用于数据库中间件…

2026/11/4 13:16:14

并行草稿机制解析:从P-EAGLE到DSpark的投机采样加速

做推理加速的人,几乎都会碰到同一个尴尬:GPU 很贵、显存很大,但生成 token 的速度就是上不去。自回归解码一步只出一个字,剩下的时间基本都耗在把几百亿参数从显存搬到计算单元的路上。投机采样(Speculative Decoding&…

2026/11/4 13:16:14

rovio轻量级VI-SLAM原理与嵌入式部署实战

简介:本资源为ROVIO(Robust Visual-Inertial Odometry)视觉惯性里程计算法的完整开源实现,面向机器人、自动驾驶与嵌入式SLAM方向的研究者及算法工程师,解决未知环境中高鲁棒、低延迟的实时定位与建图问题。压缩包共56…

2026/11/4 13:11:13

光学仿真中功能性薄膜设计与VirtualLab Fusion应用

1. 功能性薄膜在光学仿真中的核心价值 现代光学系统中,功能性薄膜的设计与仿真一直是工程师面临的挑战。传统方法需要精确建模每一层膜的厚度和材料特性,但当膜层结构复杂(如包含数百层)或参数未知时,这种建模既低效又…

2026/11/4 12:38:23

面向复杂光照与角度的宠物面部识别鲁棒性增强策略

在智慧养宠时代,基于视觉的宠物身份识别技术正逐步从实验室走向家庭应用。然而,与配合度高的人类不同,宠物是典型的“非合作生物识别对象”——它们不会主动配合摄像头调整姿态,更无法控制光照环境。实际应用中,我们常…

2026/11/3 14:24:53

SSM电子书店源码全解析:结构、原理、部署与排错实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/11/4 0:03:20

AI辅助技术栈评估:提升研发决策效率60%

1. 项目背景与核心价值技术决策一直是研发团队面临的重大挑战。随着技术生态的快速演进,技术栈的选择、维护和迭代变得愈发复杂。我们团队在过去两年里,先后经历了三次重大技术栈迁移,每次都需要投入大量人力进行技术评估和风险分析。直到去年…

2026/11/4 0:03:20

从生成Token到直接决策:Jev如何重塑AI Agent工程实践

1. 从"生成文字"到"拍板决策":Jev 到底在解决什么问题大多数人第一次接触大模型,脑子里建立的模型是"输入问题、输出文字"。你问它今天天气怎么样,它给你一段描述;你让它写个周报,它给你…

2026/11/4 0:03:20

32G统一内存跑大模型:内存账、TPS实测与端云分流

想在一台 32G 统一内存的小主机上把大模型跑成"日常可用",这件事我前后折腾了小半年。标题里说的这台 Mac mini M6,是我们这次讨论的目标平台,具体到手规格以实物为准;但下面这套推算方法和实测思路,对任何统…

2026/11/4 12:38:23

面向复杂光照与角度的宠物面部识别鲁棒性增强策略

在智慧养宠时代,基于视觉的宠物身份识别技术正逐步从实验室走向家庭应用。然而,与配合度高的人类不同,宠物是典型的“非合作生物识别对象”——它们不会主动配合摄像头调整姿态,更无法控制光照环境。实际应用中,我们常…

2026/11/3 14:24:53

SSM电子书店源码全解析:结构、原理、部署与排错实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

还想了解更多?直接咨询顾问

免费诊断 + 免费方案 + 透明报价。

全国咨询热线400-8866-253
免费获取方案
☎咨询二维码 ☎ ↑