Mingyu's Library主页

Agent 调用工具超时后怎么办:成功了、失败了、还是还在跑?

After a Tool Call Times Out: Did It Work, Fail, or Is It Still Running?

2026-11-03 · AI 每日深度学习 · 基于 arXiv 2610.41453 与 Stripe 幂等键文档

2026-11-03 · AI Daily Deep Dive · Based on arXiv 2610.41453 and Stripe's idempotency docs

问题:超时之后,你并不知道发生了什么

The problem: after a timeout, you don't know what happened

agent 调用一个会产生副作用的工具,比如下单、转账、发邮件、建工单。请求发出去了,但等不到结果,超时了。这时候有三种可能:动作其实没执行;动作已经执行成功,只是响应丢了;动作还在路上,过一会儿才会生效。从 agent 手里的信息看,这三种情况长得一模一样。

An agent calls a tool that changes something: place an order, send a payment, send an email, open a ticket. The request goes out, no result comes back, and the call times out. Three things could be true: the action never ran; the action succeeded and only the response was lost; or the action is still in flight and will land later. From the agent's side, all three look the same.

猜错的代价不对称。猜「没成功」就重试,可能扣两次钱;猜「成功了」就继续,可能漏掉一单。更麻烦的是,工作流里别的步骤可能已经做完了,所以「全部回滚重来」也不一定行。

Guessing wrong is lopsided. Assume "it failed" and retry, and you may charge twice. Assume "it worked" and move on, and you may drop an order. It gets worse when other steps in the workflow have already finished, so "roll everything back and start over" is not always possible either.

工具调用超时没收到结果 其实没执行 已经执行成功 还在路上 证据说没跑 → 可以重试(且授权/密钥未过期) 证据说已成 → 别重试,继续记录并往下走 证据不足 → 保持「未知」交给人 (handoff)
图:超时后三种可能与对应的处理
Tool call times outNo result back Never ran Already committed Still pending Evidence: not run → retry(and auth / key not expired) Evidence: done → do not retryrecord it and move on No evidence → stay "unknown"hand off to a human
Figure: three possible states after a timeout and the response to each
下面的内容分三块:先看工程界已有的老办法(幂等键),再看 2026-10-30 的一篇 arXiv 论文怎么处理幂等键解决不了的部分,最后是我的几条实操建议。论文是预印本,结论没经过同行评审,后面会标出它自己写的局限。
This document has three parts: the standard engineering fix (idempotency keys), then an arXiv paper from 2026-10-30 that handles the cases keys cannot, then a few practical suggestions from me. The paper is a preprint and has not been peer reviewed; its own stated limits are listed below.

老办法:幂等键能解决多少

The old fix: how far idempotency keys go

幂等键(idempotency key)的想法很简单:客户端给每次「要做的事」生成一个唯一 ID,随请求一起发。服务端记住这个 ID,下次看到同一个 ID 就不再执行,直接把上次的结果还给你。这样重试就是安全的。Stripe 的文档把它写得很清楚。

The idea behind an idempotency key is simple. The client generates a unique ID for each thing it wants done and sends it with the request. The server remembers the ID; if it sees the same ID again, it does not run the action again and returns the earlier result. Retrying becomes safe. Stripe's docs describe it clearly.

curl https://api.stripe.com/v1/customers \
  -u sk_test_...: \
  -H "Idempotency-Key: KG5LxwFBepaKHyUD" \
  -d description="My First Test Customer"
curl https://api.stripe.com/v1/customers \
  -u sk_test_...: \
  -H "Idempotency-Key: KG5LxwFBepaKHyUD" \
  -d description="My First Test Customer"

按 Stripe 的 API v1 文档:服务端保存的是第一次请求在端点开始执行之后的状态码和响应体,重试同一个 key 会返回保存的响应,连 500 错误也一样返回。key 最长 255 个字符,建议用 V4 UUID。key 至少 24 小时后可能被清掉,清掉后再用同一个 key 会当作新请求。服务端还会比较参数,和原请求不一样就报错。所有 POST 都接受 key;GET 和 DELETE 本来就是幂等的,不用发。

Per Stripe's API v1 docs: the server saves the status code and body of the first request after the endpoint starts executing, and a retry with the same key returns the saved response, including 500 errors. Keys can be up to 255 characters; V4 UUIDs are suggested. Keys may be pruned after at least 24 hours, and reusing a pruned key creates a new request. The server also compares parameters and errors if they differ from the original. All POST requests accept keys; GET and DELETE are idempotent by definition and do not need one.

客户端服务端 POST + Idempotency-Key: K1 执行并保存结果 (状态码+响应体) 响应丢了 / 超时 ✕ 同样请求 + 同一个 K1(重试) 返回上次保存的结果,不会再执行一次
图:幂等键让重试变安全
ClientServer POST + Idempotency-Key: K1 executes, saves status code + body response lost / timeout ✕ same request + same K1 (retry) returns the saved result, no second execution
Figure: an idempotency key makes a retry safe

