LangGraph图编排实战:State、Node、Edge构建可控AI Agent工作流

发布时间:2026/8/30 2:23:58
LangGraph图编排实战:State、Node、Edge构建可控AI Agent工作流 如果你已经能熟练调用大模型 API准备开始做一个真正的 AI Agent八成会遇到同一个问题模型答得不好要不要让它重试一次用户的问题应该分给哪个子 Agent 处理一个工作流跑了十几个步骤状态究竟保存在哪里这些问题只用“按顺序调用 LLM”的老办法很难优雅解决。LangGraph 在近两年迅速成为 Agent 开发的核心框架原因不是它多了一个“链”而是它把 Agent 的开发视角从“写一段顺序代码”改成了“画一张有向图”。在这张图里State 是多个节点共享的状态Node 是真正干活的一步Edge 决定下一步走到哪里。这套设计把复杂流程拆解成了可测试、可控制、可恢复的单元也让多轮对话、分支路由、多 Agent 协作变得直观。这篇文章会按照零基础实战路线拆解 State、Node、Edge 三个核心组件然后手把手带你把状态管理、条件分支、多 Agent 协作全部跑通。文章采用的方案适用于 LangGraph 当前主流版本代码以教学思路为准不依赖某个特殊版本你可以在本地环境直接复制运行。1. 这篇文章真正要解决的问题先说结论LangGraph 解决的是把“不可控的智能”变成“可控的流程”。如果你只做一个单轮问答即用户输入一句话、模型返回一句话那确实用不到 LangGraph直接用 ChatOpenAI 之类的接口就行。但真实业务里的 Agent 通常要复杂得多比如用户输入问题后Agent 要先判断该用哪个工具再用工具查资料然后把资料交给模型总结。第一次生成结果不够好Agent 要能自我反思并重新生成。一个客服系统里用户的问题要被路由到订单组、售后组、技术支持组等多个子 Agent。对话过程中用户之前的偏好、当前任务进度、尝试次数都需要被记录下来。这些需求如果用 LangChain 的 Chain 来写通常只能硬编码前一个步骤的输出作为后一个步骤的输入。流程一旦出现分支、循环、多角色决策代码就会堆满 if/else调试和扩展都很难受。而这正是 LangGraph 的强项它把流程变成一张有向图节点负责干活边负责决定下一步走向每个节点都能读写同一个 State于是分支、循环、回退、并行都变成了图的连接关系而不是散落在代码里的各种判断。还有一个关键点要说明LangGraph 不是 LangChain 的替代品而是 LangChain 生态里的一个编排层。你可以用 LangChain 的模型封装、工具封装、提示词模板再用 LangGraph 来控制整个工作流的走向。二者是配合关系而不是竞争关系。这篇文章适合谁读适合已经了解 Python 基本语法、能调用大模型 API、但不知道怎么把多个模型调用组合成复杂流程的开发者。如果你正在学习 Agent 开发或者正在规划和维护一个多步骤 AI 应用这篇文章可以给你一条清晰的上手路径。读完这篇文章你能得到三样东西第一对 State、Node、Edge 本质的理解第二三个可以直接运行的完整示例第三一套写生产环境 Agent 时容易踩的坑和规范建议。2. LangGraph 核心概念拆解State、Node、EdgeLangGraph 的核心模型非常像一个“有状态的有向图”。很多初学者第一次看官方文档会蒙因为文档例子里的函数签名基本都一样接收一个 state返回一个 state。理解这套设计的关键是先把三个核心概念彻底搞清楚。2.1 State多个节点共享的“工作台”State 可以理解为一张放在所有节点之间的共享工作台。每个节点执行前都可以从工作台上取走需要的信息执行完后也可以把新信息放回工作台。这样节点和节点之间就不需要手动传递参数所有数据都通过 State 流动。在代码层面State 通常是一个 TypedDict 或 Pydantic 模型。LangGraph 要求每个节点函数接收一个 State 对象然后返回一个字典字典里的内容会被合并回 State。这里有一个新手最容易误解的地方节点函数并不是直接修改传入的 state 字典而是返回一个新字典由框架去合并。比如def some_node(state): # 不要这样写 state[count] state[count] 1 return state # 应该这样写 return {count: state[count] 1}返回的字典只包含需要更新的字段LangGraph 会自动把新值合并到完整 State 中。State 中其他字段会被保留不需要在每个节点里重新返回一遍。如果你希望多个节点往同一个字段追加内容比如多轮对话的消息列表LangGraph 还支持通过 Annotated 使用 reducer来定义合并逻辑。零基础阶段先理解“返回值会合并回 State”就够用了reducer 等用到再深入。2.2 Node图里的“执行单元”Node节点是图里真正干活的单元。它可以是一个普通函数也可以是一个异步函数甚至可以是 LangChain 的 Runnable。每个节点只做一件事接收 State返回字典形式的更新然后结束。把节点想象成生产流水线上的工位。工位的输入是从 Work State 里拿到的半成品工位加工完后把半成品放回流水线下一个工位继续处理。节点的职责应该足够单一不要在一个节点里又调模型又处理数据又做路由判断那样会失去图编排的优势。在实际项目中最常见的节点有三种Agent 节点调用模型决策、Tool 节点执行工具、Router 节点根据 State 判断下一步去哪里。后面示例中会逐渐看到它们的作用。2.3 Edge决定流程走向的“路径”Edge边负责连接节点也负责控制流程走向。LangGraph 里主要有两种边。一种是普通边add_edge表示“无条件跳转”。A 节点执行完直接进入 B 节点没有其他选择。另一种是条件边add_conditional_edges表示“根据 State 路由到不同节点”。条件边需要一个路由函数该函数接收 State并返回一个字符串LangGraph 根据这个字符串去查一张映射表决定下一步走到哪个节点。另外还有两个特殊节点需要记住START 表示图的入口END 表示图的终止点。任何图都必须有从 START 进入的路径也必须有一条走向 END 的路径否则图无法正常结束。2.4 一个最小流程的四个步骤理解 LangGraph 的构建流程通常只需要四步定义 State 结构也就是声明哪些字段要在节点之间共享。实现各个 Node 函数每个函数接收 State 并返回更新。添加 Node 和 Edge把图结构连接起来并用条件边处理分支。调用 compile() 编译图然后通过 invoke() 启动执行。这个“定义状态、实现节点、连接边、编译执行”的模型就是 LangGraph 所有功能的基础。后面所有示例无论多复杂最终都会落到这四步上面。3. LangGraph 环境准备与项目初始化动手之前先把环境准备好。LangGraph 是一个 Python 库安装和普通 Python 包没有区别。3.1 Python 环境要求LangGraph 要求 Python 3.9 及以上版本。建议使用 Python 3.10 或 3.11这两个版本对类型注解的支持和对 LangChain 生态的兼容性都比较稳定。你可以用 conda 或 venv 创建一个独立环境避免和系统 Python 环境冲突python -m venv langgraph-demo source langgraph-demo/bin/activate # Windows 下运行 langgraph-demo\Scripts\activate3.2 安装 LangGraph 及依赖核心库只需要安装 langgraph。如果你打算在示例中调用大模型还需要安装 langchain-openai这是 LangChain 官方提供的 OpenAI 兼容接口封装。pip install langgraph langchain-openai如果你想在本地启动 LangGraph 的调试界面或部署服务可以额外安装官方提供的命令行工具pip install langgraph-cli需要说明的是不同版本的 LangGraph 在 API 细节上可能有细微差别安装时以官方最新稳定版为准。这篇文章里的代码遵循 LangGraph 的通用 API适用于主流版本。3.3 大模型 API 配置本文的第二个和第三个示例会调用大模型。你可以在环境变量中配置 OPENAI_API_KEYexport OPENAI_API_KEY你的 API Key如果你使用的是国内兼容 OpenAI 协议的模型服务比如 DeepSeek、Qwen 等也可以通过 base_url 指向对应服务地址from langchain_openai import ChatOpenAI llm ChatOpenAI( modelqwen-plus, # 以服务商实际模型名为准 api_key你的 API Key, base_urlhttps://你的服务地址/v1 )由于示例要保证“可复制、可运行”本文在展示 LangGraph 核心控制流时先用普通函数模拟节点逻辑不依赖模型 API 也能跑通。需要调用模型的节点会明确标注。3.4 项目目录结构建议按下面的结构组织代码方便后续扩展langgraph-demo/ ├── graph/ │ ├── __init__.py │ ├── state.py # State 定义 │ ├── nodes.py # 节点函数 │ ├── edges.py # 条件路由函数 │ └── build_graph.py # 构图与编译 ├── main.py # 入口脚本 └── requirements.txt对于教程单文件也可以但如果你真的想在生产环境使用 LangGraph建议从一开始就按模块拆分。节点函数、路由函数和构图逻辑分开放代码会清晰很多。4. 第一个 LangGraph 完整示例状态流转的最小闭环这一节会写两个示例。第一个不带大模型用纯 Python 函数感受 State 在节点之间如何流动第二个引入大模型做一个最小可用的问答 Agent。4.1 示例一纯函数节点理解 State 的传递方式新建一个文件demo1_basic_graph.py代码如下# 文件路径demo1_basic_graph.py from typing import TypedDict from langgraph.graph import StateGraph, START, END class WorkState(TypedDict): input_text: str step_count: int def step_one(state: WorkState): print(f节点 step_one 收到: {state[input_text]}) return {step_count: state[step_count] 1} def step_two(state: WorkState): print(f节点 step_two 执行当前 step_count {state[step_count]}) return {step_count: state[step_count] 1} # 1. 创建 StateGraph并传入 State 结构 builder StateGraph(WorkState) # 2. 添加节点 builder.add_node(step_one, step_one) builder.add_node(step_two, step_two) # 3. 添加边入口 - step_one - step_two - 出口 builder.add_edge(START, step_one) builder.add_edge(step_one, step_two) builder.add_edge(step_two, END) # 4. 编译并运行 graph builder.compile() result graph.invoke({ input_text: hello langgraph, step_count: 0, }) print(最终 State:, result)运行方式python demo1_basic_graph.py预期输出节点 step_one 收到: hello langgraph 节点 step_two 执行当前 step_count 1 最终 State: {input_text: hello langgraph, step_count: 2}这个示例虽然简单但能说明 LangGraph 的核心机制step_one 返回的 step_count 会自动更新到 Statestep_two 读取到的 step_count 已经是 1step_two 返回后State 的 step_count 变成 2而 step_one 没有返回的 input_text 字段仍然被保留在最终 State 中。你不需要手动把 input_text 传给 step_two也不需要维护中间变量。所有节点都从一个 State 里读数据再把新数据写回同一个 State这正是 LangGraph 和传统链式调用最大的区别。4.2 示例二引入大模型做一个最小问答 Agent第二个示例里节点内部不再是纯计算而是调用一次大模型。这个图只有一个节点结构非常简单但它证明了“LLM 可以被包在节点里并作为图的一部分运行”。新建demo2_llm_agent.py# 文件路径demo2_llm_agent.py from typing import TypedDict from langchain_openai import ChatOpenAI from langgraph.graph import StateGraph, START, END # 这里假设环境变量 OPENAI_API_KEY 已配置 llm ChatOpenAI(modelgpt-4o-mini, temperature0) class QAState(TypedDict): question: str answer: str def call_llm(state: QAState): response llm.invoke(state[question]) return {answer: response.content} builder StateGraph(QAState) builder.add_node(llm_node, call_llm) builder.add_edge(START, llm_node) builder.add_edge(llm_node, END) graph builder.compile() result graph.invoke({ question: 用一句话解释 LangGraph 是什么, answer: , }) print(回答, result[answer])运行python demo2_llm_agent.py如果配置了 API Key会输出模型生成的内容如果没有配置 Key会看到鉴权相关的报错。这个示例最有价值的点在于节点函数内部可以调用任何外部服务。LLM、数据库、HTTP 接口、本地工具都可以封装成一个节点。LangGraph 不关心节点内部做了什么它只负责保证节点按图的规则被调用并把更新后的 State 传给下一个节点。这两个示例跑通后你已经掌握了 LangGraph 最基本的开发循环定义 State写节点函数连边编译调用。接下来要解决的问题是如果流程不是一条直线而是需要判断和循环该怎么办这就是 Conditional Edge 的内容。5. 条件分支与循环Conditional Edge 完整实战真实业务几乎没有一条直线走到底的流程。用户输入合法才继续处理失败就重试超过最大次数就终止。LangGraph 解决这类需求的方式就是条件路由。5.1 场景建模自动重试的 Agent设计一个简单的场景Agent 最多执行三次。前两次执行时状态里标记“还需要继续处理”第三次执行时给出最终答案并走到 END。这个场景跟 ReAct Agent 的“思考-行动-观察”循环非常相似只是我们先用纯函数模拟方便观察控制流。新建demo3_conditional_edge.py# 文件路径demo3_conditional_edge.py from typing import TypedDict from langgraph.graph import StateGraph, START, END class AgentState(TypedDict): query: str attempt: int max_attempts: int answer: str def agent_node(state: AgentState): attempt state[attempt] 1 # 实际项目中这里会调用 LLM 或其他处理逻辑 if attempt state[max_attempts]: answer f第 {attempt} 次尝试后给出最终回答{state[query]} else: answer 还需要继续处理 return {attempt: attempt, answer: answer} def router(state: AgentState): # 根据 answer 内容判断是继续还是结束 if state[answer].startswith(第): return finish return continue_agent builder StateGraph(AgentState) builder.add_node(agent, agent_node) builder.add_edge(START, agent) builder.add_conditional_edges( agent, router, { continue_agent: agent, finish: END, }, ) graph builder.compile() result graph.invoke({ query: 帮我写一个递归函数, attempt: 0, max_attempts: 3, answer: , }) print(最终结果, result)运行python demo3_conditional_edge.py预期输出最终结果 {query: 帮我写一个递归函数, attempt: 3, max_attempts: 3, answer: 第 3 次尝试后给出最终回答帮我写一个递归函数}观察执行过程第 1 次 agent_node 执行后router 判断 answer 不以“第”开头返回 continue_agent于是再次进入 agent 节点第 3 次 agent_node 执行后router 判断 answer 以“第”开头返回 finish于是走到 END。整张图形成了“节点自身到自身”的循环这正是 Agent 自我迭代的基本形态。5.2 条件路由函数的设计规范条件路由函数本身也是一个接收 State、返回字符串的函数。它返回的字符串必须与 add_conditional_edges 的 mapping 里的 key 完全一致否则 LangGraph 会报错。为了降低排错难度建议路由函数保持纯粹只做判断不修改 State。如果你想在路由前记录日志、修改某个字段应该把它放在节点里完成而不是塞进路由函数。def router(state: AgentState): # 好的写法只负责返回下一个节点名称 if state[attempt] state[max_attempts]: return finish return continue_agent5.3 循环上限与防死循环如果条件路由写错了比如 router 永远返回 continue_agent图就会陷入无限循环。LangGraph 默认会限制递归深度超过限制时会抛出 RecursionError。你也可以通过 config 主动调整上限graph.invoke( state, {recursion_limit: 50}, )对生产环境来说与其依赖默认上限不如在 State 里加一个类似 step_count、attempt 的计数并在节点内强制判断。这样即使路由逻辑出现意外流程也不会无限消耗资源和费用。条件边还有一个高频用途把用户请求路由到不同 Agent这就引出了多 Agent 协作。6. 多 Agent 协作实战Supervisor 路由模式6.1 为什么需要多 Agent单 Agent 在简单任务上表现不错但业务复杂后把所有能力都塞进一个 Agent 会导致两个问题一是提示词越来越长模型容易混淆规则二是不同任务对工具、Prompt 的要求差异很大强行统一反而降低准确率。多 Agent 的思路是拆分每个子 Agent 只负责一个垂直领域由“主管 Agent”根据用户请求判断该找谁。这种模式在 LangGraph 里实现成本很低因为它本质上是条件边在不同节点之间选择而不是在代码里写一长串 if/else。6.2 Supervisor 模式的核心结构多 Agent 协作有两种常见结构第一种是“路由分发模式”一个 Supervisor 节点分析用户输入然后把任务直接分发到对应的 Worker 节点。这个模式简单高效适合子 Agent 之间不需要相互协作的场景。第二种是“团队讨论模式”多个 Worker 节点可以互相传递信息最后由汇总节点生成结论。这个模式更灵活但控制复杂度和成本都会显著提升。本文先实现第一种因为它最能体现 Edge 在 Agent 协作中的价值。6.3 代码实现条件边路由 Worker新建demo4_multi_agent.py# 文件路径demo4_multi_agent.py from typing import TypedDict from langgraph.graph import StateGraph, START, END class TeamState(TypedDict): user_request: str current_agent: str final_answer: str def supervisor(state: TeamState): text state[user_request] if 计算 in text or 数字 in text: return calculator_agent if 搜索 in text or 资料 in text: return research_agent return general_agent def calculator_agent(state: TeamState): # 实际项目中这里可以调用计算工具或代码执行器 return { final_answer: f计算 Agent 已处理{state[user_request]}, current_agent: calculator, } def research_agent(state: TeamState): # 实际项目中这里可以调用检索工具或爬虫 return { final_answer: f检索 Agent 已处理{state[user_request]}, current_agent: research, } def general_agent(state: TeamState): # 兜底 Agent处理未命中的请求 return { final_answer: f通用助手回答{state[user_request]}, current_agent: general, } builder StateGraph(TeamState) builder.add_node(calculator_agent, calculator_agent) builder.add_node(research_agent, research_agent) builder.add_node(general_agent, general_agent) builder.add_conditional_edges( START, supervisor, { calculator_agent: calculator_agent, research_agent: research_agent, general_agent: general_agent, }, ) builder.add_edge(calculator_agent, END) builder.add_edge(research_agent, END) builder.add_edge(general_agent, END) graph builder.compile() test_cases [ 帮我计算 23 * 17 等于多少, 帮我搜索一下 LangGraph 的最新文档, 给我讲个笑话, ] for case in test_cases: result graph.invoke({ user_request: case, current_agent: , final_answer: , }) print(f用户{case}) print(f路由到{result[current_agent]}) print(f回答{result[final_answer]}) print(- * 50)运行python demo4_multi_agent.py预期输出用户帮我计算 23 * 17 等于多少 路由到calculator 回答计算 Agent 已处理帮我计算 23 * 17 等于多少 -------------------------------------------------- 用户帮我搜索一下 LangGraph 的最新文档 路由到research 回答检索 Agent 已处理帮我搜索一下 LangGraph 的最新文档 -------------------------------------------------- 用户给我讲个笑话 路由到general 回答通用助手回答给我讲个笑话 --------------------------------------------------这个示例展示了多 Agent 图结构的基本骨架从 START 出发经过一个路由判断到达对应的 Worker 节点最后统一走向 END。每个 Worker 节点内部目前是模拟逻辑但你可以直接把它替换成真实的 LLM 调用或工具调用图结构本身不需要改变。6.4 从规则路由升级到 LLM 路由上面示例里的 supervisor 函数用的是关键词匹配实现简单但不够“智能”。真实项目中supervisor 通常会调用一次大模型让模型决定任务应该分给哪个 Agent。大致的升级思路如下def supervisor(state: TeamState): prompt f你是一个任务分发器根据用户请求决定交给哪个子 Agent。 可选 Agentcalculator_agent, research_agent, general_agent 用户请求{state[user_request]} 只输出 Agent 名称不要解释。 response llm.invoke(prompt) agent_name response.content.strip() # 做一层白名单校验防止模型返回未知节点 if agent_name not in [calculator_agent, research_agent, general_agent]: agent_name general_agent return agent_name关键点在于无论路由逻辑用规则还是用 LLM条件边的机制不变。你只需要让函数返回一个合法的节点名即可。这也是 LangGraph 这类图编排框架的优势所在控制流结构稳定路由策略可以随时替换。更复杂的多 Agent 协作还可以用 LangGraph 的 Send API 实现并行 fan-out让多个子 Agent 同时处理不同任务再合并结果。零基础阶段先掌握 Supervisor 路由模式并行模式可以作为下一步深入方向。7. 常见问题与排查方法LangGraph 初学者的报错大多集中在 State 字段不一致、条件边映射错误、循环不终止这三类。下面整理了一套高效排查表。问题现象可能原因排查方式解决方案运行时报错 KeyError初始化 State 时缺少节点后续需要的字段检查 invoke 传入的字典是否完整打印节点输入在初始 State 中补齐所有字段或给节点函数设置默认值图不结束报 RecursionError条件路由一直走回自身陷入死循环检查路由函数返回值打印 attempt 等计数字段调整路由逻辑或在 config 中设置 recursion_limit但根治方案是加循环保护条件边报错提示 invalid key路由函数返回的字符串不在映射表里在路由函数里打印返回值和 mapping 的 key让返回值和 mapping key 完全一致建议用常量或枚举管理节点名LLM 节点返回的内容写不进 State节点返回字典的 key 与 State 定义不一致打印 response 的类型和字段统一字段名比如 answer 而不是 response_content节点没有执行直接跳过Edge 连接错误或条件路由未命中检查 add_edge 和 add_conditional_edges 的 mapping确认 START 到目标节点的链路存在并且映射表覆盖所有返回值状态被覆盖而不是追加多个节点向同一字段写入且未定义 reducer检查 State 定义里该字段是否有 Annotated reducer如果需要合并多段文本改成 Annotated 列表并指定 operator.add除了表格里的问题还有一点值得提醒LangGraph 报错信息有时会很长因为它会打印出内部执行的轨迹。遇到报错不要只看最后一行往上翻找到“哪个节点、哪个函数报错”是关键定位手段。8. 最佳实践与工程建议会写示例不等于能上生产。LangGraph 项目的工程质量往往体现在下面这些细节里。8.1 State 设计保持克制State 是全局共享的所以字段数量要克制。能放在节点内部作为局部变量的数据不要全塞进 State。一个常见反例是把所有中间计算结果、临时变量、日志全部写进 State导致每次图调用都要传递一个巨大的字典调试困难也增加 token 消耗。推荐做法State 里只放“跨节点必须共享的数据”。比如用户输入、最终答案、消息历史、尝试次数。某个节点私有的中间变量定义成函数局部变量即可。8.2 节点命名和路由命名统一管理节点名和条件边映射 key 是字符串写错不会在编译时报错只会在运行时暴露。建议用常量管理节点名class NodeName: AGENT agent ROUTER router CALCULATOR calculator_agent这样写 add_node、add_edge 时就不会出现大小写不一致的低级错误。8.3 条件路由函数保持“无副作用”路由函数最好只读 State 并返回节点名字符串不要在里面修改 State、调用外部服务、打印大量日志。因为路由函数很可能在流程中被多次调用副作用会导致难以预料的重复执行。8.4 为每个节点设置超时大模型调用可能因为网络或服务限流变慢甚至卡住。LangGraph 的节点需要关注超时控制。你可以在节点函数内部给 LLM 调用设置 timeout也可以在上层编排中设置整体超时。特别是生产环境这是控制成本和安全边界的重要手段。8.5 用 Checkpointer 实现持久化和长期记忆LangGraph 的 Checkpointer 机制可以把图的状态保存下来让对话被打断后能恢复。这也是 LangGraph 实现长期记忆的关键路径。官方提供了多种持久化方案从内存版到数据库版你可以根据阶段选择。from langgraph.checkpoint.memory import InMemorySaver checkpointer InMemorySaver() graph builder.compile(checkpointercheckpointer)有了 Checkpointer再配合 config 里的 thread_id就能实现“不同用户的多个会话互不干扰”的效果。这是走向生产环境时必须用到的能力。8.6 测试和可观测性建议对每个节点单独写单元测试因为节点就是普通函数给定输入就可以断言输出。整图测试可以使用假的 LLM 结果来模拟避免每次跑测试都消耗真实 API 费用。在调试阶段可以给每个节点加一行关键日志打印输入输出的核心字段。进入复杂业务后建议接入 LangSmith 或者自建日志体系把每次图执行的节点路径、耗时、token 用量都记录下来。8.7 安全边界与合法授权多 Agent 协作场景下Worker 节点可能会调用文件、数据库、网络等工具。工具函数必须做权限校验限制操作范围。用户输入不能直接拼进命令或 SQL涉及删除、覆盖、跨系统操作时必须经过二次确认。任何生产环境变更都建议先在测试环境验证并保留备份与回滚方案。9. 总结与后续学习方向到这里你已经把 LangGraph 最核心的开发闭环完整跑通了一遍用 State 共享数据用 Node 封装执行逻辑用 Edge 和 Conditional Edge 控制流程再用一个多 Agent 示例把条件路由应用到真实协作场景。回头看LangGraph 的真正价值在于把 Agent 的复杂度拆成了状态、节点、边三个维度。控制流被显式表达成图结构之后代码不再是密不透风的 if/else 森林而是一张可以观察、可以测试、可以逐步替换的拓扑图。这也是它区别于“调用几次模型”这类方案的根本之处。下一步建议按这个顺序深入实践先阅读 LangGraph 官方文档里的入门教程把“工具调用 Agent”完整做一遍然后尝试加入 Checkpointer实现跨轮对话的记忆再尝试给节点接入真实工具比如数据库查询、文件操作最后学习 Send API 的并行任务以及如何把图部署成服务。学习 LangGraph 最忌讳的是只看文档不写代码或者一上来就抄复杂仓库。先用最简例子跑通图的基本流程再一点点增加节点和边遇到问题就按本文第 7 节的排查思路定位。只要把 State、Node、Edge 这套思维模型建起来后续大多数进阶内容都是在这三个概念上做扩展。建议收藏这篇文章在你第一次写条件边报错时它会比搜索更高效。