三亩地 三亩地SAN MU DI · CODE DIARY
ARTICLE DETAIL

日记详情

真实记录编程学习的某一天,欢迎挑你感兴趣的翻一翻。

LangGraph 基础入门4(小白必看)

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.txt

langgraph.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_nodeToolNode
灵活性中等
代码量
审批逻辑好插入需要额外设计
错误处理完全自定义框架默认处理为主
适合场景复杂业务工具流标准工具调用

可以这样选:

学习阶段:先手写,理解原理 项目常规工具调用:用 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 应用。

← 返回列表