Appearance
Tool 失败后能不能重试:Retry Eligibility 与 Idempotency Contract
Timeout 不等于“这个 Tool 没执行”
假设 Harness 调用:
text
create_ticket(operation_id=op-42)
→ remote system 已创建 ticket
→ response 在网络中丢失
→ Runtime 只看到 TIMEOUT如果 Tool contract 只写了 retry=true,Runtime 直接再调用一次就可能创建第二张工单。真正需要知道的是:这是什么副作用、同一 logical operation 能否幂等重放、结果未知时能否查询远端状态。
Retry Eligibility:Tool 只提供事实,Reliability 层做决定
通用 Retry/Backoff/Jitter policy 属于 Module 11。Tool 层至少应暴露类似:
text
side_effect = NONE | REVERSIBLE | EXTERNAL
retryability = SAFE | CONDITIONAL | NEVER
supports_idempotency_key = true/false
supports_reconciliation = true/falseRuntime 再结合 error class、remaining deadline、attempt 和 retry budget 决定 retry / reconcile / fail。不要让每个 Tool 在内部各写一套无限重试循环。
Idempotency Contract:同一次业务操作跨 Attempt 保持同一个身份
attempt_id 标识第几次执行尝试;operation_id / idempotency_key 标识“是不是同一件业务动作”。两者不能混为一谈:
text
operation_id = op-42
attempt-1 → timeout
attempt-2 → retry / reconcileRetry 时 operation identity 应保持稳定,否则外部系统会把第二次调用当成新业务动作。
对于不能提供幂等能力的高风险 Tool,uncertain outcome 必须显式返回给 Runtime,例如 UNKNOWN_EXTERNAL_STATE,先 reconciliation,而不是把 timeout 偷换成普通失败。
🔍 源码对照:Side Effect identity 必须跨审批/执行可关联
完整源码与通用分析见 11-05 HITL / Approval / Resume。这里不重复代码;这里关注 operation identity:approval 必须绑定到具体 side-effect generation / operation,retry 不能悄悄生成新的业务身份。
源码说明
MCP bridge 会向外投影 idempotentHint,而 auto-review gate 还单独维护 side-effect start 的 identity generation。把这两个点放在一起,正好说明“Tool 声称 idempotent”和“Runtime 知道某次副作用是否已经开始/完成”不是一回事。Retry eligibility 是 contract + execution fact 的联合判断。
工程边界
案例里的 idempotentHint = readOnly 只是该 bridge 的保守映射,不能替代业务级 idempotency key、dedup record 或远端 operation status。
Shadow Harness 对照
- ToolSpec 标记 retry class / side-effect class;ExecutionRecord 记录 attempt 与 external operation key。
- timeout-unknown outcome 必须进入 reconciliation,而不是默认 retry。
验证
模拟 send_email 远端成功但本地超时,分别测试没有 idempotency key、带 key、可查询 operation status 三种恢复策略。
Failure Modes
Tool 元数据没有声明副作用语义
后果: 查询 Tool 与 send_email/create_ticket 被同一种 retry policy 处理。
处理: Registry 暴露 side-effect、retryability、idempotency 和 reconciliation capability,由 Reliability policy 消费。
每次 Attempt 重新生成幂等键
后果: Retry 被远端识别为新的业务操作。
处理: idempotency key 绑定 logical operation;attempt id 单独变化。
如何验证
| 场景 | 必须成立 |
|---|---|
| Read-only Tool transport error | 满足预算时可直接 retry |
| Side-effect Tool timeout,远端状态未知 | 先进入 reconciliation,不盲目重复执行 |
| 同一 ToolCall 两个 attempts | operation/idempotency key 不变,attempt_id 改变 |
关联源码
自测
- HTTP timeout 后远端 Tool 可能已经成功写入。为什么这个 outcome unknown 不能像 read-only 查询一样直接 retry?
- 如果 Tool metadata 没有 side-effect/idempotency 声明,Runtime 凭什么判断 retry eligibility?应该把什么信息补进 contract?