ARTICLE · 1145205
后台工具一报错,Pydantic AI 为何停了?
你让 Agent 并行查资料、读文件、调用服务。它先回复“后台任务已开始”,过一会儿却直接报错,旁边正在跑的任务也停了。团队容易把这归因于模型不稳定,实际上更该检查后台工具抛出了什么异常。Pydantic AI 的 BackgroundTools 在近期版本中调整了这条错误路径:意外异常会结束当前 Agent 运行,而不再被包装成一句失败文本交给模型继续编。
这对正在使用 pydantic-ai-harness 的开发者是兼容性问题,也是一个工程边界问题:哪些失败允许模型自我修正,哪些失败必须交还应用程序?

后台工具的异常分流:模型可处理的错误返回模型,意外异常结束运行
先弄清后台工具在做什么
官方文档中的 BackgroundTools 适用于慢工具:模型发起调用后先收到“任务已开始”和任务 ID,可以继续做别的事;工具完成后,结果以同一任务 ID 的后续消息交给模型。默认只有标记了 metadata={'background': True} 的工具被选中。它是 Pydantic AI Harness 中的能力,不等于 Python 任意后台线程,也不等于把任务交给独立队列后永不等待。
文档明确说,正常的 Agent 运行会等自己的后台工具完成。如果运行提前暂停或停止,未完成的工具会被取消;异步工具需要配合取消。同步工具则无法在返回前被 Python 强行停止。这意味着“Agent 结束”与“外部副作用已撤销”不是同一句话:已经发出的支付、写库或邮件请求,可能不会因任务取消自动回滚。
这段最后的业务推论是工程判断。它提醒我们不要把框架层的取消误当作事务保障,尤其是并发调用会修改同一份数据时。
这次变更究竟改变了什么
项目的 v2.54.0 Release 将它列在兼容性说明中,对应合并的 PR #9434。PR 描述的旧行为是:普通顺序工具抛出意外异常时运行结束;同样的异常若来自 BackgroundTools,却被变成 failed: <TypeName> 发给模型,运行继续。操作者可能只看到模型最终回复,而没有注意到真实故障。
新行为让两类工具一致:后台工具出现意外异常,原异常会让运行结束,同时取消其他尚在运行的后台工具。ModelRetry、ToolFailed、需要审批或延后执行的错误仍按设计返回模型;重试预算耗尽也会结束运行。这里的“取消其他任务”是框架的控制流,不保证已经产生的外部效果被撤销。
上表是依据官方错误语义做的选型整理,不是说所有超时都该包成 ModelRetry。如果鉴权失败、数据结构变更或代码访问了不存在的字段,给模型一句“再试一次”往往只会重复失败并增加费用。
升级前先做一轮小范围回归
先在代码里找使用 BackgroundTools()、metadata={'background': True},或通过名称选中后台工具的地方。标出工具会不会写库、发通知、下单、改权限。只有纯读取的慢查询,取消后的恢复通常比较简单;有副作用的调用还需要幂等键、最终状态检查和人工接管条件。
随后构造三类故障。第一类是输入可修正,验证工具明确抛出的 ModelRetry 是否给模型合理提示;第二类是预期内的业务失败,验证 ToolFailed 后模型能否改走允许的步骤;第三类是未捕获的异常,验证外层调用者确实收到原异常,另一个正在运行的后台工具停止。最后在外部系统核对副作用,而不能只检查 Agent 的回复。
一条有用的运行日志可以长这样。字段与值是建议的日志设计,并非本文实测:
{ "run_id": "order-42-attempt-2", "tool_name": "check_inventory", "background_task_id": "task-b", "error_class": "UnexpectedServiceError", "handling": "terminate_run", "sibling_task_state": "cancel_requested", "external_state_checked": false } 保留 run_id、工具名、异常类型、并发任务 ID 和外部状态核对结果,是为了分辨“框架取消了任务”和“业务动作已经完成”。cancel_requested 尤其不能直接写成“退款已撤回”或“数据库未修改”。如果操作本身可能重试,应把业务幂等键及外部回执也写进同一条链路。
什么时候该把错误交给模型
判断标准不是异常名字是否吓人,而是模型有没有安全、明确、被授权的下一步。例如用户请求检索的参数过窄,工具可以明确提示模型换一个查询;某个候选来源打不开,模型可尝试另一条已批准来源。反过来,凭证失效、数据库连接配置错误或返回内容违反约定,模型没有修复权限,继续生成“已完成”更危险。
团队可以把后台工具分成“只读、可重试”和“有副作用、需验收”两组。前者关注模型能否得到可操作的错误信息和重试上限;后者还要约束并发、保存操作回执、事后核对最终状态。官方文档还提醒:顺序工具可能与早先启动的后台工具重叠,两个工具若不能安全并发,就不要仅靠提示词要求它们排队。
另外要留意读取结果的方式。文档指出 run_stream() 和 run_stream_sync() 会等待后台工具,却不会把后续结果交给模型;如果最终回答必须使用结果,应使用文档列出的其他运行接口或完整消费迭代事件。排障时若只看流式回复,可能把“结果没有进入最终回答”误判为后台工具根本没运行。
给团队的升级决定
没有用到 Harness 的 BackgroundTools,这次行为变更就不是你当前故障的直接解释。正在用它的团队,可以先核对锁定版本和 Release,再把现有异常逐个归类。对于希望模型处理的预期失败,按官方迁移建议明确使用 ModelRetry 或 ToolFailed;对于意外异常,让外层应用接管并报警。带写入副作用的流程,必须另外验证取消、重试与回滚语义。
本文依据官方 Release、合并 PR 与能力文档整理,未在本机对指定版本做运行实测。兼容性说明只证明框架行为发生变化,不证明任何业务系统能自动恢复。真正上线前,请用你自己的模型、工具实现和外部服务做故障注入。
来源与说明
Pydantic AI v2.54.0 Release:https://github.com/pydantic/pydantic-ai/releases/tag/v2.54.0
变更 PR #9434(含迁移说明):https://github.com/pydantic/pydantic-ai/pull/9434
BackgroundTools 官方文档:https://github.com/pydantic/pydantic-ai/blob/main/docs/harness/background-tools.md
项目仓库:https://github.com/pydantic/pydantic-ai