Agent 上线就崩?LangGraph 把 Demo 变成生产系统的最后一公里

发布时间:2026/8/9 15:19:06
Agent 上线就崩?LangGraph 把 Demo 变成生产系统的最后一公里 《LangGraph并不难难的是知道什么时候不该用》看起来是个大话题但真落到项目里常常就是几个具体选择。下面我尽量按实际开发时会遇到的问题来讲。摘要前阵子帮一个团队做 Code Review他们的 Agent 在本地跑得好好的一问模型也是最新的结果上线第一天就炸了。不是模型调用失败而是状态乱了。用户问了一个边缘问题Agent 卡在一个循环里日志里全是Max iterations exceeded但没人知道它到底卡在哪一步。更糟糕的是当用户追问时上下文已经被污染了整个对话逻辑彻底偏离。这时候我才意识到LangGraph 的真正价值不在于“让 Agent 能动起来”而在于“让 Agent 在失控前能被叫停”。很多开发者把 LangGraph 当成 LangChain 的替代品其实这是个误区。LangChain 擅长单点任务的编排比如“调用工具 - 解析结果 - 返回”。但一旦任务涉及多步决策、条件分支、甚至人工介入那种线性思维就会失效。今天不聊怎么搭个 Hello World聊聊怎么把 LangGraph 写成能扛住生产流量的系统。目录为什么脚本式 Agent 撑不住生产环境State别让数据在函数间裸奔Edge条件分支是稳定性的关键人工审批节点生产环境的必要妥协工程化落地日志、监控与回滚总结什么时候不该用 LangGraph为什么脚本式 Agent 撑不住生产环境我们早期的 Agent 写法通常是这样的def agent_step(state): thought llm.invoke(state[messages]) action parse_action(thought) if action search: result search_tool(action.input) return state result elif action confirm: return wait_for_human()这种写法在 Demo 阶段没问题但它有三个致命缺陷1. 状态不可追溯。一旦出错你只能看最后的输出不知道中间经历了多少次循环、调用了什么工具。2. 没有边界。如果模型幻觉严重可能陷入无限递归直到超时。3. 无法中断。用户中途退出或者需要人工确认时系统不知道停在哪一步。LangGraph 的核心思想是显式定义状态和转换。它强制你把 Agent 看作一个图Graph每个节点Node是一个函数每条边Edge是一个条件判断。这种显式化是工程化的第一步。State别让数据在函数间裸奔在 LangGraph 中State是所有节点共享的唯一数据源。我见过太多人用dict当 State结果不同节点之间字段命名混乱A 节点写user_idB 节点读uid最后排查时一脸懵。建议的做法是定义一个 TypedDict 或 Pydantic BaseModel明确每个字段的类型和默认值。from typing import TypedDict, Annotated import operator class AgentState(TypedDict): messages: Annotated[list, operator.add] # 消息列表自动追加 user_id: str current_step: str tool_results: dict is_approved: bool # 人工审批标志注意operator.add这个注解。它告诉 LangGraph当新消息写入时不要覆盖旧消息而是追加。这对于保持对话历史至关重要。实战建议State 设计要遵循“最小必要原则”。不要把所有中间变量都塞进去只放节点间需要传递的数据。临时变量就在节点内部处理保持 State 干净。Edge条件分支是稳定性的关键图中的边决定了流程走向。LangGraph 支持两种边1. 普通边固定从节点 A 到节点 B。2. 条件边根据 State 的值动态决定走向。最常见的场景是“工具调用后判断是否需要继续循环”。from langgraph.graph import StateGraph, END def should_continue(state: AgentState) - str: last_message state[messages][-1] if tool_call in last_message.content: return tools # 继续调用工具 return finalize # 结束生成最终答案 workflow StateGraph(AgentState) workflow.add_node(agent, agent_node) workflow.add_node(tools, tool_node) workflow.add_conditional_edges( agent, should_continue, { tools: tools, finalize: END } )这里有一个容易被忽视的细节条件函数必须是确定性的。如果你依赖模型输出的随机性来做分支判断调试时会非常痛苦。最好是在节点内部把模型输出解析成结构化数据再根据结构化数据做分支。人工审批节点生产环境的必要妥协这是很多 Demo 里缺失的一环也是生产环境最容易被忽视的稳定性保障。当 Agent 执行高风险操作比如删除数据、发送邮件、调用支付接口时必须插入一个人工审批节点。def human_approval_node(state: AgentState) - AgentState: # 这里可以集成消息队列或 UI 回调 # 比如发送 Slack 消息等待 webhook 返回 approval wait_for_human_action(state[pending_action]) state[is_approved] approval return state workflow.add_node(human_approval, human_approval_node) workflow.add_edge(tools, human_approval) workflow.add_conditional_edges( human_approval, lambda s: finalize if s[is_approved] else retry, {finalize: END, retry: agent} )踩坑经验人工审批节点必须是异步的。不要让 HTTP 请求阻塞线程。在我的项目里我们用了 Redis 作为状态存储审批节点写入 Redis等待回调更新。这样即使服务重启状态也不会丢失。工程化落地日志、监控与回滚写完图只是第一步。在生产环境中你需要回答三个问题1. 现在走到哪一步了2. 如果出错怎么回滚3. 怎么监控性能瓶颈1. 可观测性检查点CheckpointerLangGraph 内置了 Checkpointer 机制。每次状态更新都会保存到后端内存、SQL、Redis 等。这意味着你可以随时“回溯”到之前的状态。from langgraph.checkpoint.memory import MemorySaver memory MemorySaver() graph workflow.compile(checkpointermemory) # 执行时传入 thread_id thread_config {config: {configurable: {thread_id: user_123}}} result graph.invoke(input, thread_config)通过thread_id你可以查询某个用户的所有历史交互甚至恢复到上一步状态重新执行。这对于调试和合规审计至关重要。2. 异常兜底超时与重试不要依赖模型的稳定性要依赖工程的容错性。最大迭代次数在StateGraph编译时设置recursion_limit。节点超时每个节点函数内部设置超时超时后抛出异常由全局异常处理器捕获。降级策略当工具调用失败时返回一个默认的兜底回答而不是让 Agent 卡死。import asyncio async def tool_node(state: AgentState) - AgentState: try: result await asyncio.wait_for( call_external_api(state[query]), timeout5.0 ) state[tool_results] result except asyncio.TimeoutError: state[tool_results] {error: timeout} # 可以选择标记状态让 agent 节点生成一个“查询超时”的回复 return state3. 监控关键指标上生产前务必接入以下监控节点执行时间识别哪个节点是瓶颈。条件分支分布了解 Agent 最常走哪条路是否有异常路径占比过高。人工审批率如果审批率接近 100%说明 Agent 太激进需要调整 Prompt 或工具定义。总结什么时候不该用 LangGraph最后说个反直觉的观点LangGraph 不是万能的。如果你的 Agent 只是简单的“问答 检索”用 LangChain 的Chain或RunnableSequence就够了。引入 LangGraph 会增加复杂度需要维护 State、Node、Edge调试成本更高。建议的使用场景多步决策流程如分析 - 规划 - 执行 - 验证需要人工介入的环节需要状态持久化和回溯的场景复杂的条件分支逻辑不建议使用的场景单轮对话无状态简单的 RAG 管道原型验证阶段先用简单框架跑通逻辑Agent 从 Demo 到生产差的不是模型能力而是对状态、边界和异常的控制力。LangGraph 提供的是这套控制力的基础设施但怎么用取决于你对业务场景的理解。下次再写 Agent 时先画一张图再写代码。这一步能省掉你一半的上线事故。资料展示下面是我整理的AI大模型学习资料和工具包预览适合收藏后按主题逐步学习。如果你想看完整资料目录可以在评论区留言「资料」也欢迎告诉我你更关注AI大模型里的哪类内容。