跳到主要内容

错误处理与重试 ​

概述 ​

Agent 运行时可能遇到模型限流、网络异常、工具失败或参数错误。不同错误适合不同处理方式:临时故障可以稍后重试,确定性错误应立即失败,部分工具错误也可以交给大模型解释或选择其他工具。

Agents-Flex 通过以下配置处理这些情况:

配置作用
AgentRetryPolicy设置重试次数和每次重试前的等待时间
AgentRetryDecider判断当前错误是否适合重试
ToolErrorStrategy决定工具错误是终止任务,还是交回模型处理
ToolErrorMessageFactory控制模型看到的工具错误内容

这些能力最终通过 AgentExecutionPolicy 配置到 Agent。

配置自动重试 ​

java
AgentRetryPolicy retryPolicy = AgentRetryPolicy.builder()
    .maxRetries(3)
    .initialDelayMillis(1_000)
    .multiplier(2.0)
    .maxDelayMillis(30_000)
    .build();

AgentExecutionPolicy policy = AgentExecutionPolicy.builder()
    .retryPolicy(retryPolicy)
    .build();

上面的配置表示:首次执行失败后最多重试 3 次,第一次等待 1 秒,之后按 2 倍增加,但单次等待不超过 30 秒。

maxRetries 不包含第一次执行。AgentRetryPolicy.none() 表示关闭自动重试,也是默认行为。

重试过程 ​

发生可重试错误后,Runner 不会让当前线程一直等待,而是:

  1. 保存当前任务进度和错误信息;
  2. 将 AgentTurn 状态更新为 RETRY_SCHEDULED;
  3. 记录下次允许执行的时间;
  4. 等待时间到达后,由业务调度器调用 resume(turnId, AgentResumeCommand.retry()) 继续原任务。

这样,即使服务在等待期间重启,任务仍然可以从已保存的位置继续。

自动重试耗尽不等于所有错误都必须进入 FAILED。如果模型客户端抛出结构化 ModelException,Runner 会把 Turn 保存为 WAITING_FOR_MODEL,保留已经完成的模型消息、ToolCall 和 ToolMessage,等待修复条件后 继续。它与 RETRY_SCHEDULED 的区别是:后者有明确的下一次运行时间,需要由业务调度器检查并显式继续;前者需要 外部修复、显式 retryModel(...),或者一条新的用户消息。详见模型故障恢复。

重试范围 ​

默认情况下,网络异常、模型限流和服务过载等临时故障可以重试。以下错误通常不会直接重试:

  • 参数格式错误;
  • 找不到模型指定的工具;
  • 模型上下文超过限制;
  • 模型账号余额或配额耗尽;
  • 任务被取消;
  • 任务达到运行次数或资源预算上限。

应用可以通过 retryDecider(...) 自定义判断逻辑:

java
AgentExecutionPolicy policy = AgentExecutionPolicy.builder()
    .retryPolicy(retryPolicy)
    .retryDecider((turn, error, toolCall) ->
        error instanceof ModelRateLimitException
            || error instanceof ModelOverloadedException)
    .build();

自定义判断器应区分临时故障和业务错误。订单不存在、参数无效等确定性错误不应通过重复执行来解决。

工具错误处理 ​

工具执行失败时,可以选择两种处理方式:

策略行为适用场景
FAIL_RUN进入重试流程;不能重试时结束任务写入失败、安全检查失败等不能交给模型处理的错误
RETURN_ERROR_TO_MODEL把错误作为工具结果交回模型模型可以改用其他工具或向用户解释的错误

默认策略是 FAIL_RUN。

配置示例:

java
AgentExecutionPolicy policy = AgentExecutionPolicy.builder()
    .toolErrorStrategy(ToolErrorStrategy.RETURN_ERROR_TO_MODEL)
    .build();

将错误交回模型并不等于自动重试。模型会根据错误内容决定修改参数、选择其他工具或直接说明失败。

错误信息转换 ​

生产环境不应把异常堆栈、数据库信息或内部地址直接发送给大模型。可以通过 toolErrorMessageFactory(...) 转换错误内容:

java
AgentExecutionPolicy policy = AgentExecutionPolicy.builder()
    .toolErrorStrategy(ToolErrorStrategy.RETURN_ERROR_TO_MODEL)
    .toolErrorMessageFactory((turn, call, error) -> {
        ToolMessage message = new ToolMessage();
        message.setContent(
            "{\"code\":\"UPSTREAM_UNAVAILABLE\","
                + "\"message\":\"订单服务暂时不可用\"}"
        );
        return message;
    })
    .build();

Runner 会保留原工具调用的关联信息,Factory 只需要提供适合模型读取的错误内容。

异常结束消息 ​

任务取消或最终失败时,Runner 会补充结束说明,避免后续聊天历史停留在未完成的工具调用上。可以自定义这些内容:

java
AgentExecutionPolicy policy = AgentExecutionPolicy.builder()
    .interruptedToolMessageTemplate("工具 {toolName} 未完成:{reason}")
    .interruptedTurnMessageTemplate("本次任务未完成:{reason}")
    .cancellationReason("用户主动停止任务")
    .build();

这类模板主要用于后续模型上下文,不应代替面向用户的错误页面、日志或审计信息。

重试状态 ​

java
if (turn.getStatus() == AgentTurnStatus.RETRY_SCHEDULED) {
    System.out.println("已重试次数:" + turn.getRetryCount());
    System.out.println("下次执行时间:" + turn.getNextRunnableAt());
}

RETRY_SCHEDULED 表示任务尚未结束。模型结构化故障在重试次数用尽后进入 WAITING_FOR_MODEL;其他 失败通常进入 FAILED。

getRetryCount() 是 Turn 生命周期内累计安排的重试次数,适合监控;真正限制 maxRetries 的是 getConsecutiveRetryCount()。模型或工具成功、用户提交新消息或外部结果后,连续计数归零,但累计计数 保留。业务调度器使用的 RETRY 不会重置连续计数,避免持续故障无限重试。

工具的防重复执行 ​

工具可能已经完成业务操作,但 Runner 在保存结果前发生故障。任务恢复后,同一个工具调用可能再次执行。

退款、扣款、发货、发送邮件等工具必须使用稳定的幂等键识别重复请求:

java
String idempotencyKey = AgentToolContext.current().getIdempotencyKey();

业务数据库应保存该键,并在收到重复请求时返回第一次执行结果,而不是再次产生业务影响。

配置建议 ​

  1. 只重试可能自行恢复的临时故障。
  2. 写入类工具必须具备防重复执行能力。
  3. 避免 HTTP 客户端重试和 Agent 重试无限叠加。
  4. 对模型错误、工具错误、重试次数和最终状态分别记录指标。
  5. 工具错误交回模型前应进行脱敏,并提供明确的错误代码。

相关文档 ​