一个 Agent 在本地跑通,并不意味着它已经具备稳定运行的能力。

模型接口会超时,搜索服务会返回 503,数据库连接可能中断,Tool 也可能因为参数错误抛出异常。Agent 又通常包含多轮“模型 → Tool → 模型”的执行循环,其中任何一步失败,都可能影响整个任务。

因此,Agent 的错误处理需要回答几个具体问题:什么错误可以重试,什么时候应该切换备用模型,哪些 Tool 异常可以交给模型重新处理,哪些错误必须立即终止。

本文主要介绍 LangChain Agent 在真实运行环境中可能遇到的各类故障,以及如何通过重试、Fallback、超时与异常恢复等机制加以应对。

一、Agent故障来源

普通模型调用的链路比较简单:

代码片段Text
用户请求

模型调用

返回结果

如果模型请求失败,捕获异常并返回错误即可。

Agent 的链路更长:

代码片段Text
用户请求

模型判断

调用搜索 Tool

模型读取结果

调用数据库 Tool

模型继续判断

返回结果

在 LangChain 中,create_agent 创建的 Agent 会让模型与 Tool 在循环中持续交互,直到模型生成最终响应或运行被停止。

因此,一次 Agent 执行中可能存在多个可能的故障来源。

模型层可能遇到网络错误、Rate Limit、服务端故障和请求超时。

Tool 层还会引入数据库、HTTP API、文件系统和业务代码产生的异常。

执行链路也会产生新的问题。例如前三步已经成功,第四步失败,此时从头重新执行,很可能重复已经完成的操作。

从处理方式来看,常见的恢复路径可以归纳为四类:

代码片段Text
失败  
├─ Retry(重试)—— 再执行一次  
├─ Fallback(回退)—— 切换备用实现  
├─ Recover(恢复)—— 把错误交回 Agent  
└─ Fail(失败)—— 终止当前运行

不同机制针对的故障类型并不相同。

二、错误恢复边界

先看两个简单场景。

在一个 Agent 中调用了两个不同的服务。

Agent 调用天气服务时收到:

代码片段Text
HTTP 503 Service Unavailable

服务可能只是短暂抖动。等待一秒重新请求,有机会恢复。这类情况属于瞬时错误(Transient Failure)。

另一个 Tool 收到:

代码片段Text
city=""

随后抛出:

代码片段Text
ValueError: city 不能为空

相同参数执行十次,结果通常仍然一样。此时重复请求没有意义,模型需要修改调用参数。

实际项目中的错误大致可以这样区分:

类型典型情况常见处理
瞬时错误429、503、连接中断Retry
服务故障模型供应商不可用Retry、Fallback
输入错误Tool 参数非法返回模型重新处理
超时外部服务长时间无响应Timeout、Retry
业务拒绝权限不足、余额不足返回业务错误
程序错误TypeError、代码 Bug终止并记录

关于 Retry 策略,需要注意:相同输入再次执行时,如果成功概率会明显提高,Retry 才有价值。

SQL 写错、API Key 失效、参数结构不合法,都很难通过等待几秒自行恢复。对这些错误反复 Retry,只会增加响应时间和调用成本。

三、重试机制

LangChain 提供 ModelRetryMiddlewareToolRetryMiddleware,分别处理模型调用和 Tool 执行过程中出现的可重试异常。

以 Tool 为例:

代码片段Python
from langchain.agents import create_agent
from langchain.agents.middleware import ToolRetryMiddleware
from langchain.tools import tool
 
 
@tool
def search_docs(query: str) -> str:
    """Search technical documentation."""
    return f"Search result for: {query}"
 
 
agent = create_agent(
    model="openai:gpt-5",
    tools=[search_docs],
    middleware=[
        ToolRetryMiddleware(
            max_retries=3,
            initial_delay=1.0,
            backoff_factor=2.0,
            max_delay=10.0,
            retry_on=(ConnectionError, TimeoutError),
            on_failure="continue",
        )
    ],
)

max_retries=3 表示首次失败以后,最多额外尝试三次。

