尧图建网站 尧图建网站 YAOTU WEB BUILD 免费咨询
ARTICLE DETAIL

资讯详情

深耕网站建设与建站编程的一线实战洞察。

Agent异常处理的可选性设计:从策略到工程实践

Agent异常处理的可选性设计:从策略到工程实践 之前在做 Agent 项目的异常治理时遇到一个很典型的问题同一个 Agent 在调用不同工具时失败的处理方式完全不一样有的要重试有的要静默还有的要兜底降级。一开始把所有异常都按同一种策略处理结果线上经常出现“某个工具失败了整个 Agent 任务被中断”的情况。后来重新梳理了 Agent 异常处理的“可选性”设计才算是把这块理顺。这篇文章就围绕“Agent 异常处理的可选性”展开从概念讲到代码实现再落到工程实践。如果你正在做 Agent 开发或者准备把 Agent 接入业务系统这篇文章应该能帮你少走不少弯路。1. Agent 异常处理为什么需要“可选性”1.1 什么是 Agent 开发Agent 这个词在技术圈已经很热了。简单来说Agent 是一个能够感知环境、做出决策并执行动作的智能体。在 AI 应用领域Agent 通常指通过大语言模型LLM驱动能够调用外部工具、访问知识库、执行任务流程的程序。一个典型的 Agent 工作流程大致如下接收用户请求。由 LLM 理解意图并规划任务。Agent 按计划调用工具或执行代码。将工具执行结果返回给 LLM。LLM 根据结果生成最终回复或继续下一步。在这个过程中工具调用是最容易出错的环节。比如调用外部 API 超时、数据库连接失败、第三方服务返回异常数据、文件读写权限不足等。这些问题不是“可能不会发生”而是“一定会发生”。1.2 异常处理的痛点在传统后端开发中异常处理已经有一套成熟的方法论try-catch、重试、熔断、降级、超时控制。但在 Agent 场景下情况会更复杂因为“谁来处理异常”这个问题变模糊了。比如一个订单查询 Agent它内部调用了用户服务、订单服务、库存服务。假设库存服务挂了应该怎么办直接抛出异常让整个请求失败用户只是想查订单没必要因为库存服务挂掉就什么都查不到。静默忽略库存异常返回订单信息并提示“库存信息暂不可用”这在很多时候是更合理的选择。重试三次再放弃如果库存服务已经熔断重试只会增加压力。不同场景需要不同的异常处理策略。这就是“可选性”的核心价值异常处理不应该是写死的单一策略而应该是可根据场景、工具类型、任务级别灵活配置的组合策略。1.3 可选性的三层含义在 Agent 异常处理中“可选性”可以从三个维度来理解第一层策略可选。针对不同类型的异常可以选择抛出、忽略、重试、降级、兜底等不同策略。第二层依赖可选。Agent 的某些能力是可选依赖。比如某个工具不可用时Agent 仍然可以完成主体任务只是准确率或完整度下降。第三层行为可选。在任务执行过程中Agent 可以根据上下文动态决定是否把某个中间错误暴露给用户还是把它包装成“部分成功”的结果。后续的代码示例会围绕这三层展开。2. 环境准备与版本说明在开始写代码之前先把环境整理清楚。本文的示例代码基于 Java 技术栈重点演示异常处理的思路不限制具体 Agent 框架。依赖项说明JDK建议 JDK 17 及以上构建工具Maven 3.8Web 框架Spring Boot 3.x示例思路同样适用于非 Spring 项目Agent 框架不强制依赖具体框架本文直接使用原生 Java 编写便于理解核心逻辑异步编程使用 CompletableFuture 处理耗时任务版本需要注意如果你使用的是 LangChain4j、Spring AI 或其他 Agent 框架异常处理的 API 可能略有差异但本文的核心设计模式是通用的。建议新建一个 Maven 项目项目结构如下agent-exception-demo/ ├── pom.xml └── src/main/java/com/example/agent/ ├── AgentTask.java ├── AgentExecutor.java ├── AgentResult.java ├── exception/ │ ├── AgentException.java │ ├── AgentExceptionHandler.java │ └── ExceptionStrategy.java └── tool/ ├── Tool.java ├── UserTool.java ├── OrderTool.java └── StockTool.java下面开始逐步实现。3. Agent 异常处理的核心设计模式3.1 传统 try-catch 的局限性很多 Agent 项目的第一版异常处理都长这样try { String result tool.execute(input); return result; } catch (Exception e) { log.error(tool execute failed, e); return 工具调用失败; }这段代码的问题很明显所有异常一视同仁。不管是网络超时、业务异常还是数据格式错误全部进入同一个 catch 分支。处理结果过于粗糙。用户无法区分是“工具不存在”“工具执行超时”还是“工具返回了空数据”。无法动态调整。如果想要改成“失败重试”需要改动代码而不是调整配置。无法感知上下文。Agent 的每一个步骤是否关键、是否需要降级这段代码完全无感知。3.2 异常类型的设计在 Agent 场景下我们至少需要区分以下几类异常异常类型含义典型场景ToolNotFoundException工具不存在Agent 调用了未注册的工具ToolExecutionException工具执行失败工具内部抛出了异常ToolTimeoutException工具调用超时外部 API 响应超过阈值ToolDataException工具返回数据异常返回 JSON 格式错误、字段缺失AgentInterruptedException任务被中断用户取消、权限校验失败在实际工程中可以定义这些异常类也可以直接使用通用异常配合错误码。下面是一个简化示例。// 文件路径src/main/java/com/example/agent/exception/AgentException.java public class AgentException extends RuntimeException { private final String errorCode; public AgentException(String errorCode, String message) { super(message); this.errorCode errorCode; } public AgentException(String errorCode, String message, Throwable cause) { super(message, cause); this.errorCode errorCode; } public String getErrorCode() { return errorCode; } }在此基础上定义几个具体异常// 文件路径src/main/java/com/example/agent/exception/ToolTimeoutException.java public class ToolTimeoutException extends AgentException { public ToolTimeoutException(String toolName, long timeoutMs) { super(TOOL_TIMEOUT, Tool [ toolName ] execution timeout after timeoutMs ms); } }// 文件路径src/main/java/com/example/agent/exception/ToolExecutionException.java public class ToolExecutionException extends AgentException { public ToolExecutionException(String toolName, Throwable cause) { super(TOOL_EXECUTION_ERROR, Tool [ toolName ] execution failed, cause); } }3.3 可选性策略设计“可选性”在代码层面的核心体现就是异常处理策略。我们定义一个枚举来表示策略类型// 文件路径src/main/java/com/example/agent/exception/ExceptionStrategy.java public enum ExceptionStrategy { // 抛出异常中止任务 THROW, // 重试若干次后抛出 RETRY, // 忽略异常返回降级结果 IGNORE, // 返回降级结果并记录告警日志 DEGRADE, // 使用默认兜底值 FALLBACK }每一种策略的含义THROW适用于关键步骤失败后整个任务无法继续。RETRY适用于临时性故障比如网络抖动、服务瞬时不可用。IGNORE适用于非关键步骤失败不影响主流程。DEGRADE返回一个降级结果比如空列表、默认文案。FALLBACK调用备用实现比如主服务失败后调用本地缓存。这样设计带来的“可选性”是同一个工具在不同场景下可以配置不同策略同一个任务的不同步骤也可以配置不同策略。3.4 配置化的异常处理在实际项目中不建议把策略硬编码在 catch 块里。推荐的做法是把策略作为元数据配置在工具上。// 文件路径src/main/java/com/example/agent/tool/Tool.java public interface Tool { String getName(); String execute(String input) throws Exception; /** * 默认异常策略抛出异常 */ default ExceptionStrategy strategy() { return ExceptionStrategy.THROW; } /** * 重试次数仅当 strategy 为 RETRY 时生效 */ default int maxRetries() { return 3; } /** * 超时时间单位毫秒 */ default long timeoutMs() { return 3000; } /** * 降级结果仅当 strategy 为 DEGRADE 或 FALLBACK 时生效 */ default String fallbackResult() { return ; } }这里把“是否重试”“超时多少毫秒”“失败后返回什么”都变成了工具的可选配置。不同的工具实现这些默认方法就可以拥有独立的异常处理行为而不需要改公共代码。4. 完整实战一个带可选异常处理的 Agent4.1 需求说明我们来实现一个简单的“订单查询 Agent”。它的职责是根据用户 ID 查询用户基本信息。根据用户 ID 查询订单列表。根据订单列表关联查询库存状态。三个步骤的依赖关系是用户信息和订单查询可以并行库存状态依赖订单结果。我们对异常处理的要求是用户服务异常抛错整个任务失败。订单服务异常重试 2 次仍然失败则抛出异常。库存服务异常忽略返回空库存不影响订单结果。4.2 实现工具类先实现三个工具。// 文件路径src/main/java/com/example/agent/tool/UserTool.java import com.example.agent.exception.ExceptionStrategy; import com.example.agent.exception.ToolExecutionException; public class UserTool implements Tool { private final boolean available; public UserTool(boolean available) { this.available available; } Override public String getName() { return userTool; } Override public String execute(String input) throws Exception { if (!available) { throw new ToolExecutionException(getName(), new RuntimeException(user service unavailable)); } return {\userId\:\u_1001\,\name\:\张三\}; } Override public ExceptionStrategy strategy() { return ExceptionStrategy.THROW; } }// 文件路径src/main/java/com/example/agent/tool/OrderTool.java import com.example.agent.exception.ExceptionStrategy; public class OrderTool implements Tool { private int callCount 0; Override public String getName() { return orderTool; } Override public String execute(String input) throws Exception { callCount; // 模拟前两次调用失败第三次成功 if (callCount 3) { throw new RuntimeException(order service temporary error, count callCount); } return [{\orderId\:\o_2024001\,\amount\:199.90}]; } Override public ExceptionStrategy strategy() { return ExceptionStrategy.RETRY; } Override public int maxRetries() { return 2; } }// 文件路径src/main/java/com/example/agent/tool/StockTool.java import com.example.agent.exception.ExceptionStrategy; public class StockTool implements Tool { private final boolean available; public StockTool(boolean available) { this.available available; } Override public String getName() { return stockTool; } Override public String execute(String input) throws Exception { if (!available) { throw new RuntimeException(stock service unavailable); } return {\orderId\:\o_2024001\,\stockStatus\:\IN_STOCK\}; } Override public ExceptionStrategy strategy() { return ExceptionStrategy.IGNORE; } Override public String fallbackResult() { return {}; } }注意这里的设计意图OrderTool故意模拟了“前两次失败、第三次成功”的情况用于验证重试策略。StockTool配置为IGNORE用于验证“库存服务不可用但不影响主流程”。4.3 实现异常处理器接下来是核心部分异常处理器。它根据工具配置的策略来决定如何处理异常。// 文件路径src/main/java/com/example/agent/exception/AgentExceptionHandler.java import com.example.agent.tool.Tool; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class AgentExceptionHandler { private static final Logger log LoggerFactory.getLogger(AgentExceptionHandler.class); /** * 执行工具调用并根据策略处理异常。 * * param tool 工具实例 * param input 工具输入参数 * return 工具返回结果 */ public String executeWithStrategy(Tool tool, String input) { ExceptionStrategy strategy tool.strategy(); if (strategy ExceptionStrategy.THROW) { return this.executeWithThrow(tool, input); } if (strategy ExceptionStrategy.RETRY) { return this.executeWithRetry(tool, input); } if (strategy ExceptionStrategy.IGNORE) { return this.executeWithIgnore(tool, input); } if (strategy ExceptionStrategy.DEGRADE || strategy ExceptionStrategy.FALLBACK) { return this.executeWithFallback(tool, input); } // 默认走抛出策略 return this.executeWithThrow(tool, input); } private String executeWithThrow(Tool tool, String input) { try { return tool.execute(input); } catch (Exception e) { log.error(Agent tool [{}] execution failed, strategyTHROW, tool.getName(), e); throw new AgentException(TOOL_EXECUTION_ERROR, Tool [ tool.getName() ] execution failed, e); } } private String executeWithRetry(Tool tool, String input) { int maxRetries tool.maxRetries(); Exception lastException null; for (int i 0; i maxRetries; i) { try { return tool.execute(input); } catch (Exception e) { lastException e; log.warn(Agent tool [{}] execution failed, retry {}/{}, tool.getName(), i, maxRetries); } } throw new AgentException(TOOL_RETRY_EXHAUSTED, Tool [ tool.getName() ] retry exhausted after maxRetries attempts, lastException); } private String executeWithIgnore(Tool tool, String input) { try { return tool.execute(input); } catch (Exception e) { log.warn(Agent tool [{}] execution failed, ignored, return default result, tool.getName(), e); return tool.fallbackResult(); } } private String executeWithFallback(Tool tool, String input) { try { return tool.execute(input); } catch (Exception e) { log.warn(Agent tool [{}] execution failed, use fallback result, tool.getName(), e); return tool.fallbackResult(); } } }这里体现的是“策略可选”的第一层设计。调用方不需要关心某个工具内部如何使用 try-catch只需要配置好策略异常处理逻辑统一收敛到AgentExceptionHandler中。4.4 实现 Agent 执行器Agent 执行器负责编排任务。它调用异常处理器执行各个工具并汇总结果。为了演示异步处理这里使用CompletableFuture实现用户服务和订单服务的并行调用。// 文件路径src/main/java/com/example/agent/AgentExecutor.java import com.example.agent.exception.AgentException; import com.example.agent.exception.AgentExceptionHandler; import com.example.agent.tool.Tool; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; public class AgentExecutor { private static final Logger log LoggerFactory.getLogger(AgentExecutor.class); private final AgentExceptionHandler exceptionHandler new AgentExceptionHandler(); private final ExecutorService executorService Executors.newFixedThreadPool(4); public AgentResult execute(String userId) { try { // 1. 并行调用用户服务和订单服务 Tool userTool new UserTool(true); Tool orderTool new OrderTool(); CompletableFutureString userFuture CompletableFuture .supplyAsync(() - exceptionHandler.executeWithStrategy(userTool, userId), executorService); CompletableFutureString orderFuture CompletableFuture .supplyAsync(() - exceptionHandler.executeWithStrategy(orderTool, userId), executorService); String userInfo userFuture.get(5, TimeUnit.SECONDS); String orderInfo orderFuture.get(5, TimeUnit.SECONDS); // 2. 根据订单结果查库存 Tool stockTool new StockTool(false); String stockInfo exceptionHandler.executeWithStrategy(stockTool, orderInfo); return new AgentResult(userInfo, orderInfo, stockInfo); } catch (Exception e) { log.error(Agent task execution failed, e); throw new AgentException(AGENT_EXECUTION_ERROR, Agent task execution failed, e); } finally { executorService.shutdown(); } } }这里有几个关键点需要说明userFuture.get(5, TimeUnit.SECONDS)是超时控制超过 5 秒按失败处理。使用supplyAsync包装exceptionHandler.executeWithStrategy可以让异常处理逻辑在异步线程中同样生效。StockTool(false)传入false代表库存服务不可用用于演示忽略策略的效果。4.5 定义结果对象执行器返回一个AgentResult用于承载三个步骤的结果。// 文件路径src/main/java/com/example/agent/AgentResult.java public class AgentResult { private final String userInfo; private final String orderInfo; private final String stockInfo; public AgentResult(String userInfo, String orderInfo, String stockInfo) { this.userInfo userInfo; this.orderInfo orderInfo; this.stockInfo stockInfo; } public String getUserInfo() { return userInfo; } public String getOrderInfo() { return orderInfo; } public String getStockInfo() { return stockInfo; } Override public String toString() { return AgentResult{ userInfo userInfo \ , orderInfo orderInfo \ , stockInfo stockInfo \ }; } }4.6 运行与验证最后写一个入口类来验证整个流程。// 文件路径src/main/java/com/example/agent/AgentApplication.java public class AgentApplication { public static void main(String[] args) { AgentExecutor executor new AgentExecutor(); AgentResult result executor.execute(u_1001); System.out.println(result); } }运行后输出预期如下AgentResult{userInfo{userId:u_1001,name:张三}, orderInfo[{orderId:o_2024001,amount:199.90}], stockInfo{}}结果分析用户服务正常返回用户信息。订单服务前两次调用失败第三次成功说明重试策略生效。库存服务不可用但被忽略并返回默认空结果{}整个任务不受影响。这就是“可选性”的实际效果不同工具可以根据自身重要性选择不同的失败行为。4.7 模拟关键步骤失败如果把UserTool的可用性改为false即用户服务不可用Tool userTool new UserTool(false);运行后会看到以下现象Exception in thread main com.example.agent.exception.AgentException: Tool [userTool] execution failed因为UserTool的策略是THROW所以它的失败会直接中断整个 Agent 任务。这在业务上也是合理的——查订单时连用户信息都拿不到继续执行没有意义。5. 异步编程中的异常处理要点在上面的示例中我们使用了CompletableFuture这也是 Agent 开发中常见的异步编程方式。但 CompletableFuture 的异常处理有一些容易踩坑的地方。5.1 get() 与 join() 的异常差异CompletableFuture.get()抛出的是受检异常调用方必须处理InterruptedException和ExecutionException。而join()抛出的是非受检的CompletionException。在实际 Agent 开发中更推荐统一处理// 不推荐异常信息容易丢失 String result future.join(); // 推荐保留完整异常链 try { String result future.get(5, TimeUnit.SECONDS); } catch (TimeoutException e) { // 处理超时 } catch (ExecutionException e) { // 处理任务执行异常 Throwable cause e.getCause(); } catch (InterruptedException e) { Thread.currentThread().interrupt(); }5.2 异步任务中的异常丢失问题一个常见问题是使用supplyAsync时如果内部没有 catch 异常异常会包装在CompletionException中。如果调用方又没有检查isCompletedExceptionally()异常可能被静默吞掉。推荐在进入异步线程时对 Agent 执行做统一包装CompletableFutureString userFuture CompletableFuture .supplyAsync(() - { try { return exceptionHandler.executeWithStrategy(userTool, userId); } catch (Exception e) { // 在这里打日志保留异常上下文 log.error(Async tool [{}] failed, userTool.getName(), e); throw e; } }, executorService);5.3 回调式异常处理有时我们需要在异步任务完成后执行不同的分支。CompletableFuture提供了exceptionally方法这也是 Agent 异常处理“可选性”的一种体现CompletableFutureString userFuture CompletableFuture .supplyAsync(() - exceptionHandler.executeWithStrategy(userTool, userId), executorService) .exceptionally(ex - { // 可选在回调中决定降级结果 return {\userId\:\unknown\}; });但要注意exceptionally只处理异常情况如果supplyAsync内部已经捕获了异常并返回默认值那么exceptionally不会触发。需要根据实际业务决定在哪一层处理。6. 常见问题与排查思路写 Agent 异常处理的时候下面这几种问题是高频出现的情况整理成表格供你快速排查。问题现象常见原因解决思路Agent 执行器无响应直到超时工具调用没有设置超时时间或者超时时间过长给每个工具设置合理的timeoutMs()并在异常处理器中统一包装超时逻辑某个工具失败导致整个任务失败但业务上不需要异常策略默认使用了THROW检查该工具的strategy()配置改为IGNORE或DEGRADE重试导致多次重复执行maxRetries()配置过大或者盲目对非幂等操作重试确认工具是否幂等非幂等操作不要开启重试异步任务异常没有日志CompletableFuture 内部异常被包装调用方没有检查在supplyAsync内部捕获异常并打日志降级结果格式不符合 LLM 预期fallbackResult()返回了空字符串或非法 JSON返回与正常结果结构一致的降级数据比如{}或空数组错误信息对用户不友好直接把底层异常堆栈展示给用户在AgentException中定义错误码由上层统一映射为友好提示服务熔断后仍然频繁重试代码逻辑只做了本地重试没有感知全局熔断状态接入断路器等能力在开启熔断时跳过重试直接降级这里重点说下the agent execution provider did not respond in time这类问题。很多 Agent 框架在调用 LLM 或外部工具时有默认超时时间如果你遇到“执行者没有及时响应”的报错一般排查顺序是检查外部服务是否正常用 curl 或其他工具直接调一下接口。检查超时配置是否过短比如模型本身响应就需要 10 秒只配了 3 秒超时。检查是否有并发阻塞比如线程池被打满导致任务排队。检查是否开启了重试如果每次超时都重试会放大资源消耗。7. 可选性在 Agent 架构中的更多实践7.1 能力可选工具注册与发现在完整的 Agent 框架中工具不会像上文一样直接 new 出来而是通过注册中心管理。工具注册时可以携带异常策略元数据# 工具配置文件示例tool-registry.yaml tools: - name: userTool enabled: true strategy: THROW timeoutMs: 3000 - name: orderTool enabled: true strategy: RETRY maxRetries: 2 timeoutMs: 5000 - name: stockTool enabled: true strategy: IGNORE fallbackResult: {}这样运维和开发可以在不修改代码的情况下调整 Agent 的异常行为。这就是“可选性”在部署层面的应用。7.2 任务级降级有些 Agent 任务本身是“尽力而为”的。比如一个每日新闻摘要 Agent如果某个新闻源接口挂了不应该影响整个摘要生成。此时可以在任务级别配置降级策略public class AgentTask { // 任务是否允许部分成功 private boolean partialSuccessAllowed; // 最小成功工具数 private int minSuccessTools; // getter / setter 省略 }这样Agent 执行器可以在任务结束时检查成功工具数如果达到最小阈值则返回部分成功的结果。7.3 可选参数与上下文另一种“可选性”体现在 Agent 的输入参数上。有些参数是可选的如果 LLM 没有提取到工具调用可以直接跳过而不是抛出异常。在设计 Tool 接口时可以增加一个“参数是否可选”的标记public interface ToolParameter { String name(); boolean required(); String defaultValue(); }对于可选参数Agent 在组装工具入参时做一层过滤缺失时使用默认值。这可以避免因为某个可选字段没传整个工具调用失败。8. 最佳实践与工程建议基于上面的实战和踩坑经验整理几条对 Agent 异常处理特别有用的工程建议。8.1 回归“非 Agent 应用”的异常处理原则不要把 Agent 异常处理想得过于特殊。传统的异常处理原则在 Agent 场景同样适用异常类型要细分不要吞掉原始异常。日志要包含工具名、输入参数标识、错误码、耗时。对外暴露错误时只暴露用户能理解的信息不要把完整堆栈直接返回。重试要有上限且必须考虑幂等性。降级结果要和正常结果保持结构一致方便上层解析。8.2 为核心工具链提供“可观测性”Agent 的链路比传统接口更长一个问题可能出在 LLM 规划、工具调用、参数组装、结果解析等任意环节。建议在异常处理器中埋入指标指标名含义agent_tool_total工具调用总数agent_tool_failure_total工具调用失败数agent_tool_timeout_total工具调用超时数agent_tool_retry_total工具重试次数agent_tool_degraded_total工具降级次数agent_task_success_totalAgent 任务成功数agent_task_partial_totalAgent 任务部分成功数agent_task_failure_totalAgent 任务失败数通过这些指标可以快速判断 Agent 的“健康度”。如果降级次数突然升高说明依赖的下游服务出现了问题需要及时关注。8.3 谨慎设计重试和降级重试和降级是可选性策略中使用频率最高的两个方案但也是最容易出问题的。重试的风险非幂等操作重试会导致重复数据。热点服务故障时盲目重试会放大流量冲击。重试间隔过短等于没重试。降级的风险降级数据如果结构不对LLM 可能“一本正经地胡说八道”。降级结果可能掩盖真实故障让问题难以被发现。建议建立一套规则写操作不重试读操作可重试核心链路不降级非核心链路可降级降级必须打日志并记录指标。8.4 让 Agent 本身具备“异常解释能力”这是 Agent 项目比较特别的一点。传统应用捕获异常后直接把堆栈打出来就行。但在 Agent 场景LLM 需要理解异常并在回复中向用户解释。一个推荐的流程是工具调用失败后异常处理器记录结构化错误信息工具名、错误码、错误摘要。将错误信息作为上下文传给 LLM。LLM 根据错误信息决定是重试、跳过还是在最终回复中向用户说明。示例[System Context] Tool stockTool execution failed with error code TOOL_EXECUTION_ERROR. Error message: stock service unavailable. Strategy applied: IGNORE. Fallback result: {}. [Assistant] 您的订单信息已查询成功但库存状态暂时无法获取建议稍后重试。这种“Agent 可选地决定如何向用户呈现异常”的能力是 Agent 应用体验的重要部分。8.5 安全边界与最小权限Agent 工具一旦开放给用户就面临更大的安全风险。在异常处理层面也要考虑不在日志中打印敏感参数比如用户手机号、身份证号、Token。不在异常消息中暴露内部服务地址、数据库连接信息。对工具的输入做校验避免用户构造恶意参数。涉及删除、更新等敏感操作的工具默认使用THROW策略不要自动重试、自动降级。9. 总结与下一步学习本文围绕“Agent 异常处理的可选性”从概念讲到实战再落到工程实践核心内容可以概括为三条主线第一策略可选。通过ExceptionStrategy枚举和Tool接口的默认方法让每个工具可以独立配置异常行为解决“一个策略走天下”的问题。第二依赖可选。通过配置化的工具注册让 Agent 的某些能力成为可选依赖非核心服务挂掉不影响主任务。第三结果可选。通过fallbackResult和任务级降级让 Agent 在部分失败时仍然能给出可用结果并且把情况清楚地告诉上层。下一步你可以继续探索几个方向选择一个成熟的 Agent 框架比如 LangChain4j 或 Spring AI把你自己的异常处理策略接入框架。研究 LLM 工具调用的内容校验避免模型“幻觉”导致参数错误。为 Agent 增加全局熔断、限流能力结合异常策略形成更完整的容错体系。用 Micrometer 或 Prometheus 把上文提到的指标埋点落地搭建 Agent 监控面板。如果你正在做的 Agent 项目还没有系统的异常处理设计可以从本文的工具级别开始改造先让每个工具具备独立的策略配置再逐步加入任务级降级和指标观测。这样即使后面业务复杂度上来了容错体系也不会成为瓶颈。
返回列表