最近刷招聘JD发现一个现象大厂招Agent工程师面试题从怎么写一个循环变成了你的Agent怎么审计操作、怎么降级、怎么记录权限变更。很多人一脸懵——这不就是多写几行日志的事吗但真正写生产级Agent的人知道问题没这么简单。我上一个项目用LangGraph搭了一个工单处理AgentDemo阶段跑得挺顺接入公司内部系统后运维第一件事是问我这个Agent调用外部API时有没有权限隔离有没有操作日志出错时能回滚吗我哑口无言。因为Demo阶段我们只关注了能不能跑通没关注能不能上线。这篇就聊聊LangGraph工作流到底该怎么写才能让Agent从Demo变成真正敢上线的系统。摘要本文结合近期大模型应用从Demo转向权限、日志和可观测的实战观察拆解LangGraph工作流的关键概念与工程化要点。通过一个工单处理Agent的实战案例讲清楚State、Node、Edge、条件分支和人工审批节点的实际用法并给出练习顺序和面试能力要求。目录为什么需要图工作流State 与 NodeEdge 与条件分支人工审批节点工程化落地总结为什么需要图工作流很多人一开始接触Agent习惯用脚本思维写先调模型再调工具再调模型循环往复。这种方式在Demo阶段没问题但一旦业务复杂起来问题就暴露了流程不可控模型返回什么就走什么分支调试时完全抓不住状态散乱变量到处飞出了问题不知道是哪个环节污染了状态无法审计Agent做了什么、为什么这么做日志里找不到依据图工作流解决的就是这个问题。LangGraph的核心思想是把Agent的执行过程建模成一张图。图里有节点Node节点之间通过边Edge连接状态State在节点之间流动。这样做的好处是1. 流程可见一张图把整个Agent的执行路径画出来谁调用谁、什么时候分支一目了然2. 状态可控所有状态集中在一个State里不会散落在各个函数参数中3. 可调试图结构支持断点、回溯、重放出了问题可以精确定位到哪个节点出了问题我见过一个团队用脚本写的Agent在测试环境跑得挺好上线后模型偶尔返回异常格式整个流程直接卡死。改用LangGraph之后给每个节点加了错误处理和重试逻辑线上稳定性明显提升。实战建议不要一上来就写复杂图。先从一个简单的链式流程开始比如接收输入→调模型→调工具→返回结果跑通后再逐步加分支和循环。State 与 NodeState是LangGraph的记忆Node是执行单元。State的设计决定了整个Agent的可维护性。很多人一开始把State定义成一个字典什么都往里塞结果随着功能增加State越来越臃肿节点之间的依赖关系也搞不清楚。我的建议是State要按职责拆分每个节点只操作自己需要的字段。举个例子一个工单处理Agent的State可能长这样from typing import TypedDict, Annotated, Literal import operator class AgentState(TypedDict): # 输入 user_input: str # 工具调用 tools_called: Annotated[list, operator.add] # 执行结果 result: str # 审批状态 approval_status: Literal[pending, approved, rejected] # 审计日志 audit_log: Annotated[list, operator.add]这里用Annotated配合operator.add是为了支持列表类型的累加操作——每次调用工具都把记录追加进去而不是覆盖。Node就是普通的Python函数接收State作为参数返回State的更新def parse_intent(state: AgentState) - dict: 解析用户意图 intent call_llm(state[user_input]) return {tools_called: [fparse_intent:{intent}]} def call_tool(state: AgentState) - dict: 调用工具 tool_result execute_tool(state[tools_called][-1]) return {result: tool_result, audit_log: [ftool:{tool_result}]}注意Node返回的是字典LangGraph会自动合并到State里。踩坑提醒State里的字段类型尽量用TypedDict而不是普通dict这样IDE能给出类型提示也能在节点之间做静态检查。Edge 与条件分支边Edge定义了节点之间的流转关系。普通边很简单A节点执行完直接去B节点。条件边Conditional Edge才是LangGraph的精髓。它允许根据State的当前值决定下一步去哪个节点。比如上面的工单Agent解析完意图后可能需要根据意图类型走不同的工具def route_by_intent(state: AgentState) - str: 根据意图路由到不同工具 intent extract_intent(state[user_input]) if intent 查询: return query_tool elif intent 创建: return create_tool else: return fallback graph.add_conditional_edge( parse_intent, route_by_intent, { query_tool: query_node, create_tool: create_node, fallback: fallback_node } )条件函数的返回值必须和add_conditional_edge中定义的边目标节点名称一一对应。实战判断标准如果你的Agent流程超过3个分支或者存在循环逻辑比如需要多次调工具直到满足条件就该用条件边了。否则用普通边更简洁。很多人喜欢在条件函数里写复杂的业务逻辑这其实是错误的。条件函数应该只负责路由真正的业务逻辑放在对应的Node里。人工审批节点这是Demo和生产环境最大的区别之一。很多Agent Demo里工具调用是自动执行的——查数据、发邮件、改配置全由模型决定。但在生产环境涉及写操作的步骤必须有人工确认。LangGraph支持人工节点Human Node执行到这一步时流程会暂停等待人工输入后再继续。from langgraph.types import interrupt def check_and_interrupt(state: AgentState) - dict: 需要审批时暂停 if needs_approval(state): result interrupt({ message: 此操作需要人工确认, action: state[tools_called][-1] }) return {approval_status: result[decision]} return {approval_status: auto_approved}配合interrupt()方法可以实现更精细的暂停。工程化要点审批节点不仅要记录是否批准还要记录谁批准的、在什么时间批准的、基于什么信息批准的。这些是审计日志的核心字段。我见过一个团队审批节点只存了approve或reject结果出了线上事故完全无法追溯是谁在什么情况下点的通过。工程化落地写一个能跑的LangGraph不难写一个能上线的LangGraph需要关注以下几点1. 权限隔离Agent调用的每个工具都应该有独立的权限控制。不要给Agent一个万能钥匙。# 错误做法一个工具类做所有事 class AgentTools: def query(self, ...): ... def create(self, ...): ... def delete(self, ...): ... # 正确做法按权限拆分 class QueryTool: ... # 只读权限 class CreateTool: ... # 写入权限需要审批 class DeleteTool: ... # 删除权限需要双重审批2. 日志记录每个节点的输入、输出、执行时间都应该记录到审计日志里。import time from datetime import datetime def audit_wrapper(node_func): 节点审计装饰器 def wrapped(state: AgentState) - dict: start time.time() result node_func(state) elapsed time.time() - start state[audit_log].append({ node: node_func.__name__, input: {k: v for k, v in state.items() if k ! audit_log}, output: result, elapsed_ms: round(elapsed * 1000, 2), timestamp: datetime.now().isoformat() }) return result return wrapped3. 可观测性接入Prometheus或类似工具暴露Agent的关键指标节点调用次数、平均耗时、错误率、审批通过率等。4. 练习顺序如果你是初学者建议按这个顺序练习1. 基础链写一个3节点的链式流程理解State和Node的基本用法2. 条件分支加一个条件边根据State值路由到不同节点3. 循环实现一个调工具→检查结果→决定是否需要再次调用的循环4. 人工审批加入interrupt实现需要人工确认的节点5. 审计日志给每个节点加装饰器记录完整的执行轨迹6. 权限控制把工具按权限拆分不同节点调用不同权限的工具面试建议面试时不要只讲我用了LangGraph要讲清楚你设计的State结构、条件分支的逻辑、以及你怎么处理权限和日志的。后者才是企业真正关心的。总结LangGraph让Agent从脚本变成了可控的系统但这只是第一步。从Demo到生产真正拉开差距的不是会不会写图而是会不会设计权限、会不会记录日志、会不会做可观测。最近面试里我越来越常听到这样的问题你的Agent出错时怎么定位是哪个节点的问题你的Agent调用了外部API权限是怎么隔离的你能不能回放Agent的完整执行轨迹这些问题才是2026年大模型应用开发的真实分水岭。Demo能跑只是入场券。敢上线才是真本事。资料展示下面是我整理的AI大模型学习资料和工具包预览适合收藏后按主题逐步学习。如果你想看完整资料目录可以在评论区留言「资料」也欢迎告诉我你更关注AI大模型里的哪类内容。