LangGraph 基础入门4(小白必看)
LangGraph 中断、工具调用与部署:从 Human-in-the-loop 到 Agent 工程落地
前面几篇已经整理了 LangGraph 的基础、控制流、持久化与记忆管理。这一篇继续往工程实践走,重点看三个非常实用的能力:
中断:让图暂停,等待人工输入或审批 工具调用:让模型调用外部函数或服务 部署:把本地图运行成可调试、可访问的 Agent 服务这三个能力结合起来,LangGraph 就不只是“本地跑一个流程”,而是可以做更接近真实业务的 Agent 系统。
一、为什么需要中断?
在很多 Agent 场景里,图不能一直自动跑到底。
比如:
- 模型生成了操作计划,需要人工确认
- 工具调用前需要用户批准
- Agent 写好了内容,需要用户审核修改
- 工作流跑到关键步骤,需要人工补充信息
- 某个高风险动作,比如删除文件、发邮件、提交订单,需要确认
这类场景就叫:
Human-in-the-loop,人在回路中LangGraph 的中断机制,就是为这种场景准备的。
二、动态中断 interrupt()
动态中断是指:图运行到某个节点内部时,代码主动调用interrupt(),让图暂停。
可以理解成:
节点执行到这里,先别继续了,等人给一个输入。基础形式大概是:
fromlanggraph.typesimportinterrupt,Commanddefreview_node(state):user_feedback=interrupt({"question":"是否批准继续执行?","content":state["draft"]})return{"feedback":user_feedback}执行到interrupt()时,图会暂停,并把中断信息返回给外部。
外部拿到用户输入后,再用Command(resume=...)恢复。
三、恢复中断:Command(resume=…)
恢复中断时,通常会重新调用图,并传入:
Command(resume=用户输入)比如:
graph.invoke(Command(resume="同意继续"),config=config)这里的意思是:
把“同意继续”作为 interrupt() 的返回值,继续执行原来的节点。所以中断和恢复可以这样理解:
interrupt():暂停并向外要数据 Command(resume=...):把外部数据送回来,让图继续执行四、基础 HITL 模式
基础 Human-in-the-loop 流程一般是:
节点生成内容 ↓ interrupt 暂停,等待人工确认 ↓ 用户输入确认结果 ↓ Command(resume=...) 恢复 ↓ 节点继续执行适合:
- 内容审核
- 审批确认
- 人工补充信息
- 任务执行前确认
可以记住一句话:
interrupt 不是报错,而是一次有意识的暂停。五、多个并行中断
如果图里有多个并行节点,它们都可能触发中断。
比如:
node_a 需要人工确认 node_b 也需要人工确认这时可能会产生多个 interrupt。
恢复时通常需要构建:
中断 ID -> 恢复值也就是给不同中断分别提供不同答案。
可以理解成:
多个暂停点,就要分别告诉每个暂停点怎么继续。六、审批模式
审批模式是中断机制最常见的用法。
流程一般是:
Agent 生成计划 ↓ interrupt 等待审批 ↓ 如果批准:继续执行 如果拒绝:终止或改走其他节点比如:
decision=interrupt({"type":"approval","message":"是否允许执行工具调用?"})ifdecision=="approve":return{"approved":True}else:return{"approved":False}这种模式适合高风险动作:
- 发邮件
- 执行 SQL
- 删除数据
- 调用付费接口
- 提交订单
七、审核与编辑模式
有时候用户不是简单同意或拒绝,而是想改一下内容。
比如模型生成了一段文案:
请审核并修改这段内容。用户可以返回修改后的文本。
流程就是:
模型生成 draft ↓ interrupt 把 draft 给用户 ↓ 用户修改 ↓ resume 返回修改后的内容 ↓ 后续节点使用修改版内容这适合:
- 博客草稿审核
- 合同条款修改
- 邮件发送前编辑
- 报告内容确认
八、工具执行审批模式
工具调用前审批,是 Agent 系统里很重要的安全设计。
比如模型想调用工具:
delete_file(path="xxx")不能直接执行,应该先中断:
模型请求工具调用 ↓ interrupt 请求用户批准 ↓ 批准后执行工具 ↓ 拒绝则返回拒绝信息或终止这类模式可以避免 Agent 擅自执行危险操作。
九、单节点串行中断
一个节点内部也可以多次调用interrupt()。
比如:
先问姓名 再问年龄 再问是否确认这种叫单节点串行中断。
但是要注意:同一个节点内的interrupt()调用顺序非常重要。
恢复时,LangGraph 会按照原来的调用顺序匹配中断。
所以不要随便改变节点内部interrupt()的顺序。
十、interrupt 使用规范
1. 不要用 try/except 包裹 interrupt()
interrupt()本身依赖特殊的中断机制,不是普通业务异常。
如果用try/except把它捕获了,可能导致中断机制失效。
不推荐:
try:value=interrupt("请输入内容")exceptException:...2. 不要更改单节点内 interrupt 顺序
比如原来是:
name=interrupt("请输入姓名")age=interrupt("请输入年龄")后面不要随便改成:
age=interrupt("请输入年龄")name=interrupt("请输入姓名")否则恢复时可能对不上。
3. 不要传递复杂类型
interrupt()中传递的数据尽量简单,比如:
- 字符串
- 数字
- 布尔值
- 简单字典
- 简单列表
不要传复杂对象、函数、数据库连接等。
4. 中断前的副作用要幂等
副作用指:
- 写数据库
- 发请求
- 发邮件
- 创建文件
- 扣费
如果节点在中断前做了副作用操作,恢复时可能会重新执行这段逻辑。
所以中断前的副作用最好是幂等的。
幂等就是:
执行一次和执行多次,结果一致。十一、静态断点
除了在代码里主动interrupt(),LangGraph 还支持静态断点。
静态断点更像调试器里的断点。
你可以在编译时设置:
graph=builder.compile(checkpointer=checkpointer,interrupt_before=["node_a"])意思是:
执行 node_a 之前暂停。也可以设置:
interrupt_after=["node_a"]意思是:
执行 node_a 之后暂停。静态断点适合调试,不一定需要写进业务节点代码。
十二、动态中断和静态断点的区别
| 对比点 | 动态中断interrupt() | 静态断点 |
|---|---|---|
| 位置 | 写在节点代码内部 | 编译或调用时配置 |
| 目的 | 业务暂停,等待人工输入 | 调试暂停 |
| 是否需要节点代码配合 | 需要 | 不一定 |
| 常见场景 | 审批、编辑、人工确认 | 本地调试、观察状态 |
简单记:
业务中断用 interrupt() 调试断点用 interrupt_before / interrupt_after十三、本地部署并对接 LangSmith
LangGraph 项目可以本地部署成 Agent Server,并对接 LangSmith 做调试和追踪。
常见流程是:
准备项目结构 编写图代码 配置 langgraph.json 启动本地服务 在 LangSmith / Studio 中调试典型项目结构:
project/ agent.py langgraph.json .env requirements.txtlanggraph.json一般用来声明图入口。
示意:
{"graphs":{"agent":"./agent.py:graph"}}意思是:
agent 这张图来自 agent.py 文件里的 graph 对象。十四、启动本地服务
安装相关依赖后,可以用 LangGraph CLI 启动本地服务。
常见命令类似:
langgraph dev启动后,本地会运行一个 Agent Server。
这样你就可以通过接口、Studio 或前端 UI 去调用这张图。
十五、对接 AgentChatUI
AgentChatUI 是一个聊天前端,用来和 LangGraph Agent Server 交互。
整体流程:
LangGraph 图代码 ↓ langgraph dev 启动服务 ↓ AgentChatUI 连接服务地址 ↓ 在网页里聊天、触发工具、查看历史适合测试:
- 多轮对话
- 工具调用
- 历史记录
- 中断恢复
- Agent UI 体验
十六、工具调用节点:手动处理工具调用
工具调用是 Agent 的核心能力。
最基础的做法是手动处理tool_calls。
流程一般是:
llm_node 调用绑定工具的模型 ↓ 模型返回 tool_calls ↓ tool_node 读取 tool_calls ↓ 根据工具名执行对应工具 ↓ 把结果包装成 ToolMessage ↓ 返回给 LLM 继续推理手动处理的优点是灵活。
比如可以自己控制:
- 哪些工具允许执行
- 工具失败怎么处理
- 是否需要人工审批
- 工具结果怎么包装
- 是否记录日志
缺点是代码更繁琐。
十七、ToolNode:自动处理工具调用
LangGraph 提供了ToolNode,可以帮你自动执行工具调用。
大概用法:
fromlanggraph.prebuiltimportToolNode tools=[get_weather,get_news]tool_node=ToolNode(tools)然后注册:
builder.add_node("tools",tool_node)当模型返回tool_calls后,ToolNode会根据工具名自动调用对应工具,并返回ToolMessage。
适合标准工具调用场景。
如果你不需要特别复杂的审批、缓存、异常处理,ToolNode会比手写tool_node简洁很多。
十八、手动工具节点和 ToolNode 的区别
| 对比点 | 手动 tool_node | ToolNode |
|---|---|---|
| 灵活性 | 高 | 中等 |
| 代码量 | 多 | 少 |
| 审批逻辑 | 好插入 | 需要额外设计 |
| 错误处理 | 完全自定义 | 框架默认处理为主 |
| 适合场景 | 复杂业务工具流 | 标准工具调用 |
可以这样选:
学习阶段:先手写,理解原理 项目常规工具调用:用 ToolNode 复杂审批/安全控制:手写或封装自己的 ToolNode十九、ToolRuntime 是什么?
ToolRuntime可以让工具在执行时访问更多运行时信息。
比如:
- 当前状态
- 上下文
- 配置信息
- 存储器
这意味着工具不只是“输入参数 -> 返回字符串”,还可以参与更复杂的图状态管理。
比如工具可以读取当前用户:
根据 user_id 查询数据库或者结合上下文:
VIP 用户返回更详细结果二十、在工具中更新状态
有些工具不只是返回结果,还希望更新图状态。
比如:
查询天气工具执行后,把 weather 字段写入 State或者:
搜索工具执行后,把 documents 写入 State这种场景下,工具就不只是“给模型一个观察结果”,还会影响后续节点的状态。
实际开发时要注意:
工具更新状态时,要清楚这个字段由谁写、谁读、是否需要 Reducer。二十一、工具节点容错:重试机制
工具调用经常会失败,比如:
- 网络波动
- API 限流
- 第三方服务超时
- 工具参数错误
可以给工具节点增加重试机制。
思路是:
工具失败 ↓ 判断是否是可重试错误 ↓ 等待一段时间 ↓ 重新调用 ↓ 超过最大次数后返回失败信息适合重试的错误:
- 网络超时
- 临时服务不可用
- 限流后稍等可恢复
不适合重试的错误:
- 参数格式错误
- 工具名称错误
- 权限不足
- 明确的业务拒绝
二十二、工具节点缓存
工具缓存可以减少重复调用。
适合:
- 天气查询
- 新闻查询
- 文档解析
- 搜索结果
- 用户资料查询
比如同一个问题短时间重复问:
北京今天天气怎么样?不一定每次都要重新调 API,可以先查缓存。
缓存时要考虑两个点:
缓存 key:什么输入算同一次请求 ttl:缓存多久过期二十三、中断 + 工具调用的组合
真正项目里,中断和工具调用经常一起用。
比如:
模型决定要调用 send_email 工具 ↓ 工具执行前 interrupt,请用户审批 ↓ 用户同意 ↓ 执行 send_email ↓ 返回 ToolMessage ↓ 模型总结执行结果这就是一个更安全的 Agent 工具调用流程。
对于危险工具,可以加审批。
对于普通工具,可以直接执行。
二十四、学习时最容易混的点
1. interrupt 不是异常
它是 LangGraph 的中断机制,不是普通raise Exception。
所以不要用普通异常思维理解它。
2. resume 是把值送回 interrupt
Command(resume="同意")这个"同意"会成为之前interrupt()的返回值。
3. 静态断点更适合调试
如果只是想观察节点前后的状态,用静态断点。
如果业务上需要用户输入,用动态中断。
4. ToolNode 是标准工具执行器
简单工具调用可以用ToolNode。
但如果你要审批、复杂容错、状态更新,可能要手写工具节点。
5. 工具调用后通常要回到 LLM
工具只是返回观察结果。
最终答案通常还是由 LLM 结合工具结果生成。
所以典型流程是:
LLM -> Tool -> LLM总结
这篇主要整理了 LangGraph 里更偏工程实践的部分:
动态中断 interrupt() 恢复中断 Command(resume=...) 审批模式 审核与编辑模式 工具执行审批 静态断点 本地部署 AgentChatUI 对接 手动工具节点 ToolNode ToolRuntime 工具状态更新 工具重试与缓存可以用一句话串起来:
中断让 Agent 能等人,工具让 Agent 能做事,部署让 Agent 能真正被调用。学到这里,LangGraph 就已经从“流程编排框架”进入了“Agent 工程框架”的范围。后面真正做项目时,重点就是把检查点、记忆、中断、工具调用和部署组合起来,做出稳定、可控、可恢复的 Agent 应用。