initial_delaybackoff_factor 控制重试间隔。忽略随机抖动时,过程大致是:

代码片段Text
第一次失败
等待约 1 秒

第二次失败
等待约 2 秒

第三次失败
等待约 4 秒

这种策略称为指数退避(Exponential Backoff)。

如果几十个 Agent 同时碰到下游服务出问题,所有请求马上重发,很可能让服务压力雪上加霜。用指数退避配合随机抖动,能避免大量请求在同一时刻扎堆重试。

模型调用可以采用相同机制:

代码片段Python
from langchain.agents.middleware import ModelRetryMiddleware
 
agent = create_agent(
    model="openai:gpt-5",
    tools=[search_docs],
    middleware=[
        ModelRetryMiddleware(
            max_retries=3,
            initial_delay=1.0,
            backoff_factor=2.0,
            retry_on=(ConnectionError, TimeoutError),
            on_failure="error",
        )
    ],
)

这里需要重点关注 retry_on

生产系统通常应明确哪些异常允许重试。例如连接中断和超时可以重试,而参数错误、权限错误和程序 Bug 往往应直接向上传播。

上例运行结果:

代码片段Text
Model request failed: TimeoutError
Retrying after 1s...

Model request failed: TimeoutError
Retrying after 2s...

Model request succeeded
Agent completed successfully

从结果可以看到,Retry 没有改变执行目标,也没有更换模型。系统只是再次执行了同一个操作。

四、Fallback机制

如果同一个服务连续失败,继续原封不动地重试不一定是好办法。

这时可以使用 Fallback,也就是准备一组备用模型或服务。

两者的执行关系可以简单表示为:

代码片段Text
Retry

Model A

Model A

Model A


Fallback

Model A

Model B

Model C

LangChain 的 ModelFallbackMiddleware 可以在主模型失败后,按照配置顺序尝试其他模型。

代码片段Python
from langchain.agents import create_agent
from langchain.agents.middleware import (
    ModelFallbackMiddleware,
    ModelRetryMiddleware,
)
 
agent = create_agent(
    model="openai:gpt-5",
    tools=[search_docs],
    middleware=[
        ModelRetryMiddleware(
            max_retries=2,
            on_failure="error",
        ),
        ModelFallbackMiddleware(
            "openai:gpt-5-mini",
        ),
    ],
)

这套配置表达的运行策略是:

代码片段Text
调用主模型

失败

再次调用主模型

仍然失败

尝试备用模型

Fallback 需要特别关注模型能力是否兼容。

如果 Agent 使用 Tool Calling、结构化输出或者多模态能力,备用模型也需要支持相应功能。

否则可能出现:

代码片段Text
主模型失败

切换备用模型

备用模型缺少所需能力

再次失败

因此,备用模型应该经过实际验证,确保它能够完成当前 Agent 所需要的任务。

上述示例输出如下:

代码片段Text
Primary model request failed
Retry 1 failed
Retry 2 failed

Fallback model selected

Request succeeded
Agent completed

这里形成了两层恢复机制:短暂故障由 Retry 处理,主服务持续不可用时再进入 Fallback。

五、Tool异常恢复

我们先看一个具体场景。

假设模型生成了错误调用:

代码片段Text
get_order(order_id="")

Tool 随后抛出:

代码片段Text
ValueError: order_id 不能为空

如果直接终止 Agent,本次任务到这里结束。

但这条错误信息对模型其实有价值。模型看到 order_id 不能为空 后,可以修改 Tool Call,再执行一次:

代码片段Text
Tool 执行失败

错误信息返回模型

模型重新判断

生成新的 Tool Call

这个过程与普通 Retry 有明显区别。

Retry 会重新执行相同调用:

代码片段Text
get_order(order_id="")

get_order(order_id="")

Agent Recovery 则允许模型修改参数:

代码片段Text
get_order(order_id="")

收到错误信息

get_order(order_id="ORDER-100001")

ToolRetryMiddleware 在重试耗尽后,可以通过 on_failure="continue" 把错误作为 Tool 消息返回给 Agent。

