LangGraph 错误处理和重试机制

第一章:为什么需要"重试"?

1.1 用生活比喻理解

想象你在打电话给客服。有时候线路忙,打不通;有时候对方正在通话中;有时候你拨错号码了。

  • 线路忙 :等一会儿再打,可能就通了 → 值得重试

  • 拨错号码 :再打一百次也没用,号码本身就是错的 → 不值得重试

程序里的"节点"也一样。节点执行时可能遇到各种错误:

  • 临时性错误:网络抖动、API 限流、数据库连接超时 → 重试几次可能就好了

  • 永久性错误:参数类型传错了、代码逻辑写错了 → 重试一万次也是错

重试机制就是帮你自动判断:"这个错值不值得再试一次?"

1.2 没有重试会怎样?

假设你写了一个节点调用外部 API:

python

python 复制代码
def call_api(state):
    response = requests.get("https://api.example.com/data")
    return {"result": response.text}

如果这次网络刚好抖动了一下,请求失败,整个图就直接崩溃,用户看到报错。但实际上,等 1 秒再试一次,可能就成功了。

加上重试机制 ,LangGraph 会自动帮你再试,你不需要写 while 循环、try...except 嵌套,只需要在 add_node 时加一个参数。

第二章:RetryPolicy 是什么

2.1 一句话定义

RetryPolicy 是一个"重试规则说明书"。你把它交给某个节点,节点执行失败时,LangGraph 就按这本说明书决定"要不要重试、重试几次、哪些错误值得重试"。

2.2 它长什么样

python

python 复制代码
from langgraph.types import RetryPolicy

RetryPolicy(
    max_attempts=5,           # 最多尝试几次
    retry_on=custom_retry_on,  # 遇到什么异常才重试(可选)
)

它有两个主要参数:

参数 含义 默认值
max_attempts 最多尝试几次(包含第一次) 5
retry_on 一个函数,接收异常,返回 True 表示重试,False 表示不重试 内置默认函数

2.3 怎么用

python 复制代码
在 add_node 的时候传进去:

python

builder.add_node(
    "my_node",           # 节点名字
    my_node_function,    # 节点函数
    retry_policy=RetryPolicy(max_attempts=5)  # 重试策略
)
就这么简单。节点执行失败时,LangGraph 自动接管重试逻辑。

第三章:默认重试策略(不用自己写,但必须懂)

3.1 默认行为是什么

python 复制代码
如果你只写:

python

RetryPolicy(max_attempts=5)
没有指定 retry_on,LangGraph 会用内置的默认重试函数。这个默认函数的行为是:

遇到大多数异常都重试,但有一批"明确不该重试"的异常会直接跳过。

3.2 哪些异常默认不重试

这批"不该重试"的异常是:

text

python 复制代码
ValueError          值错误(比如参数类型不对)
TypeError           类型错误
ArithmeticError     算术错误(比如除以零)
ImportError         导入错误
LookupError         查找错误(比如字典键不存在)
NameError           变量名错误
SyntaxError         语法错误
RuntimeError        运行时错误
ReferenceError      引用错误
StopIteration       迭代停止
StopAsyncIteration  异步迭代停止
OSError             操作系统错误(比如文件不存在)

为什么这些不重试?

因为它们是代码写错了导致的,不是"运气不好"。重试一百次,代码还是错的,结果还是错。所以直接放弃,把错误抛给你看。

3.3 哪些异常会重试

除了上面列出的那批,其他所有异常默认都会重试,比如:

python 复制代码
Exception(通用异常)

ConnectionError(网络连接错误)

TimeoutError(超时)

你自己定义的异常类(只要不是上面那批的子类)

为什么这些要重试?

因为它们通常是临时性问题。等一会儿再试,可能就好了。

3.4 用生活比喻

默认策略就像一个"有经验的客服主管":

  • 客户说"网络卡了" → 再试一次

  • 客户说"我密码忘了" → 再试一次

  • 客户说"你们代码有 bug" → 这个重试也没用,直接升级给技术部门(抛错)

3.5 代码里怎么体现的

python

python 复制代码
def test_default_retry():
    default_graph = build_retry_graph(
        node_name="unstable_api",
        node_func=unstable_api_call,
        retry_policy=RetryPolicy(max_attempts=5)  # 只设了次数,没设 retry_on
    )

