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 就能"聪明地"判断哪些错误值得再试。

相关推荐
菩提小狗2 小时前
每日极客日报 · 2026年10月06日
ai·开源·极客日报·it热点·技术资讯
Maynor9963 小时前
让 AI 编程助手学会做视频、做 PPT:Agent Skills 入门与安装全指南
人工智能·aigc·ai编程·效率工具·cursor·claude code
猛犸象限3 小时前
【CJMP Grok Bot实践】从鸿蒙搬到 iOS 和 Android,我们为什么最后选了 CJMP
ai编程·grok
程序员老赵3 小时前
Docker 部署 DeepSeek Harness:轻松搭建局域网里的 AI Agent 平台
后端·ai编程·deepseek
mantou1323 小时前
我做了个 App:在手机上指挥电脑里的 Claude Code / Codex,还能直接看它产出的图表和模拟器画面
开源·ai编程·claude
王中阳Go3 小时前
自己摸了 2 个月零 offer,补底子只用了 3 块:Go 后端转 AI 最难的不是技术
后端·agent·ai编程
柯南46683 小时前
【AI工程师精讲】KV Cache 精讲:为什么 AI 越聊越慢,以及长上下文真正的成本在哪
人工智能·ai编程
林伽一4 小时前
能力趋同、账单分化,技术选型正在从榜单转向负载|2026年10月06日
人工智能·科技·安全·ai
小虎AI生活4 小时前
AI 落地的最后一公里,Anthropic 用 1 亿美元买了个教训
aigc·ai编程