登录
推荐 文章 Go 技术 课程 下载 专题 AI
首页 >  科技周边 >  人工智能

AI Agent 调用外部工具超时后怎么设计可恢复结果

来源:17golang原创

时间:2026-09-08 06:21:30 203浏览 收藏

AI Agent 调用外部工具超时后,最稳妥的处理不是把异常文字原样塞回模型,也不是无条件再提交一次。应先把结果分成“未调用成功、执行状态未知、已确认失败”三类,再由工具适配层决定重试、查询、转人工或结束。这样模型拿到的是可判断的状态,用户也能得到一个可继续处理的结果。

把超时设计成状态机:schema 负责输入形状,业务校验负责可执行条件,适配层负责截止时间与幂等键,恢复记录负责证明下一次动作不会重复产生副作用。
要点速览
  • 超时不是空结果,至少要区分参数未通过、执行未知和确认失败。
  • 有副作用的工具必须携带幂等键;未知状态先查状态或对账,不要直接重提。
  • 把总预算、重试次数、脱敏日志和恢复入口放在工具适配层统一处理。

先把工具超时变成可识别的结果对象

一次调用至少有三条边界:请求是否通过校验、外部系统是否开始执行、调用方是否在截止时间内拿到响应。网络超时只能说明“当前调用方没有拿到结果”,不能证明外部动作没有发生。

// ToolResult 让上层根据状态决定重试、查询还是结束
type ToolResult struct {
	RequestID string `json:"request_id"`
	Status    string `json:"status"` // succeeded、rejected、unknown、failed
	Code      string `json:"code"`
	Message   string `json:"message"`
	Retryable bool   `json:"retryable"`
}

// timeout 只描述本次等待超时,不替外部系统猜测执行结果
func timeoutResult(id string) ToolResult {
	return ToolResult{RequestID: id, Status: "unknown", Code: "TOOL_TIMEOUT", Retryable: false}
}

unknown 是关键状态。对于查询天气、读取文档这类幂等读操作,可以在预算内重新查询;对于扣款、下单、发货这类写操作,必须先用 request_id 查询外部状态,确认没有执行后才考虑补偿。回传给模型的 Message 只保留动作建议和错误码,不要放入 Token、完整请求头或敏感参数。

AI Agent 外部工具超时结果静态关系图,展示工具 Schema、参数校验、超时策略、工具适配器、恢复记录与 Agent 结果边界
图1:工具 Schema、参数校验和超时策略共同决定 Tool Adapter 能返回哪一种可恢复结果,Agent 只消费经过整理的状态。

用 schema 与参数校验挡住无效重试

schema 解决“字段是否存在、类型是否正确、格式是否符合约定”,业务校验解决“这个请求现在能不能执行”。例如 order_id 通过字符串校验,不代表订单仍处于可取消状态。两层校验都通过后,才进入外部工具。

阶段检查内容失败回传
schema必填字段、类型、枚举、长度指出可修正字段,状态为 rejected
业务规则权限、资源状态、幂等键返回明确业务码,不调用工具
适配层截止时间、连接和响应格式区分 failed 与 unknown
恢复层查询状态、重试预算、人工入口返回可继续处理的 recovery 状态
// 参数校验失败时,给 Agent 一个可修正的字段提示
func validateArgs(args map[string]any) ToolResult {
	orderID, ok := args["order_id"].(string)
	if !ok || orderID == "" {
		return ToolResult{Status: "rejected", Code: "MISSING_ORDER_ID", Message: "请补充 order_id"}
	}
	return ToolResult{Status: "succeeded", Code: "ARGS_OK"}
}

重试请求还要保留原始幂等键,而不是每次生成新的请求号。否则第一次请求可能已在服务端成功,第二次请求又被当成一笔新操作。对于不支持幂等的写工具,宁可进入恢复队列,也不要把“再试一次”交给模型自由决定。

AI Agent 工具恢复静态关系图,展示幂等键、工具适配层、未知状态、状态查询、恢复队列与最终响应之间的边界
图2:恢复边界要把未知状态、状态查询和恢复队列隔开,幂等键贯穿工具适配层与恢复记录。

让重试与恢复路径拥有明确边界

可以把决策写成一张小表,而不是让模型根据一段模糊异常自行发挥:

状态读工具有副作用的写工具
rejected修正参数后重新调用修正参数后重新调用
unknown在剩余预算内重试或查询先查状态,必要时转恢复队列
failed按错误码决定是否退避保留失败原因,禁止盲目补提

重试上限应同时受次数和时间预算约束。比如单次工具最多等待 3 秒、恢复查询最多 2 次,并把剩余预算传给适配层;不能每次重试都重新获得一个完整的 3 秒窗口。对用户而言,“正在确认外部系统状态”比“工具调用失败”更有帮助,因为前者保留了恢复入口。

把超时预算和安全回传一起落地

生产实现中,日志至少记录 request_id、工具名、状态变化、耗时、重试次数和最终恢复动作。参数应记录摘要或脱敏后的字段,不能把访问令牌、Cookie、完整地址或个人信息直接回传给模型。最终响应可以包含三部分:当前状态、用户下一步、是否需要人工处理。

验收时准备四组固定样例:schema 缺字段、工具在截止时间前明确失败、响应超时但服务端已成功、连续查询仍无法确认。检查点不是“模型说得像不像”,而是状态是否稳定、幂等键是否复用、恢复动作是否可追踪,以及总耗时是否没有突破预算。

常见问题

超时后直接重试为什么危险?

因为调用方只知道响应没回来,不知道外部动作有没有发生。写操作可能已经成功,直接重试会产生重复订单、重复扣款或重复任务。

模型应该看到完整异常堆栈吗?

不应该。模型需要稳定的错误码、状态和下一步建议;堆栈、密钥、请求头和敏感参数应留在受控日志中。

什么时候可以自动重试?

参数已通过、工具是幂等读操作或具备可靠幂等键,并且剩余时间预算足够时,才适合按上限和退避策略自动重试。

可恢复结果的核心不是把 Agent 变得更会猜,而是让工具调用提供稳定的状态边界。先校验,再调用;超时后先确认状态;每次恢复都沿用幂等标识,系统才既能继续工作,也能避免把不确定性变成重复副作用。

声明:本文转载于:17golang原创 如有侵犯,请联系study_golang@163.com删除
相关阅读
更多>
最新阅读
更多>
课程推荐
更多>