← 全部文章
智能体周刊2026 年第 38 期

2026-W38 周刊:工具的幂等性谁来保证

本周智能体生态聚焦:幂等这件事,别指望模型自己记住。重试是框架给的,超时是网络给的,同一轮里调两次是采样给的——这三样都不在 prompt 的射程内。我的结论很直:写操作的幂等键由框架生成、透传,工具侧去重。读操作别折腾,缓存够了。 模型重试不是意外,是默认行为 [Chronicle 那篇](https://arxiv.org/abs/2609.20625v1)讲得挺实在:agent 的失败难复现,因为推理本身不是 bitwise 可复现的,工具读的是会变的状态,多步轨迹重跑

YGG 智能体周刊6 分钟阅读#weekly#agent#engineering#architecture#2026

幂等这件事,别指望模型自己记住。重试是框架给的,超时是网络给的,同一轮里调两次是采样给的——这三样都不在 prompt 的射程内。我的结论很直:写操作的幂等键由框架生成、透传,工具侧去重。读操作别折腾,缓存够了。

模型重试不是意外,是默认行为

Chronicle 那篇讲得挺实在:agent 的失败难复现,因为推理本身不是 bitwise 可复现的,工具读的是会变的状态,多步轨迹重跑基本不重样。它想解决的是回归测试,但反过来读一遍更刺人——连"把刚才那次重放一遍"都做不到,还想靠 prompt 里写一句"不要重复调用"来保证唯一性?

Overclaiming 那篇更扎心。agent 会高估自己的完成度,而最终那段回复往往是用户唯一能看到的账本。工具侧没有幂等的话,账本和实际副作用直接对不上——它说退款成功了,其实发了两次;它说建了一个工单,其实建了三个。用户信任的是那段自然语言,出问题的是数据库。

这两个问题其实是一件事的两面:模型看不见自己之外发生了什么,而副作用发生在模型之外。

幂等键该由框架生成,不该由模型写

具体做法我说细一点。框架在派发 tool call 的那一刻生成 key,拼法要确定性——(session_id, step_id, tool_name, call_index) 之类,哈希成一个字符串。这里有个容易踩的坑:别用 UUID。UUID 在重试时是新值,等于没做幂等。要的是同一次意图在重试后算出同一个 key。

透传方式随你,塞进工具参数、放 header、放 trace context 都行。工具侧拿到之后 INSERT ... ON CONFLICT DO NOTHING,或者 Redis 的 SETNX 加个 TTL,然后返回一个 duplicate: true 之类的标志。这样 agent 知道"上一次其实成功了",可以接着往下走,而不是傻等超时再重来。

为什么不能让模型自己写这个 key?因为重试发生在它的上下文之外。它在 token 流里吐出一个 key,重试时重新采样,大概率是另一个字符串。这不是模型不听话,是它压根没有那个信息。让它猜一件它观测不到的事,本来就不合理。

HarnessTax那篇 harness 组件研究支持这个方向:execution loop 固定,其余组件的差异对长任务表现影响很大。幂等透传属于 harness 的一部分,不是 prompt 的一部分。Claude Code 现在没有 CLAUDE.md 时会去读 AGENTS.md,也是同一个趋势——大家把约定往 harness 层收。

读操作强上幂等是浪费

反过来讲一句:给读操作套幂等键,我不认。读没有副作用,重复调最多浪费时间和 token。你要为它维护 key 存储、TTL、一致性,收益接近零。这种问题缓存层解决就够——按参数哈希存一下,TTL 给短一点,成本远低于搭一套幂等基础设施。

但有个边界得说清楚:名字带 get 不代表真没副作用。ZCode 静默上传 Git history就是个现成例子,工具实际干了什么,和它的命名、文档可能完全不是一回事。所以分类不能靠名字,要靠工具自己声明的副作用等级,声明和实现对不上就是 bug,测试里该有一条盯着。

一句话收

框架生成透传,工具校验去重,模型不负责。prompt 里那句"不要重复调用"是安慰剂,它拦不住框架层的 retry,也拦不住采样。

不确定的地方也有:同一轮里并行发多个 tool call,key 怎么排现在没有共识,我先用 call_index 顶着。也许过阵子回头看,这套显式透传会被 trace_id 隐式传递替掉。按我现在看,显式还是比隐式靠谱——出问题时能一眼看出是哪个 key 撞了。

延伸阅读

编辑说明

本文由 YGG 臻星科技团队整理,聚合 ArXiv、HackerNews 与公开厂商博客,人工审稿。