
摘要工具错误处理的核心不是避免错误而是让 Agent 看到错误。不抛异常、返回错误信息、实现重试让 Agent 具备自修正能力。引言你有没有遇到过这种情况Agent 调用工具后突然沉默了没有任何响应工具明明执行失败了Agent 却以为成功了继续往下走一个小小的网络超时导致整个对话流程中断这些问题的根源往往是工具的错误处理没做好。在传统编程中我们习惯用异常来处理错误。但在 Agent 系统中这套做法会害了Agent。因为 Agent 的决策完全依赖工具返回的文本——如果工具抛出异常Agent 根本看不到异常内容就像一个盲人摸象只能靠猜测继续行动。核心概念核心原则不抛异常返回错误信息这是工具错误处理的第一性原理工具永远不要抛出异常而是将错误转换为字符串返回。为什么因为 Agent 的决策链路是这样的用户输入 → Agent 思考 → 调用工具 → 读取工具输出 → 继续思考如果工具抛出异常这个链路就断了。Agent 无法读取异常内容也就无法做出正确的后续决策。错误分类与处理策略错误类别示例处理方向输入验证错误缺少必填参数、参数类型错误返回清晰错误信息提示正确格式外部依赖错误网络超时、API 5xx、数据库连接失败区分临时性可重试与永久性错误业务逻辑错误查询无结果、权限不足、资源不存在返回人类可读的错误描述工具内部异常除零错误、索引越界、空指针捕获并转换为工具返回的一部分可重试 vs 不可重试类型特征处理方式临时性错误网络超时、API 限流、服务暂时不可用使用指数退避重试永久性错误参数错误、权限不足、资源不存在直接返回错误让 Agent 调整输入代码示例基础工具内部的 try/except最简单的错误处理就是在工具内部捕获所有异常fromlangchain_core.toolsimporttooltooldefdivide(a:float,b:float)-str:除法运算。try:resulta/breturnstr(result)exceptZeroDivisionError:return错误除数不能为零请提供一个非零的除数。exceptExceptionase:returnf计算失败{str(e)}# 测试print(divide.invoke({a:10,b:2}))# 输出5.0print(divide.invoke({a:10,b:0}))# 输出错误除数不能为零...关键点无论发生什么工具都返回字符串。Agent 能看到错误内容就知道下一步该怎么做。高阶使用 tenacity 实现重试对于临时性错误如网络超时重试是最佳策略。tenacity库让重试逻辑变得优雅fromlangchain.toolsimporttoolfromtenacityimportretry,stop_after_attempt,wait_exponential,retry_if_exception_typeimportrequeststoolretry(stopstop_after_attempt(3),waitwait_exponential(multiplier1,min2,max10),retryretry_if_exception_type(requests.exceptions.Timeout))deffetch_web_data(url:str)-str:从指定 URL 获取数据。try:responserequests.get(url,timeout5)response.raise_for_status()returnresponse.textexceptrequests.exceptions.HTTPErrorase:# 4xx 错误不重试直接返回ife.response.status_code500:returnf请求失败{e.response.status_code}{e.response.reason}# 5xx 错误可以重试raiseexceptrequests.exceptions.Timeout:# 超时错误会触发重试raiseexceptExceptionase:returnf未知错误{str(e)}# 如果 3 次重试都失败tenacity 会抛出异常# 但我们可以结合 handle_tool_error 来兜底重试策略说明stop_after_attempt(3)最多重试 3 次wait_exponential(multiplier1, min2, max10)指数退避等待 2s → 4s → 8s最大 10sretry_if_exception_type(Timeout)只对超时错误重试最佳实践1. 工具内部捕获所有异常tooldefmy_tool(param:str)-str:try:# 业务逻辑passexceptSpecificErrorase:returnf特定错误{str(e)}exceptExceptionase:returnf未知错误{str(e)}永远不要让异常逃逸出工具函数。2. 错误信息要清晰、可操作❌差的错误信息错误✅好的错误信息错误API 调用失败状态码 401。请检查 API Key 是否正确配置。✅更好的错误信息错误无法找到用户 john_doe。请确认用户名拼写正确或尝试使用用户 ID 查询。3. 为临时性错误实现重试使用tenacity库但要注意只对临时性错误重试网络超时、API 限流不要对永久性错误重试参数错误、权限不足设置合理的重试次数和等待时间retry(stopstop_after_attempt(3),waitwait_exponential(multiplier1,min2,max10),retryretry_if_exception_type((Timeout,RateLimitError)))4. 在 Agent 系统提示中加入错误处理指导system_prompt你是一个智能助手。 当工具调用失败时 1. 仔细阅读错误信息 2. 如果是输入错误修正参数后重试 3. 如果是临时性错误等待后重试 4. 如果是永久性错误告知用户并建议替代方案 永远不要忽略错误信息。 5. 记录错误日志在生产环境中错误日志至关重要importlogging loggerlogging.getLogger(__name__)def_handle_error(error:Exception)-str:logger.error(f工具执行失败{error},exc_infoTrue)returnf工具执行出错{error}。请稍后重试。总结工具错误处理的核心原则不抛异常返回错误信息Agent 依赖工具输出做决策错误信息要清晰、可操作告诉 Agent 发生了什么、如何修正使用 handle_tool_error 统一处理作为兜底机制为临时性错误实现重试使用 tenacity区分可重试与不可重试错误Agent 级别也要处理错误handle_parsing_errors让 Agent 自我修正记录错误日志便于监控和调试记住在 Agent 系统中错误不是终点而是新的起点。让 Agent 看到错误它才能学会如何避免错误。