但幂等键有几个明显的边界,文档自己也写了。第一,它要服务端支持,第三方接口不一定有。第二,有时限,过期后保护就没了。第三,如果请求在开始执行前就因为参数校验失败或并发冲突被拒绝,结果不会被保存,这种可以直接重试。第四,它只告诉你「别重复执行」,不告诉你「现在到底是什么状态」。agent 如果连这个服务端都没有 key 可用,就只能自己判断。这正是论文要处理的部分。

Keys have clear limits, and the docs say so. One: the server has to support them, and third-party APIs often do not. Two: they expire, and after that the protection is gone. Three: if a request is rejected before execution starts (failed validation, or a conflict with a concurrent request), no result is saved, and you can simply retry. Four: a key only tells you "don't run it twice"; it does not tell you what state things are in right now. When an agent has no key to lean on, it has to judge for itself. That is the part the paper tackles.

论文的做法:先收集证据,再决定能不能重试

The paper's approach: gather evidence first, then decide whether to retry

论文是 arXiv 2610.41453,Genliang Zhu 等人,2026 年 10 月 30 日提交,题目是《Evidence-Guided Recovery for AI Agents with Ambiguous Tool Outcomes and Partial Execution》。摘要把问题说成:工具超时后,agent 不知道动作是失败了、已提交了、还是仍在进行,而工作流里别的步骤已经完成了。

The paper is arXiv 2610.41453 by Genliang Zhu et al., submitted 30 October 2026: "Evidence-Guided Recovery for AI Agents with Ambiguous Tool Outcomes and Partial Execution". Its abstract frames the problem this way: after a tool timeout the agent does not know whether the action failed, committed, or is still pending, while other workflow steps have already finished.

它的做法,按摘要的说法,是把恢复建模成「基于证据的任务恢复」,对象是三样东西:已批准的义务(approved obligations,也就是这个任务还欠着哪些该做的事)、服务方的能力(provider capabilities,比如这个接口是否支持幂等键、能不能查询状态),以及与公开证据一致的各种可能状态。

Per the abstract, the method models recovery as evidence-guided task recovery over three things: approved obligations (what the task still owes), provider capabilities (for example, whether the API supports idempotency keys or status lookups), and the states that are consistent with public evidence.

在这之上有两个关键部件。一个是共享的「可行性检查」(admissibility check),专门看密钥是否过期、授权的时间点、步骤之间的依赖、以及残留的副作用。另一个是「终态证书」(terminal certificate),它把「目标真的达成了」和「有公开证据支持的安全收尾」区分开。实现上,是常规的观察条件规划(observation-contingent planning)加上一个单独构建的「效果历史裁决器」(effect-history adjudicator)。

Two parts matter most. One is a shared admissibility check that looks at key expiry, authorization timing, dependencies between steps, and residual effects. The other is a terminal certificate, which separates "the goal was actually met" from "a safe completion supported by public evidence". The implementation pairs standard observation-contingent planning with a separately built effect-history adjudicator.

我觉得最有价值的设计是:「未知」和「交给人」是明确的输出,不是失败。论文摘要写得很直接——Unknown and handoff outcomes stay explicit,保证只在服务方声明的能力范围内成立,不承诺对任意第三方做到「恰好执行一次」。
The design choice I find most useful: "unknown" and "handoff" are explicit outcomes, not failures. The abstract says it directly: unknown and handoff outcomes stay explicit, and guarantees depend on the declared provider capabilities rather than arbitrary third-party exactly-once execution.

结果:数字说明了什么,没说明什么

Results: what the numbers show and what they don't

测试结果
37 个任务的有限研究规划方法和三种主动对照各认证了 28 个完成;另有 4 个「已保存的合成费用单元」需要额外计算。
预注册、按任务保留的对照(58 组配对,19 个任务族)「建议」方式认证 30 个完成,「证据提示」方式 9 个,差 36.2 个百分点(精确族符号翻转检验 p=0.0078)。
效率272 次提案对 399 次。
验证116 条轨迹全部通过独立回放。
TestResult
Finite study, 37 assignmentsPlanning and three active controls each certify 28 completions; four saved synthetic fee units require extra computation.
Preregistered, assignment-held-out comparison (58 paired units, 19 task families)Advice certifies 30 completions vs 9 for evidence prompting: a 36.2-point gap (exact family sign-flip p=0.0078).
Efficiency272 proposals vs 399.
VerificationAll 116 trajectories pass independent replay.

