LangGraph 多智能体失败恢复:Tool Error、Timeout 与重试策略
这篇文章记录了我在贵阳实验室的实战过程。我坚信,在技术下行的时代,程序员唯一的护城河就是通过 AI 建立属于自己的数字资产。
本文解决的问题
- LangGraph 多智能体系统里,如何对各种 Tool Error 进行结构化分类与响应?
- 遇到工具 Timeout 超时,如何优雅降级(Fallback)而非简单报错退出?
- 怎样在 Supervisor-Worker 协作架构中建立规范 of 失败上报与分发机制?
- 为什么 Checkpointer 是断点恢复的银弹,在 Python 代码中该如何集成?
- 如何在日志中保留关键的调用链追踪字段(Request ID, Run ID, Thread ID)?
适合谁读
- 遇到工具超时、三方 API 限流和模型幻觉生成错误 Schema 的系统架构师。
- 正在用 LangGraph 落地多智能体协同,且受困于 Worker 智能体自行死循环重试的后端开发工程师。
- 负责 AI 系统稳定性、高可用保障以及审计日志追踪的 DevOps 与全栈开发人员。
一、生产级 Agent 一定会失败
失败是系统工程的入场券,无法恢复才是真正灾难的开始。
在多智能体系统进入生产环境后,你会发现 happy path 只占运行周期的极小部分。现实世界充满了各种不可预测的边缘情况(Edge Cases)。如果你在设计 LangGraph 状态图时,把所有的工具调用、模型推理都假设为必然成功,那么在真实的高并发、多网络层级的环境下,你的系统会频繁遭遇死锁、静默崩溃或死循环。
我们在开发一个多智能体系统时,必须为每一种工具、每一个 Agent 节点设计其 failure path。常见失败类型可以概括为以下几种物理场景:
- 外部依赖失败:三方服务限流(Rate Limited)、API 接口变更导致的 Schema Mismatch、网络偶尔抖动导致的 Tool Timeout。
- 智能体决策失败:模型幻觉导致生成了工具不支持的参数(Invalid Tool Input)、Supervisor 路由选择错误(Wrong Route)、Worker 返回了空结果(Empty Result)。
- 权限与合规失败:访问特定工具时被安全策略拒绝(Permission Denied)、人工审批流程超时或被拒绝(Approval Rejected)。
Demo 阶段,我们只需关注模型是否理解了用户的意图。而生产阶段,我们必须关注模型做错了、工具超时了、API 崩溃了之后,系统如何不丢状态地优雅降级。
二、Tool Error 先分类,不要一律重试
将所有工具错误混为一谈并盲目执行 Retry,是导致 Token 成本暴涨与三方服务雪崩的元凶。
当一个 Worker 智能体调用底层 Tool 失败时,首要任务是识别错误的物理本质。在 LangGraph 中,我们应当通过底层的 Python 异常拦截器对错误进行语义化分类。
1. 临时性错误(Transient Errors)
这类错误的特征是具有时间偶发性。例如网络抖动(ConnectTimeout)、三方 API 限流(HTTP 429 Rate Limit)、或者上游服务短暂的网关超时(HTTP 504)。 针对临时性错误,最适合的策略是带抖动的指数退避重试(Exponential Backoff with Jitter)。
2. 参数与结构错误(Input / Schema Errors)
例如模型幻觉导致多传了字段、少传了必填参数,或者参数类型与工具定义的 Pydantic Schema 不符。 这类错误绝对不能盲目重试。因为在参数不改变的情况下,重试一百次也会得到相同的报错。正确的恢复策略是捕获 ValidationError,将错误日志作为反馈上下文(Feedback Loop)重新喂给模型,促使其修正参数后再次调用。
3. 权限与合规错误(Authorization Errors)
例如工具在执行时返回了权限不足(Permission Denied)或 Access Token 过期。 这类错误应该立即安全终止执行,或者向 Supervisor 汇报,将任务挂起并转交人工审核以申请更高权限,绝对禁止自动重试。
常见报错日志(ValidationError Error Logs)
在生产环境中,最常遇到的参数幻觉错误如下:
pydantic.v1.error_wrappers.ValidationError: 1 validation error for ReadFinancialReportInput
ticker
value is not a valid dict (type=type_error.dict)
[ERROR] 2026-06-13T12:44:00Z - Worker 'finance_worker' failed on tool 'read_financial_report' with code SCHEMA_MISMATCH.
如果出现上述 ValidationError 却直接触发网络重试,只会平白浪费模型输入 Token。
三、Timeout 后怎么处理?
超时不是一个简单的系统动作,而是一个复杂的业务决策点。
在 LangGraph 多智能体系统中,当一个任务超时(Timeout)时,我们不应该只是抛出一个 Exception 然后让程序崩溃。我们需要根据任务的实时上下文,设计精细的分流策略:
- 偶发性慢请求:例如外部数据库查询因为冷启动超时。如果属于非事务性操作,可以在 1s 后直接触发一次重试。
- 必然超时的长任务:例如读取一份 200 页的财报进行全文 AI 审计。这一步如果强行使用同步 Tool,必然会触发 HTTP 超时。合理的策略是在工具内部实现异步任务化(Async Job),工具在启动任务后立即返回一个 job_id,然后将 Worker 节点转为轮询(Polling)或挂起状态,通过 Checkpointer 保存进度,等异步引擎完成后再行拉起。
- 降级服务商(Fallback Provider):如果主数据源工具超时,立即切换到备用数据源工具。
我们可以为多智能体系统设计一个三阶段超时兜底机制:
- 第一次超时:在 Worker 内部尝试进行带短间隔的快速重试。
- 第二次超时:Supervisor 介入,缩小任务规模(比如把读取全文改成只读取摘要),或者切换成 Fallback 工具。
- 第三次超时:彻底挂起任务,生成一份说明“部分步骤超时,请检查”的降级报告,或者转交 Human Review。
四、Supervisor 和 Worker 怎么分工?
Worker 是只负责干活和报告的“哑节点”,Supervisor 才是拥有掌控权的指挥官。
在复杂的 Supervisor-Worker 编排设计中,一个致命的错误是让 Worker 自己去决定如何重试或如何降级。这会导致 Worker 内部逻辑极度臃肿,且 Supervisor 无法感知全局状态,从而使得整个状态图产生死锁或局部死循环。
规范的架构设计原则是:「Worker 负责捕获异常并返回结构化错误状态,而重试、降级和转人工的决策权统一收拢在 Supervisor 节点」。
Worker 失败时的上报规范
当 Worker 节点执行发生异常时,它应当优雅地通过 try-except 捕获异常,并且更新全局 Graph State 中的 error_context,然后将控制权交回给 Supervisor。
以下是 Worker 应该返回的结构化状态片段:
{
"worker_name": "finance_worker",
"status": "failed",
"error_type": "tool_timeout",
"error_message": "读取财报 risk_factors 部分发生 HTTP 504 超时",
"tool_name": "read_financial_report",
"retryable": true,
"attempt_count": 1,
"suggested_action": "retry_with_smaller_input"
}
Supervisor 节点读取到 error_context 后,结合当前的全局上下文(如当前整体预算、运行时间限制等),决策出下一步的走向:是让该 Worker 带着修改后的上下文进行 retry,还是更换 Worker 执行 fallback,或者是触发 ask_human。
五、Retry 策略怎么设计?
容错框架的基石是结构化的控制流,而不是依赖模型的自觉性。
在 LangGraph 中,我们不要试图用 Prompt 告诉模型“如果工具失败了请你重试”。这种软约束非常不稳定。我们需要使用条件边(Conditional Edge)和有状态的计数器来构建强约束的 Retry 控制流。
下面是在 LangGraph 中实现带状态重试、自动 Fallback 以及 Human Review 分流的完整 Python 代码示例:
import time
import random
from typing import Dict, Any, TypedDict, Annotated, List
from langgraph.graph import StateGraph, END
from langgraph.checkpoint.memory import MemorySaver
# 1. 定义全局 Graph 状态
class AgentState(TypedDict):
task: str
messages: List[str]
current_worker: str
error_context: Dict[str, Any]
retry_count: int
max_retries: int
result: str
status: str # "success", "failed", "pending_review"
# 模拟底层工具:一个偶尔超时、偶尔返回权限错误的 API
def read_financial_report_tool(ticker: str, attempt: int) -> str:
print(f"[Tool Log] Calling read_financial_report_tool for {ticker}, attempt={attempt}")
# 模拟权限错误 (不可重试)
if ticker == "RESTRICTED_STOCK":
raise PermissionError("Access denied: Restricted by compliance policy.")
# 模拟临时性超时错误 (前两次调用超时,第三次成功)
if attempt < 3:
raise TimeoutError("Read financial report timed out after 30 seconds.")
return f"Success: Retrieved 2026 Q1 financial report data for {ticker}."
# 2. Worker 节点:捕获错误并结构化上报,绝不自行 Crash
def finance_worker_node(state: AgentState) -> Dict[str, Any]:
ticker = state["task"]
retry_cnt = state.get("retry_count", 0) + 1
try:
# 执行工具
tool_result = read_financial_report_tool(ticker, retry_cnt)
return {
"result": tool_result,
"status": "success",
"retry_count": retry_cnt,
"error_context": {}
}
except Exception as e:
# 判断是否可重试
retryable = True
error_code = "UNKNOWN_ERROR"
if isinstance(e, TimeoutError):
error_code = "TOOL_TIMEOUT"
elif isinstance(e, PermissionError):
error_code = "PERMISSION_DENIED"
retryable = False
print(f"[Worker Alert] Worker 'finance_worker' failed: {str(e)}")
return {
"status": "failed",
"retry_count": retry_cnt,
"error_context": {
"worker_name": "finance_worker",
"error_code": error_code,
"error_message": str(e),
"retryable": retryable
}
}
# 3. Supervisor 节点:全局容错决策大脑
def supervisor_node(state: AgentState) -> Dict[str, Any]:
err_ctx = state.get("error_context", {})
if not err_ctx:
# 无错误,指示流程继续
return {"status": "success"}
retry_count = state.get("retry_count", 0)
max_retries = state.get("max_retries", 3)
print(f"[Supervisor Decision] Evaluating error: {err_ctx.get('error_code')}, count={retry_count}")
# 决策路径 1: 权限错误直接终止或挂起转人工
if err_ctx.get("error_code") == "PERMISSION_DENIED":
print("[Supervisor] Critical permission error. Escalating to human review.")
return {"status": "pending_review"}
# 决策路径 2: 达到最大重试次数,执行 Fallback 降级
if retry_count >= max_retries:
print("[Supervisor] Max retries reached. Initiating fallback mechanism.")
return {"status": "fallback"}
# 决策路径 3: 临时性错误且未超限,允许重试
if err_ctx.get("retryable"):
# 指数退避延迟模拟 (生产环境建议用非阻塞的外部调度器)
backoff_delay = 2 ** retry_count
print(f"[Supervisor] Retry approved. Backing off for {backoff_delay}s...")
time.sleep(0.1) # 模拟延迟
return {"status": "retry"}
return {"status": "failed"}
# 4. Fallback 降级节点
def fallback_node(state: AgentState) -> Dict[str, Any]:
print("[Fallback Node] Executing fallback: Using cached index data instead of raw report.")
return {
"result": f"Fallback: Used offline database cache for {state['task']}. (Data integrity: partial)",
"status": "success"
}
# 5. 条件边路由逻辑 (Routing Logic)
def route_after_supervisor(state: AgentState) -> str:
status = state["status"]
if status == "retry":
return "finance_worker"
elif status == "fallback":
return "fallback"
elif status == "pending_review":
return "human_review_node"
elif status == "success":
return END
else:
return END
def human_review_node(state: AgentState) -> Dict[str, Any]:
print(f"[Human Node] Task {state['task']} is suspended. Thread ID: {state.get('request_id')}")
# 这里会让流程挂起,等待外部接口改写状态重新拉起
return {"status": "pending_review"}
# 6. 编排有状态的图结构
workflow = StateGraph(AgentState)
workflow.add_node("finance_worker", finance_worker_node)
workflow.add_node("supervisor", supervisor_node)
workflow.add_node("fallback", fallback_node)
workflow.add_node("human_review_node", human_review_node)
workflow.set_entry_point("finance_worker")
# 节点连接
workflow.add_edge("finance_worker", "supervisor")
workflow.add_conditional_edges(
"supervisor",
route_after_supervisor,
{
"finance_worker": "finance_worker",
"fallback": "fallback",
"human_review_node": "human_review_node",
END: END
}
)
workflow.add_edge("fallback", END)
workflow.add_edge("human_review_node", END)
# 启用持久化检查点
memory = MemorySaver()
graph = workflow.compile(checkpointer=memory)
六、Fallback 不是失败,而是降级执行
提供一个有缺陷但依旧有价值的响应,远比返回一个冷冰冰的 500 报错更专业。
降级(Fallback)是保障多智能体系统可用性(Availability)的核心手段。当某些次要工具不可用或者严重超时,我们必须能够将工作流导向一个安全备用分支。
常见的降级场景设计包括:
- 财报读取工具超时:不要直接报错,改用大模型根据现有的行业摘要、历史基准数据,生成一份“局部分析报告”,并明确打上「部分缺失」的标志。
- CRM 客户系统写入失败:将待写入的客户数据序列化后存入本地的 Redis 或错误重试数据库,生成一条“待人工导入清单”,防止销售线索在运行中丢失。
- 邮件通知发送失败:将邮件正文转化为 Markdown 草稿,保存在待发送面板,并向前台通知用户手动发送。
降级数据协议规范
在设计 Fallback 节点的输出时,必须明确返回元数据,说明该结果的完整性(Integrity)与来源,从而让下游的系统、其他 Worker 智能体或者最终用户能够有清晰的预期。例如:
{
"result_data": "...",
"meta": {
"integrity_flag": "partial",
"fallback_triggered": true,
"failed_dependencies": ["read_financial_report"],
"timestamp": "2026-06-13T12:44:30Z"
}
}
七、什么时候转 Human Review?
机器智能的终点是人工审查,安全边界不容任何妥协。
虽然我们致力于将系统设计为自动化执行,但当发生以下几类严重危害业务安全的错误时,系统应当立即挂起当前线程,将图节点路由至「人工介入(Human Review)」状态。关于人工审批的具体持久化流程,可以阅读上一篇系列文章:LangGraph Human-in-the-loop 实战:多智能体审批流怎么做?。
以下情况必须交由人工接管:
- 权限不足(PERMISSION_DENIED):如果 Worker 试图执行某项高风险删除或修改动作,但由于当前 Token 权限不足报错,绝对不允许模型自动越权申请,必须由管理员进行物理授权。
- 涉及财务资金扣款失败:当支付工具返回状态不明(如网络断开但扣款可能已发出),此时进行盲目 Retry 可能会导致重复扣款,必须挂起任务等待财务人工对账。
- 多次重试均以相同错误退出:说明系统环境已发生根本性改变(如外部 API 彻底关停或参数格式被永久修改),需要开发人员介入排查。
八、Checkpointer 如何恢复失败任务?
检查点是系统发生灾难性崩溃时的“时空回溯器”。
在 LangGraph 中,MemorySaver 或者是基于 PostgreSQL 的 SqliteSaver 检查点机制,是多智能体失败恢复的物理保障。如果系统在第 5 个节点运行超时崩溃,我们不需要让大模型重新从第 1 个节点开始执行。
只要你在初始化时为图运行提供了唯一的 thread_id,Checkpointer 就会自动在每次节点执行成功后保存图的状态快照(State Snapshot)。
失败任务断点恢复的步骤:
- 状态冻结:Worker 节点发生不可自动修复 of 错误,将控制权转给
human_review_node,系统暂停并退出。 - 人工排查:人工或后台运维脚本检测到失败线程,读取其保存的 State 状态。
- 状态修复:使用
graph.update_state()覆盖或修复错误的变量(例如人工更正了错误的 SQL 代码,或者补充了必填的字段)。 - 流式继续:使用同一个
thread_id重新调用graph.stream()或graph.invoke(),此时 LangGraph 会自动找到最近一次保存的 Checkpoint,跳过前面成功的节点,从失败的节点(或者你指定的恢复节点)继续往下运行。
Python 恢复执行代码示例:
# 模拟一次图的执行,传入 thread_id 挂载在 checkpointer 下
config = {"configurable": {"thread_id": "request_uuid_10012"}}
# 运行一个会触发权限错误的股票
initial_state = {
"task": "RESTRICTED_STOCK",
"max_retries": 3,
"retry_count": 0,
"error_context": {},
"status": "pending"
}
print("--- 开始首次执行 ---")
for event in graph.stream(initial_state, config):
print(event)
# 此时因为权限错误,Supervisor 将其导向了 human_review_node
# 我们来看一下目前的图状态
current_state = graph.get_state(config)
print(f"\n[Checkpoint State] Status: {current_state.values.get('status')}")
print(f"[Checkpoint State] Error: {current_state.values.get('error_context')}")
# 人工介入:我们决定更换任务股票,消除合规风险,并通过 update_state 覆盖状态
print("\n--- 人工修复状态并继续执行 ---")
graph.update_state(
config,
{
"task": "NORMAL_STOCK", # 更换为正常的股票代码
"status": "pending", # 重置状态
"error_context": {}, # 清空错误上下文
"retry_count": 0 # 重置重试计数
},
as_node="supervisor" # 指定我们是在哪个节点后进行的状态更新
)
# 再次以相同的 thread_id 启动,图将读取 Checkpoint 从 supervisor 之后恢复执行
for event in graph.stream(None, config):
print(event)
九、对比块:重试路由机制 vs 模型重想机制
在早期的 AI Agent 开发中,很多人习惯使用传统的「模型全盘重想(Re-prompting)」来处理失败。然而在复杂的生产级多智能体系统中,这一做法弊大于利。
| 评估维度 | 模型全盘重想 (Model Re-prompting) | 状态图结构化恢复 (State-Graph Recovery) |
|---|---|---|
| 执行稳定性 | 极低。依赖 LLM 对报错信息的感知,存在持续幻觉、陷入相同死循环的风险。 | 极高。由 Python 状态机强控制,严格遵守最大尝试次数限制与降级路径。 |
| Token 损耗 | 极高。每次失败都需要将历史全部对话以及错误日志打包重新输入,Token 呈指数增长。 | 极低。仅传递当前节点的结构化状态和错误描述,无历史废弃冗余输入。 |
| 高危工具安全性 | 极其危险。可能会因为幻觉导致重复触发未经审计的敏感写工具(如重复扣款)。 | 绝对安全。状态节点执行是精确隔离的,可通过 Checkpointer 锁定断点,杜绝重复写入。 |
| 人工接管支持 | 困难。由于缺乏物理快照,很难中途将内存变量导出给人工,人工处理后也无法恢复原位。 | 原生支持。Checkpointer 物理存储当前 thread_id 下的快照,支持无缝改写状态与恢复。 |
十、错误日志应该记录哪些字段?
没有追踪字段的错误日志,等于没有日志。
在多智能体系统中,一个用户请求可能会跨越多个 Agent、调用数十次底层工具。如果在日志中只打印一条简随的 Exception: Timeout,那么在生产环境中,你根本无法定位到是哪一个 Worker 在哪一次工具调用中发生的超时。
每个日志条目必须包含以下核心追踪字段:
- 追踪三联体:唯一请求 ID(
request_id)、本次图运行实例 ID(run_id)以及持久化上下文的线程 ID(thread_id)。 - 节点上下文:出错节点的名称(
node_name)、执行失败的 Worker 智能体(worker_name)以及具体触发异常的底层工具名称(tool_name)。 - 错误度量:结构化错误类型(
error_type)、自定义系统错误码(error_code)、当前重试的次数(attempt_count)以及本次调用耗时(latency_ms)。
安全审计铁律:敏感数据物理隔离
在记录错误日志时,必须遵循数据合规安全红线。这里严禁在日志中记录完整的 API Key、LLM 原始返回中包含的用户凭证、底层 SQL 物理执行失败所携带的完整数据库敏感明文,以及涉及用户个人隐私的参数。 日志仅应当保留结构化的控制字段与非敏感的错误摘要。
十一、常见错误
1. 所有失败都让模型重新想一遍
很多开发者在遇到工具返回错误时,粗暴地把 Exception 文本拼接回 Prompt 中重新向模型发起请求。这会导致严重的幻觉堆叠,使得模型可能在同一次请求中产生数次不同的参数解析错误,平白消耗大量 Token 却无法最终运行成功。
2. Worker 自己无限 retry
不要在 Worker 内部嵌入 while True 的重试代码。如果底层工具发生永久性的 403 错误,Worker 自行重试会导致整个主线程被彻底阻塞,外部的调度引擎和 Supervisor 均无法感知底层的故障。
3. Timeout 后直接报错退出
在大多数长耗时场景中,一次 Timeout 并不意味着任务毫无价值。直接退出会导致之前所有成功的中间节点算力付诸东流。应当尽量通过 Fallback 机制提取已经完成的局部数据提供给用户,或降级执行备用方案。
4. 权限错误也重试
权限不足通常是由密钥过期或配置错误导致的系统级问题。重试这类错误不仅无法解决问题,还可能因为短时间内的多次越权请求而触发三方服务的安全封禁警报。
5. 没有错误日志
很多团队虽然启用了 LangGraph,却没有在日志中注入 request_id、run_id 和 node_name。当线上用户反馈任务卡住时,运维人员无法在海量日志中检索出与该用户 thread_id 唯一绑定的报错路径。
6. 失败后丢失上下文
不配置 Checkpointer 或是每次运行都随机生成 thread_id,会导致系统一旦遇到故障,原本执行到中途的中间状态全部在内存中丢失,人工客服在后台即使排查出原因也无法帮用户继续未完的任务,只能让用户重新提交。
十二、上线检查清单
- 工具是否统一使用
try-except捕获异常,并返回结构化的error_context? - 系统是否区分了临时性错误与参数、权限等不可恢复错误,并实施了差异化重试?
- 针对可能超时的高频接口,是否配置了合理的
max_retries和有感知的 Backoff 间隔? - 所有的 Worker 节点是否已经移除了自有的死循环重试,将重试控制权统一上交给了 Supervisor?
- 当达到最大重试上限时,是否有对应的 Fallback 节点执行降级,并返回带
integrity_flag的状态? - 高风险操作(如删除数据、越权操作)失败时,是否能够安全路由至
human_review挂起节点? - 系统是否开启了 Checkpointer 功能,并保证每次用户会话使用稳定且唯一的
thread_id? - 错误日志记录中是否包含了追踪字段(
thread_id、run_id、node_name)? - 日志持久化引擎是否配置了过滤器,自动脱敏了用户密码、Token 等机密凭证?
- 降级输出和人工干预触发时,系统前台是否有对等的状态提示界面,避免用户界面显示死锁?
FAQ
LangGraph 里 Tool Error 应该直接重试吗?
不应该一律重试。必须对错误进行类型识别:网络抖动、HTTP 429 限流、上游超时等临时性错误可以进行有限重试;而对于权限错误、Schema 参数校验错误、以及业务审批拒绝等不可恢复错误,重试只会浪费 Token,应当立即进入降级或人工审查流程。
Timeout 是不是一定代表任务失败?
不是。Timeout 往往说明任务规模超限或三方服务响应迟缓。我们可以通过拆分任务规模、将长耗时同步工具重构为异步状态机制、或者通过 Fallback 提供局部已加载好的结果来挽救会话,而不是直接抛出 500 异常。
Supervisor 和 Worker 谁负责失败恢复决策?
Worker 节点只负责做具体的工具执行,在发生崩溃时记录标准化的失败上下文,它是恢复逻辑的“信息提供者”;而 Supervisor 节点才是掌控全局状态的“决策者”,由它结合全局预算和限制,判断下一步是 retry、fallback、ask_human 还是安全退出。
Checkpointer 能防止 Tool Error 发生吗?
不能。Checkpointer 的物理本质是图状态的持久化快照。它无法阻止网络超时或接口报错的发生,但能确保在系统发生意外故障或人工修改了错误上下文后,智能体能不用重新执行前面繁琐的步骤,直接从上一个完好的 Checkpoint 节点后继续运行。
多智能体系统中最危险的失败是什么?
最危险的失败不是单个接口抛出错误,而是由于没有进行错误分类,系统发生死循环重试;或者状态丢失,导致高风险的写操作(如调用划款 API)在没有状态一致性保证的情况下被重复触发。
LangGraph 生产级 Agent 编排实战系列
- 第 1 篇:LangGraph 多智能体协作实战:Supervisor、Worker 与状态交接怎么设计?
- 第 2 篇:LangGraph 状态隔离实战:thread_id、session_id、user_id 怎么设计?
- 第 3 篇:LangGraph Human-in-the-loop 实战:多智能体审批流怎么做?
- 第 4 篇:LangGraph 多智能体失败恢复:Tool Error、Timeout 与重试策略
- 第 5 篇:LangGraph Observability 实战:如何追踪每个 Agent 的决策路径?
系列导航
LangGraph 生产级 Agent 编排实战系列:
- 第 1 篇:Supervisor / Worker
- 第 2 篇:状态隔离
- 第 3 篇:Human-in-the-loop
- 第 4 篇:失败恢复
- 第 5 篇:Observability
- 第 6 篇:Checkpointer
- 第 7 篇:Subgraph