LangChain 还提供 ToolErrorMiddleware,用于将 Tool 异常转换为模型能够理解的受控错误信息。

代码片段Python
from langchain.agents import create_agent
from langchain.agents.middleware import (
    ToolErrorMiddleware,
    ToolRetryMiddleware,
)
 
 
def handle_tool_error(exc, request):
    if isinstance(exc, ValueError):
        return (
            f"{request.tool_call['name']} received invalid arguments. "
            "Please correct the arguments and try again."
        )
 
    return None
 
 
agent = create_agent(
    model="openai:gpt-5",
    tools=[search_docs],
    middleware=[
        ToolRetryMiddleware(
            max_retries=2,
            on_failure="error",
        ),
        ToolErrorMiddleware(
            on_error=handle_tool_error,
        ),
    ],
)

Middleware 的组合顺序会影响异常传播。

如果希望 Tool 先自动重试,重试耗尽后再进入错误转换,需要确保最终异常能够继续传递到负责处理它的 Middleware。

上面示例输出:

代码片段Text
Tool call:
search_docs(query="")

Tool error:
ValueError

Agent receives:
search_docs received invalid arguments.
Please correct the arguments and try again.

Tool call:
search_docs(query="LangChain middleware")

Tool succeeded

一般来说,网络超时、503 等瞬时故障更适合 Retry;参数错误、查询条件错误等模型有能力修正的问题,更适合把错误重新放回 Agent 的上下文。

六、超时边界

还有一类问题不会立即抛出异常:

代码片段Text
Agent

External API

一直等待……

如果没有设置 Timeout,Agent 可能长时间占用连接和执行资源。

因此,凡是调用外部服务,都应该考虑明确的时间边界。

普通 HTTP Tool 可以直接在 HTTP Client 中设置:

代码片段Python
import httpx
from langchain.tools import tool
 
 
@tool
def query_service(keyword: str) -> str:
    """Query an external service."""
    response = httpx.get(
        "https://api.example.com/search",
        params={"q": keyword},
        timeout=5.0,
    )
    response.raise_for_status()
    return response.text

超过五秒后,HTTP Client 会抛出超时异常。外层 Retry 再决定是否重新请求:

代码片段Text
Timeout

判断异常类型

Retry

仍然失败

Fallback / Recover / Fail

模型客户端同样应该根据实际 SDK 提供的配置设置请求超时。

错误处理离故障源越近,通常越容易准确判断发生了什么。

七、组合策略

生产环境中的错误处理通常由多种机制组成。

一条比较清晰的执行路径是:

Agent 错误处理与恢复流程:调用发生失败后,根据错误类型进入重试、模型修正或失败流程,重试耗尽后使用 Fallback。放大查看 ↗
图示先判断错误是否可恢复,再决定 Retry、Recovery、Fallback 或直接 Fail。

实际项目中可以按照故障位置来安排处理逻辑。

HTTP 超时由 HTTP Client 控制。

Tool 参数错误在 Tool 边界转换成清晰的错误信息。

模型服务的瞬时故障交给 ModelRetryMiddleware

主模型持续不可用时,再进入模型 Fallback。

权限错误、配置错误以及程序 Bug,则应向上传播,并交给日志、Trace 和应用层异常处理机制记录。

此外,对于涉及写操作或与外部系统交互的 Tool,应配合使用幂等键、事务状态检查,或加入重复请求保护机制。

像查询天气、搜索文档等读操作通常比较适合自动 Retry;而支付、退款、发消息等操作则应先解决幂等问题。

总结

本文讨论了 Agent 运行过程中几种最常见的故障处理方式。

Timeout 负责限制等待时间,Retry 适合处理具有恢复概率的瞬时故障,Fallback 用于主服务持续不可用时切换备用路径,Tool Error Recovery 则允许模型根据错误信息重新调整参数和执行策略。

实际项目中,应先区分错误类型和副作用,再决定恢复方式;涉及写操作时,还需要配合幂等、事务和状态检查,避免一次故障演变成重复执行。