ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

剖析 LangGraph:从 Agent Loop 到 State 驱动的可控 Agent

剖析 LangGraph:从 Agent Loop 到 State 驱动的可控 Agent 上一篇我们拆解了Agent Loop。Agent 并不是 LLM 自己在循环而是由 Runtime 驱动LLM 做决策 → Runtime 执行 → State 更新 → 再次调用 LLM → ……那么问题来了如果我们不满足于一个简单的 Agent Loop而是希望构建一个真正可暂停、可恢复、可调试、可控制的 Agent该怎么办这正是LangGraph要解决的问题。一、LangGraph 到底是什么可以先用一句话理解LangGraph 是一个以 State 为核心、以 Graph 为控制结构用于构建复杂 Agent 工作流的运行框架。它的基本组成可以抽象为Graph Nodes State Routing其中Node执行一个具体步骤State节点之间共享的工作记忆Edge / Routing决定下一步执行什么LangGraph 官方文档给出的核心思路也是如此先把 Agent 拆解成离散步骤再定义节点之间的决策与转换最后通过共享 State 将这些节点连接起来。这和传统 Workflow 最大的区别在于流程不是简单写死的而是可以在节点执行过程中根据 State 和结果进行动态路由。二、第一步不要先写 Agent先拆业务流程这是理解 LangGraph 最重要的一步。假设我们要构建一个「客服邮件 Agent」。需求可能是读取客户邮件判断问题类型和紧急程度查询相关文档创建 Bug 工单生成回复必要时人工审核发送邮件不要一上来就写一个巨大的 Prompt“你是一个客服 Agent请完成以上所有工作……”LangGraph 的思路恰恰相反先把复杂任务拆成一个个离散步骤。例如START ↓ Read Email ↓ Classify Intent ↓ ┌──────────────┬──────────────┐ ↓ ↓ ↓ Doc Search Bug Track Human Review └──────────────┴──────────────┘ ↓ Draft Reply ↓ Human Review ↓ Send Reply ↓ END每一个步骤就是一个 Node。官方示例正是按照这种方式将邮件处理拆成Read Email、Classify Intent、Doc Search、Bug Track、Draft Reply、Human Review和Send Reply等节点。三、Node本质上就是一个函数LangGraph 中 Node 并没有神秘之处。最简单的理解Node 接收 State → 执行工作 → 返回 State 更新例如defsearch_documentation(state):querybuild_query(state)resultssearch(query)return{search_results:results}一个 Node 可以调用LLM数据库API搜索引擎Python 函数外部工具人工输入因此Node 并不等于“LLM”。官方文档实际上把节点分成不同类型① LLM Node负责理解分类推理生成② Data Node负责查询数据库搜索知识库获取客户历史③ Action Node负责调 API创建工单发送邮件执行外部操作④ Human Input Node负责人工审核补充信息人机协作这意味着LangGraph 不是“LLM 工作流”而是可以把 LLM、工具、代码和人统一组织起来的执行图。四、真正的核心State如果说 Node 是“手”那么 State 就是 Agent 的“工作记忆”。LangGraph 中所有节点都可以读取共享 State并向 State 写入更新。例如classEmailAgentState(TypedDict):email_content:strsender_email:strclassification:dict|Nonesearch_results:list[str]|Nonecustomer_history:dict|Nonedraft_response:str|None整个 Agent 执行过程中Email ↓ State ↓ Classification ↓ State ↓ Search Results ↓ State ↓ Draft Response ↓ State因此后面的节点并不需要重新询问前面的节点。它们只需要读取当前 State。五、一个非常重要的设计原则State 保存原始数据这是这篇 LangGraph 文档里非常值得注意的一个设计思想State 保存原始数据而不是保存格式化后的 Prompt。例如不要把请根据以下客户邮件判断紧急程度……直接存进 State。而应该保存{email_content:...,sender_email:...,classification:{...}}真正需要调用 LLM 时再根据当前节点的需求构造 Prompt。这样做有几个好处第一解耦。不同节点可以用不同方式使用同一份数据。第二容易调试。你可以直接看到 Agent 到底拿到了什么原始信息。第三Prompt 可以独立演进。修改 Prompt 不需要修改 State 结构。第四更适合长期运行的 Agent。State 是数据Prompt 是执行逻辑。两者不应该混在一起。六、RoutingAgent 为什么能够“自己选择下一步”这又回到了我们之前研究的 Agent Loop。例如classificationllm.invoke(...)ifclassification[intent]bug:gotobug_trackingelifclassification[intent]question:gotosearch_documentationelse:gotodraft_response这里发生了一个非常重要的变化LLM 不直接执行工具。LLM 产生的是结构化决策Runtime 根据这个决策选择下一节点并执行。在 LangGraph 中可以通过Command同时完成State Update Goto例如returnCommand(update{classification:classification},gotosearch_documentation)这实际上就是 Agent Loop 中Decision → Routing → Execution的具体工程实现。七、为什么 LangGraph 不是简单的 Workflow传统 Workflow 往往是A → B → C → D路径基本确定。而 Agent 的执行过程可能是A ↓ B ↓ ┌────→ C ────┐ │ ↓ ├────→ D → E │ ↓ └────→ Human ─┘ ↓ F下一步可能由LLM 判断State条件工具结果人工输入共同决定。因此 LangGraph 更准确的理解是用 Graph 描述可能的执行空间用 State 保存当前执行状态用 Routing 决定当前实际路径。八、Human-in-the-loopAgent 可以暂停这是 LangGraph 非常重要的能力。例如LLM 生成回复 ↓ 发现是高风险问题 ↓ Human Review ↓ 暂停 ↓ 等待人工 ↓ 人工批准 / 修改 / 拒绝 ↓ 继续执行LangGraph 使用interrupt()暂停图的执行。更重要的是它不是简单地 sleep。执行状态会被保存之后可以从暂停位置继续运行。官方示例通过 Checkpointer 保存状态并使用thread_id标识一次持续的执行上下文。人工输入后可以继续调用图让 Agent 从中断的位置恢复。这意味着 Agent 开始具备暂停 → 等待 → 恢复的能力。这对于真实业务非常重要。九、Error 不是异常情况而是 Agent 流程的一部分真实世界里的 Agent 不可能永远成功。网络可能超时API → Timeout模型可能产生错误工具调用LLM → Tool Call → Error用户可能没有提供必要信息Agent → 缺少客户 IDLangGraph 的思路不是简单try:...except:pass而是根据错误类型采取不同策略。错误处理者策略网络/限流系统Retry工具/解析错误LLM写入 State → 再循环缺少用户信息人类interrupt未知异常开发者冒泡调试这实际上把Error Handling提升成了Agent Control Flow官方文档明确将错误处理纳入 Agent 的设计过程而不是把它当作代码最后补上的异常处理。十、为什么 Node 不应该无限做大这是 LangGraph 一个非常值得工程师思考的问题。例如Node A ├─读取邮件 ├─调用 LLM ├─查询数据库 ├─搜索知识库 ├─生成回复 └─发送邮件当然可以。但如果中途失败执行到第 90% ↓ 发生错误整个 Node 可能需要重新执行。如果拆成Read ↓ Classify ↓ Search ↓ Draft ↓ Review ↓ Send那么每个节点都可以成为Checkpoint 边界。失败后只需要从较近的位置恢复。同时小节点还有更好的可观测性更容易调试更容易测试更容易配置不同 Retry 策略更容易复用因此Node 粒度本质上是在“代码简单性”和“可恢复性、可观测性”之间做权衡。LangGraph 官方文档也特别强调了节点粒度与持久化、调试、故障恢复之间的关系。十一、把 LangGraph 放回 Agent Loop现在回头看上一篇讲的 Agent Loop┌───────────────┐ │ State │ └───────┬───────┘ ↓ Model ↓ Decision ↓ Routing ↓ Node ↓ Tool / API ↓ State Update │ └──────────→ ModelLangGraph 做的事情就是把这个 Loop 工程化。它增加了State Nodes Routing Persistence Retry Timeout Human-in-the-loop Streaming Observability于是Agent Loop 从一个简单的“循环调用模型”变成了一个可观察、可控制、可恢复的状态化执行系统。十二、LangGraph 的本质不是画图而是管理“状态变化”很多初学者容易产生一个误解LangGraph 把 Agent 画成流程图。其实不是。Graph 只是表现形式。真正重要的是State 如何变化。可以把一次 Agent 执行理解成State₀ ↓ Node₁ ↓ State₁ ↓ Node₂ ↓ State₂ ↓ Node₃ ↓ State₃Graph 决定下一步可以去哪State 决定Agent 当前知道什么Node 决定当前要做什么Checkpoint 决定出问题之后从哪里恢复这四个概念组合起来才构成 LangGraph 的核心。十三、最终理解LangGraph 在 Agent 架构中的位置如果把现代 Agent 拆成几个层次┌─────────────────┐ │ LLM │ │ 理解 / 推理 / 决策 │ └────────┬────────┘ ↓ ┌─────────────────┐ │ Agent Runtime │ │ │ │ State │ │ Routing │ │ Tools │ │ Persistence │ │ Retry │ │ HITL │ └────────┬────────┘ ↓ ┌─────────────────┐ │ External World│ │ API / DB / Web │ │ Code / Human │ └─────────────────┘LLM 负责“下一步应该做什么”LangGraph 负责“把这个决策变成一个可执行、可暂停、可恢复、可追踪的过程。”所以可以把 LangGraph 理解成Agent 的状态化 Runtime / Orchestration Layer。十四、一句话总结如果说Agent Loop解决的是Agent 如何循环工作那么LangGraph解决的是如何把这个循环变成一个真正能够处理复杂状态、动态路由、错误恢复和人机协作的工程系统最终可以浓缩成一个公式LangGraph State Nodes Routing Persistence Control而它背后的设计思想可以进一步浓缩成一句话把 Agent 从“黑盒调用模型”变成“可观察、可控制、可恢复的状态化工作流”。这也是理解 LangGraph、Deep Agents以及更复杂 Agent Runtime 架构的一把关键钥匙。
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进