读这些数字要小心。样本很小(几十个任务、两套本地模型),模型和任务都是论文自己设计的,不是真实线上流量。作者在局限里也承认:这个对照比较的是「所评估的建议接口」在统一保护层下的表现,不是搜索对规则式建议,那需要另做匹配对照。我的看法:它证明的是「把证据结构化地喂给规划器,比只在提示词里写一句『请考虑证据』好很多」,而不是证明某个具体系统可以直接上线。

Read the numbers with care. The samples are small (dozens of tasks, two local model bundles), and both models and tasks were designed by the authors, not drawn from live traffic. The authors state a limit themselves: the comparison tests the evaluated advice interface under a common shield, not search versus rule-based advice, which would need a separate matched comparison. My read: it shows that feeding evidence to a planner in a structured way beats just writing "please consider the evidence" in the prompt. It does not show that any particular system is ready for production.

我的实操建议(这一节是我的判断,不是论文原话)

What I would do (this section is my judgment, not the paper's)

先说明:下面几条是我把幂等键文档和论文的思路拼在一起得出的,没有在真实系统里验证过。

A note first: the points below are my own synthesis of the idempotency docs and the paper's ideas. I have not validated them in a real system.

  • 每个会产生副作用的调用都带一个稳定的幂等键,并且在重试时复用同一个。key 要在第一次调用之前就生成并记下来,而不是每次重试重新生成。
  • 超时后先查,不要先重试。有「查询状态」接口就先查;没有,就看有没有别的公开证据(对账单、邮件回执、后台列表)。
  • 把「未知」当成合法状态写进你的 agent 流程。证据不够时,停下来交给人,比猜一个要便宜。
  • 记下授权和密钥的过期时间。Stripe 的 key 可能 24 小时后被清掉,隔夜才重试的任务就不能指望它了。
  • 别指望对第三方接口做到「恰好一次」。论文自己也只在服务方声明的能力内给保证。
  • Give every side-effecting call a stable idempotency key and reuse it on retry. Generate and record the key before the first attempt, not on each retry.
  • After a timeout, check first; do not retry first. If there is a status endpoint, call it. If not, look for other visible evidence (a ledger, a receipt email, a list in the admin console).
  • Make "unknown" a legal state in your agent workflow. When evidence is thin, stopping and handing off is cheaper than guessing.
  • Record when authorizations and keys expire. A Stripe key may be pruned after 24 hours, so a task retried the next morning cannot count on it.
  • Do not expect exactly-once behavior from a third-party API. The paper itself only offers guarantees within declared provider capabilities.

常见坑

Common pitfalls

  • 每次重试都换新 key:等于没用幂等键。
  • 同一个 key 换了参数:Stripe 会比较参数并报错,这是保护,不是 bug。
  • 把校验失败的请求也当成「已执行」:文档说参数校验失败或并发冲突时结果不会保存,这类请求可以直接重试。
  • 把论文的实验数字当成线上指标:样本小、任务自建,别直接引用成「提升 36%」。
  • New key on every retry: that defeats the point of the key.
  • Same key with different parameters: Stripe compares parameters and errors. That is a safeguard, not a bug.
  • Treating a validation failure as "executed": the docs say nothing is saved when validation fails or a concurrent request conflicts, so those can simply be retried.
  • Quoting the paper's numbers as production metrics: the samples are small and the tasks self-built. Do not cite "36% better" as a general claim.

术语表

Glossary

术语一句人话
idempotency key(幂等键)随请求发的唯一 ID,让服务端认出「这是同一次操作的重试」。
obligation(义务)任务里还欠着、必须完成的事。
provider capability(服务方能力)接口自己声明能做到的事,比如支持幂等键、可查询状态。
admissibility check(可行性检查)在重试或跳过之前,检查密钥、授权、依赖是否还成立。
terminal certificate(终态证书)证明任务是「真的达成」还是「有证据支持的安全收尾」的记录。
handoff(交接)证据不够时明确交给人处理。
TermPlain explanation
Idempotency keyA unique ID sent with a request so the server can tell a retry from a new request.
ObligationSomething the task still owes and must finish.
Provider capabilityWhat the API says it can do, such as supporting keys or status lookups.
Admissibility checkA check, before retrying or skipping, that keys, authorization and dependencies still hold.
Terminal certificateA record saying whether the goal was met or the task ended safely with supporting evidence.
HandoffExplicitly passing the case to a person when evidence is not enough.

来源

Sources

说明:论文细节来自 arXiv 摘要页;我尝试读全文 HTML 时被限流,所以论文里更细的定义和示例我没读到。幂等键的细节来自 Stripe 文档,只适用于 Stripe API v1 的描述。

Note: the paper details come from the arXiv abstract page. My attempt to read the full HTML was rate limited, so finer definitions and examples in the paper were not read. The idempotency details come from Stripe's docs and describe Stripe API v1.