工具超时 安全与工程
别名:
超时
工具可能挂起(网络请求没响应),用 `Promise.race` 包一层,超时就按错误协议返回 `{ ok: false, error: 'timeout after 10s' }`——超时本身也是数据,不是崩溃。需要主动中断时接上 `AbortController`,把 `signal` 传给工具。
它是什么
工具可能挂起:一个网络请求没有响应、一个外部进程卡住,await 就永远等下去,整个 Agent 循环被一个工具拖死。超时的做法是用 Promise.race 包一层,让「工具结果」和「一个到点就 reject 的计时器」赛跑:
const result = await Promise.race([
impl(args),
new Promise((_, reject) =>
setTimeout(() => reject(new Error('timeout after 10s')), 10_000)),
]);
超时也是数据
超时本身按统一错误协议处理:返回 { ok: false, error: 'timeout after 10s' } 回填给模型,让模型知道这次尝试超时了、可以换一种方式重试——而不是中断对话。注意 Promise.race 只负责「到点返回」,并不取消底层请求:需要真正中断时接上 AbortController,把 signal 传给工具(fetch 的第二个参数就能接收)。
小结
超时 + 取消是一对:race 解决「不无限等」,signal 解决「真的停」。对 Agent 循环,这两者都是「工具执行是 IO」这条铁律的工程化手段(第 08 章)。