这里 unstable_api_call 前两次抛的是普通 Exception,所以默认策略会重试。第 3 次成功,最终返回结果。

如果这里抛的是 ValueError,默认策略不会重试,直接失败。

第四章:自定义重试策略(精细控制)

4.1 什么时候需要自定义

默认策略是"大多数异常都重试,少数不重试"。但有时候你想更精确:

  • 只对特定错误信息重试

  • 只对特定异常类型重试

  • 根据错误码决定是否重试

这时候就要自己写一个 retry_on 函数。

4.2 retry_on 函数长什么样

python

python 复制代码
def custom_retry_on(exception: Exception) -> bool:
    """接收一个异常,返回 True 表示重试,False 表示不重试"""
    err_msg = str(exception)
    if "模拟API调用失败" in err_msg:
        return True
    return False

规则很简单:

  • 参数:一个异常对象

  • 返回值 :True 或 False

  • True → 重试

  • False → 不重试,直接抛错

4.3 代码里的自定义函数

python

python 复制代码
def custom_retry_on(exception: Exception) -> bool:
    """自定义重试规则:只对包含「模拟API调用失败」的异常重试"""
    print("########################:  "+str(exception))
    err_msg = str(exception)
    if "模拟API调用失败" in err_msg:
        print(f"捕获到可重试异常: {err_msg}")
        return True
    print(f"捕获到不可重试异常: {err_msg}")
    return False
逐行解释:

第 1 行:定义函数,接收 exception,返回布尔值。

第 3 行:把异常转成字符串,打印出来(方便调试)。

第 4 行:把异常信息存到 err_msg 变量里。

第 5-7 行:如果异常信息里包含"模拟API调用失败",返回 True(表示重试)。

第 8-9 行:否则打印"不可重试异常",返回 False。

4.4 怎么用

python

复制代码
python 复制代码
custom_graph = build_retry_graph(
    node_name="custom_retry_api",
    node_func=unstable_api_call,
    retry_policy=RetryPolicy(
        max_attempts=5,          # 最多试 5 次
        retry_on=custom_retry_on # 用你自己的判断函数
    )
)
这样,节点抛出的异常会被 custom_retry_on 检查:

包含"模拟API调用失败" → 重试

其他任何异常 → 不重试,直接抛错

4.5 自定义策略的威力

你甚至可以写更复杂的规则:

python 复制代码
python

def smart_retry(exception: Exception) -> bool:
    # 网络错误 → 重试
    if isinstance(exception, ConnectionError):
        return True
    # 超时错误 → 重试
    if isinstance(exception, TimeoutError):
        return True
    # 错误信息里有 "rate limit"(限流)→ 重试
    if "rate limit" in str(exception).lower():
        return True
    # 其他都不重试
    return False

这样,你的 Agent 就能"聪明地"判断哪些错误值得再试。

相关推荐
警醒与鞭策15 小时前
Codex桌面版与Claude桌面版使用设置
android·unity·ai·性能优化
择势16 小时前
从零散提效到体系化协作:iOS 团队 AI 研发工作流完整实践
ai编程
救救孩子把16 小时前
LangGraph 工程化架构:类型、状态、流式通信与可观测性
架构·agent·trace·opentelemetry·langgraph·graphrag
奇牙coding17 小时前
GPT-5.5 报 401 invalid_api_key 怎么办?换密钥前按 4 层排查请求头、项目权限和端点
数据库·gpt·ios·ai
leeguoo17 小时前
让 Claude Code / Codex 用上你已登录的 Chrome
前端·chrome·ai编程
Potato_土豆17 小时前
MCP Server 接入多个 AI 客户端:配置差异与 10 个真实踩坑
人工智能·后端·ai编程
Markus实验室17 小时前
一个任务烧了54亿token,我盯着账单看了十分钟
agent·ai编程
烬羽18 小时前
给 RAG Agent 装上"仪表盘":LangSmith 全链路观测与量化评估实战
深度学习·openai·ai编程
LEE18 小时前
别把 Agent 架构画成组织架构图——子代理该不该拆,用任务级 Eval 说话
前端·后端·ai编程
梦醒江南18 小时前
RAG 证据链验收:别只测答案像不像,要证明它从哪里来
前端·agent·ai编程