工具结果要认得流已关闭
Agent 里的工具调用不是“发出去就一定能收回来”的同步函数,而是挂在一次模型响应流上的子任务;一旦模型 stream 已经因为 provider error、schema error、用户取消或网络断开而关闭,迟到的工具结果就不能再塞回原来的 result stream,否则会把一次失败响应伪装成半成功状态,甚至污染下一次恢复。
Vercel AI SDK 7 月 14 日在 ai@6.0.226 / ai@5.0.213 修了一个很典型的边界:model stream error 关闭 result stream 后,pending tool executions 仍可能继续完成并 enqueue results。这个问题看起来只是 SDK 内部 race condition,但对 Agent Engineer 更重要的信号是:tool execution 的生命周期必须绑定到 run/response 的可接收窗口,而不只是绑定到工具进程本身。
工程上可以把每次 tool call 建成带 epoch 的状态机:created -> dispatched -> accepted_by_stream -> committed,其中 committed 前必须检查 response/run 仍然 open、call_id 仍属于当前 transcript projection、abort reason 不是 terminal。工具本身可以继续做清理或落审计日志,但它的输出不应再进入已关闭的模型消息流;否则 replay、UI、计费、审批恢复和子 Agent 汇总都会看到一份“不该存在的结果”。
常见误区是只在 stream pump 外层 catch error,然后假设下游 await 的工具自然会被取消。现实里很多工具是独立 promise、队列任务、浏览器会话或远程 MCP 调用,取消传播不完整时尤其容易出现晚到结果。OPC 类平台如果要承接长任务和多工具并发,应该明确区分:执行是否还在跑、结果是否可投递、结果是否已进入权威 transcript。
你现在的 Agent runtime 里,有没有一个地方能明确回答:某个工具结果晚到时,它应该被提交、丢弃、补偿,还是只写审计?