这篇不先堆名词。我们把《LangGraph跑通那天我才发现前面的学习顺序反了》拆成几级台阶看完至少知道下一步该学什么、该练什么。摘要去年年底我花两周搭了个Agent Demo能自动查订单、调API、生成报告同事看了都说这东西能省一半人力。上周真正要接进生产环境被运维按住了——权限没配日志没有出事了连错从哪来都不知道。那一刻我才意识到LangGraph跑通只是第一步后面的坑比写代码还多。今天想把这段经历摊开说说特别是那些教程里不会写、但上线前必须解决的问题。---目录从脚本式Agent到可控系统的鸿沟State与Node别再把状态塞进全局变量Edge与条件分支流程控制比写节点难人工审批节点权限控制的真正入口工程化落地日志、权限、可观测性总结Demo和生产的距离是工程化能力从脚本式Agent到可控系统的鸿沟早期做Agent我习惯写链式调用调用模型 → 解析结果 → 调用工具 → 再次调用模型。这种写法在Demo阶段完全够用但有两个致命问题一是状态无处安放。每个节点之间靠全局变量或返回值传递稍微复杂一点就需要手动维护上下文调试的时候根本不知道状态在哪一步丢的。二是流程不可回溯。一旦某个环节出错你只能从头重跑没有断点、没有快照复现问题全靠猜。LangGraph引入的图结构解决的就是这两个问题。它把Agent拆成节点和边每个节点执行一个动作边控制流转逻辑整个工作流是一个有向图。更重要的是图有State——一个显式的状态容器所有节点共享、修改、读取。这个设计看起来简单但真正用起来才发现它把写代码和管流程分开了。你不再需要自己写状态管理代码LangGraph替你存、替你传。---State与Node别再把状态塞进全局变量我第一次用LangGraph时犯了一个典型错误在Node里直接操作外部变量。# 错误示范Node里偷偷改外部状态 context {user_id: None, order_status: None} def check_order(state): # 假装从外部改了context context[order_status] shipped return {messages: [AIMessage(content订单已发货)]} graph.add_node(check, check_order)这种写法在Demo里跑通了但一旦并发进来或者要加日志、加权限检查立刻炸锅。LangGraph的State设计就是为了让你显式地传递状态而不是偷偷摸摸地改全局变量。正确的做法是把所有需要跨节点共享的数据都放进State schema里from langgraph.graph import StateGraph, START, END from typing import TypedDict, Annotated import operator class AgentState(TypedDict): user_id: str order_id: str order_status: str messages: Annotated[list, operator.add] approval_required: bool graph StateGraph(AgentState)这里用operator.add来累加messages是因为LLM对话历史需要追加而不是覆盖。这个细节教程里经常一笔带过但实际用的时候很容易踩坑。---Edge与条件分支流程控制比写节点难节点好写边难调。我接手的第一个真实需求是用户查询订单如果订单金额超过5000元需要人工审批才能继续。这个逻辑在代码里长这样def should_approve(state: AgentState) - str: if state[order_status] pending and state.get(amount, 0) 5000: return need_approval return auto_process graph.add_conditional_edges( check_order, should_approve, { need_approval: human_review, auto_process: finalize } )条件分支的问题不在于写出来而在于测试它。Demo阶段你手动触发几次就能覆盖所有路径但真实场景下你需要保证每种分支都有对应的日志记录、权限校验和异常处理。我的经验是每加一个条件分支就问自己三个问题——这个分支有日志吗这个分支有权限控制吗这个分支失败后State能被正确回滚吗---人工审批节点权限控制的真正入口这是我最想强调的部分。很多教程讲到人工介入就停了但真正上线时审批节点才是权限控制的咽喉。我见过的最典型的坑Agent调了写操作API但审批节点没有校验当前用户是否有这个权限。结果某个普通用户触发了审批流程审批通过后就直接写库了。正确的做法是把权限校验放在审批节点之前def human_review(state: AgentState) - AgentState: # 1. 先校验当前用户是否有审批权限 if not check_approval_permission(state[user_id]): raise PermissionError(f用户 {state[user_id]} 无审批权限) # 2. 记录审批日志 log_event(approval_requested, { user_id: state[user_id], order_id: state[order_id], amount: state.get(amount) }) # 3. 等待人工输入实际项目中这里会阻塞并推送通知 approval wait_for_human_input() return { approval_result: approval, messages: [HumanMessage(contentf审批结果: {approval})] }注意log_event这个调用。很多团队在Demo阶段不写日志上线后出问题只能靠翻代码猜。审批节点是天然的日志埋点位置因为这里是人工介入的边界所有进入这个节点的请求都应该有记录。---工程化落地日志、权限、可观测性LangGraph本身不提供日志和权限系统这些需要你自己接。我踩过的坑总结成三条建议第一给每个节点加执行日志。import time import logging logger logging.getLogger(__name__) def check_order(state: AgentState) - AgentState: start time.time() logger.info(f[check_order] 开始处理, order_id{state[order_id]}) # 实际业务逻辑 result fetch_order_from_db(state[order_id]) elapsed time.time() - start logger.info(f[check_order] 完成, 耗时{elapsed:.2f}s, status{result.get(status)}) return { order_status: result.get(status), messages: [AIMessage(contentf订单状态: {result.get(status)})] }不要嫌烦。上线后出问题日志是你唯一的线索。第二权限校验集中在一个层不要散落在节点里。我见过把权限检查写在每个Node里的项目后来加一个新的权限维度改了一整天。正确做法是写一个中间件或者在图的入口处统一校验def auth_middleware(state: AgentState) - AgentState: 统一权限校验 user_id state[user_id] # 查询用户权限配置 permissions get_user_permissions(user_id) # 校验当前操作是否需要特定权限 required_permission determine_required_permission(state) if required_permission and required_permission not in permissions: raise PermissionError(f缺少权限: {required_permission}) return state第三用LangGraph的checkpoint机制做状态快照。from langgraph.checkpoint.memory import MemorySaver checkpointer MemorySaver() graph.compile(checkpointercheckpointer) # 每次invoke都会自动保存状态快照 result graph.invoke( {user_id: u123, order_id: o456}, config{configurable: {thread_id: session_001}} )checkpoint不只是用来恢复状态的它在调试时非常有用——你可以回滚到任意一步看当时的State是什么样子。---总结Demo和生产的距离是工程化能力LangGraph让我重新理解了Agent开发的分水岭。Demo阶段你关注的是模型能不能跑通、工具能不能调对生产阶段你关注的是权限有没有校验、日志能不能追溯、出错能不能回滚。很多团队卡在这一步不是模型不够强而是工程化基础没打牢。我的建议是学习顺序上先搞懂State和Node的基础用法再深入条件分支和人工介入写代码的同时就写好日志和权限校验别等上线前再补用checkpoint机制做状态管理它能帮你省很多调试时间Agent从Demo到生产差的不只是代码是一套工程化思维。LangGraph提供了骨架但血肉需要你自己填。资料展示下面是我整理的AI大模型学习资料和工具包预览适合收藏后按主题逐步学习。如果你想看完整资料目录可以在评论区留言「资料」也欢迎告诉我你更关注AI大模型里的哪类内容。