-
Notifications
You must be signed in to change notification settings - Fork 2
Tool Idempotency and Recovery
AceGuru-mjh edited this page Oct 1, 2026
·
4 revisions
📑 本页目录
长任务被打断后,"这个操作到底做没做"必须能回答。T76 为此建立了
ToolExecutionPolicy(80 个工具的幂等分类)+RecoveryPolicy(恢复决策矩阵)。 与 任务运行时 的 journal 配合使用。
| 分类 | 语义 | 恢复动作 |
|---|---|---|
READ_ONLY |
重放无副作用 | RETRY(放心重放) |
IDEMPOTENT_WRITE |
重放结果等价 | RETRY |
NON_IDEMPOTENT |
重放会产生重复副作用 | VERIFY(先验证再决定) |
UNKNOWN |
行为不可判定 | VERIFY |
| 分类 | 代表工具 |
|---|---|
READ_ONLY |
read_file list_files web_search ui_dump logcat browser_snapshot
|
IDEMPOTENT_WRITE |
write_file(整覆盖)app_install create_directory browser_navigate github_write_file
|
NON_IDEMPOTENT |
app_uninstall ui_tap input_text browser_click terminal_send alarm
|
UNKNOWN |
shell_execute http_request mcp_call terminal_exec code_runner
|
未列入表的工具默认 UNKNOWN(保守侧)。
Note
这套分类与 工具系统 v3 的
retrySafe = readOnly || idempotent 是同一口径的两处表达:
执行硬化层用它决定是否重试,任务运行时用它决定恢复动作。
| journal 中记录的状态 | 决策 | 理由 |
|---|---|---|
SUCCEEDED |
SKIP | 绝不重复已成功落盘的操作(幂等性验收核心) |
FAILED |
SKIP | 失败不会因重放变成功,交给上层重新决策 |
NOT_STARTED |
SKIP | 尚未开始,正常流程会重新发起 |
UNKNOWN(中断时刻) |
按分类裁决(下表) | 真正需要人为语义的地方 |
UNKNOWN 的裁决:
ask_user 族 → RETRY (问人没有副作用)
READ_ONLY → RETRY
IDEMPOTENT_WRITE → RETRY
NON_IDEMPOTENT → VERIFY
UNKNOWN → VERIFY
VERIFY 的语义:不重放,而是向模型注入提示 ——
操作 X 可能已在中断前执行,请先用只读工具验证其实际效果,再决定是否重做。
flowchart LR
A["TOOL_CALL_STARTED"] --> B["journal 追加 RUNNING<br/>(含幂等分类快照)"]
B --> C{"进程死亡?"}
C -->|否| D["TOOL_CALL_FINISHED → SUCCEEDED / FAILED"]
C -->|是| E["journal 停留在 RUNNING<br/>恢复时判为 UNKNOWN"]
D --> F["decideForOperation → SKIP"]
E --> G["decideForOperation → RETRY / VERIFY"]
一个很容易踩的坑:恢复时把已成功的写操作再跑一遍。
-
write_file整覆盖 → 重放等价,问题不大; -
app_install→ 重复安装,浪费流量与时间; -
terminal_send、ui_tap、browser_click→ 语义完全不同(再点一次按钮可能提交两次表单)。
所以 journal 里 SUCCEEDED 一律 SKIP,这是"幂等性验收"的核心断言,有专项测试。
-
MCP 生态总览
新 - (沙箱 MCP · 官方 Hub · 逆向 Host · 门控语义)
- 终端运行时
- 终端 API 契约
- SDK 边界
- Termux 能力矩阵
- Ubuntu rootfs 供给
- Ubuntu 生命周期
- PRoot 二进制溯源
- VT100/ANSI 模拟器
- 终端性能
- 终端迁移
- 原生层 C++/JNI