pydantic-ai 0.0.20 里注册了一个查库存的工具,内部用 requests.get(timeout=5),上游一慢就抛 requests.Timeout,整轮 agent.run 直接把这个异常抛给调用方,模型没有机会换参数重试。

一开始怀疑是「Agent 的 retries 默认值只有 1,重试一次就放弃」,查了一圈,方向不对。

把日志和配置对完,能解释这个现象的基本就这几处。工具函数没有捕获网络异常,异常直接冒泡到运行器。另一种情况是没有用 ModelRetry 告诉模型这次失败可以重来。

另外,工具返回 None 被当成成功,后续解析又报错。

上来先在工具里捕获异常并返回可读的错误文本

python -c "import requests;print('except requests.Timeout: return \"库存服务超时\"')"

再往下把可重试的失败包装成 ModelRetry

python -c "from pydantic_ai import ModelRetry;print(ModelRetry('库存接口超时,请换仓库编号重试'))"

提高 Agent 的重试次数并限制工具超时

python -c "from pydantic_ai import Agent;a=Agent('openai:gpt-4o-mini', retries=3);print(a)"

等前面都确认过,再用 mock 让工具稳定超时,验证整轮是否还能收敛

python -c "print({'tool':'get_stock','mock':'timeout'})"

恢复的判定其实很直接。工具超时后模型收到 ModelRetry 的提示,换了仓库编号再次调用并成功,agent.run 返回正常结果而不是抛异常。

容易忽略的是,工具的异常边界要自己兜住,网络错误、限流、空结果这三类都应该转成模型能理解的文字,让它决定重试还是换方案。拖得越久,排查成本越高,因为现场状态会被后续操作覆盖。

作者 9823189