问题
Armin Ronacher(Flask 作者,现做 AI 编程工具 Pi)发现一个反直觉的现象:更新的 Claude 模型在调用第三方工具时,反而比旧模型更容易产生格式错误的参数。
具体表现:Pi 的编辑工具接受一个嵌套的 edits[] 数组,每项含 oldText / newText。Opus 4.8 和 Sonnet 5 在调用时会凭空发明额外字段:
{
"oldText": "...", // 内容完全正确
"newText": "...", // 内容完全正确
"requireUnique": true // 凭空发明的字段
}
Armin 在多次试验中看到了一整园"发明字段":type、id、kind、unique、requireUnique、matchCase、in_file、forceMatchCount、children、notes、cost、oldText2、newText2……
最烦人的是:实际的 oldText / newText 内容是字节级正确的。模型做对了编辑,只是在对象末尾加了垃圾字段,导致 Pi 按 schema 校验失败、要求重试。
而旧模型(Opus 4.5 及更早)完全没有这个问题。
为什么会这样:RL 训练的隐藏代价
Armin 的核心假说:这不是随机退化,而是训练产物。
Claude Code 的编辑工具是"平坦"的
Claude Code 自己的编辑工具 schema 接近 file_path + old_string + new_string + 可选 replace_all flag——不是 Pi 那种嵌套 edits[] 结构。
Claude Code 的客户端极其"宽容"
Armin 反编译了 Claude Code 的代码,发现它有一整套容错机制:
- 检查模型输出中泄露的
<invoke标记 - Unicode 转义修复(修 broken
\uXXXX) - 参数别名(
old_str/old_string/path/file_path互通) - 静默过滤未知 key
- 不使用
strict模式(因为 Anthropic 对 strict 模式下的 schema 复杂度有限制)
这意味着什么
如果强化学习在这样的 harness(或其模拟)里进行,略微畸形的工具调用仍能完成任务并获得奖励。harness 完全吸收了错误,几乎没有梯度信号去惩罚"多发明一个字段"。
更糟的是:模型可能强力适配了 Claude Code 的编辑工具形状。一个语义相同但 schema 不同的第三方工具会变成off-distribution。模型越强(prior 越强),反而越难适配你的工具。
Armin 的担忧:"替代工具 schema 可能不只是不熟悉。它们可能被一个优化特定、宽容工具生态的 post-training 隐式惩罚了。而且这个生态是不公开的。"
上下文依赖与缓解措施
这个问题高度依赖上下文:
- 全新单轮 prompt("编辑这个文件")无法复现
- 有完整 Agent 历史(读过文件、诊断过问题、再组合多行编辑)才能触发
- 某用户的会话中,Opus 4.8 失败率约 20%
- 从历史中剥离 thinking blocks → 失败率减半
- 开启 strict tool invocation → 在 Armin 的测试中完全消除
这对 Agent 开发者意味着什么
| 维度 | 判断 |
|---|---|
| 工具 schema 不是中立的 | 不要假设 schema 是抽象契约、模型是通用推理器。某些工具形状更接近模型的 post-training 分布,某些更远 |
| 嵌套参数比平坦参数危险 | 顶层属性在 ANTML 里内联处理;嵌套对象数组需要模型在长多行字符串后写转义 JSON——错误发生在最高熵点(闭合 } 还是继续 ,"...") |
| strict 模式是当前解法 | Anthropic 的 strict 模式(服务端拒绝采样 schema 不允许的 key)能解决,但对 schema 复杂度有限制 |
| 你的 harness 可能要适配 Claude Code 的形状 | 如果这种趋势持续,第三方编程工具可能不得不实现和 Claude Code 相似的编辑工具形状才能获得最佳性能 |
对比:OpenAI 的 harmony 格式
OpenAI 的模型(含开源的 gpt-oss)显式训练在 harmony 响应格式上。工具调用可以这样表达:
<|start|>assistant<|channel|>commentary to=functions.get_weather
<|constrain|>json<|message|>{"location":"San Francisco"}<|call|>
<|constrain|>json 标记让推理栈可以在这个边界切换到 JSON 约束采样。Armin 测试了现有 Codex 模型(除 5.6 外),没有发现这种回归。
行动建议
| 角色 | 建议 |
|---|---|
| 做 Agent harness / 编程工具 | 如果用 Anthropic 模型且有嵌套参数工具,开启 strict 模式。这是目前最可靠的解法 |
| 设计工具 schema | 尽量用平坦的顶层属性而非深层嵌套。嵌套越深,模型在高熵点的采样错误率越高 |
| 追踪模型回归 | 新模型在你的工具上不一定更好。建立自己的工具调用成功率评估,不要假设"更强模型 = 更好工具调用" |
| 关注 Claude Code 的影响 | 随着越来越多 post-training 在单一主导 harness 内进行,其他 harness 将被迫继承它的怪癖。这是 Tool Use 的基础机制层面的趋势 |
一句话结论:模型变强了,但它在强化学习中被训练成"最擅长调用 Claude Code 那套宽容工具"。你的工具如果不是那个形状,可能要为模型的强 prior 付出代价。这不是 bug,是 RL 的隐藏副作用——对所有自建编程 Agent harness的人都是警告。