Edit 工具演进史:从 function call 到 schema 约束的活体标本
从 AutoGPT 的文本协议到 Claude Code 2.0 的多文件编辑,按五代编年史拆解 edit 工具 schema 的演化,并提炼出载荷最小化、工具端校验、错误即反馈、合并调用、副作用权限反转、协议随模型迁移六条通用策略。
0. 先给结论(含对假设的修正)
想从 edit 工具的演变里看 function call 精度策略,这个切入点对了一半。edit 工具确实是观察”业界如何在真实产品里驯服 function call”的最佳窗口——它是所有工具里最刁钻的一种:
- 参数是任意代码文本:old/new 会撞上编码(UTF-8、弯引号、NBSP)、空白差异、重复片段;
- 副作用不可逆:写错文件轻则污染仓库,重则破坏环境;
- 失败只能靠错误信息迭代:不像查天气,edit 一次不成通常要靠”错误回填”重试,没有别的路径。
但驱动它演变的变量是四个,而非一个:① 确定性应用、② token/成本、③ 错误恢复、④ 安全授权。“提升 LLM function call 准确度”只是其中一半,另一半是”把决定权从模型手里拿走”。有意思的是:这两半在 schema 上都有可辨识的指纹——下面逐代拆。
一句话主线:edit 工具 schema 的角色,从”描述要执行的内容”演化为”制造确定性 + 生成反馈信号”。
1. 五世代编年史
G0:无 schema 时代(2023 上半年)—— AutoGPT / BabyAGI
编辑 = 一条 shell 指令或一段 Python 代码里 open().write()。没有工具协议,只有 prompt 约定。
教训:这就是 ReAct 式文本协议——零训练成本、模型无关,但格式漂移率高,且没有校验层,写坏了没人知道。
G1:整文件重写(2023 末–2024 初)—— 早期 function calling 应用
工具极简:write_file(path, content),schema 就两个字段。
优点:解析零歧义、模型好懂。代价在 Aider 的 edit-formats 文档里写得很直白:
The “whole” format… can be slow and costly because the LLM has to return the entire file even if just a few lines are edited.
且实际还有三个隐性代价:① 输出 token 多,长 JSON 参数尾部漂移率上升;② 隐藏回归——模型”顺手”改掉没让它改的行;③ 上下文压力(整文件回写把旧内容又灌回窗口)。
教训:schema 极简 ≠ 精度好。参数体量本身就是错误率的来源。
G2:文本 diff 协议(2024)—— Aider + SWE-agent
Aider 刻意不用 function calling 来编辑,让模型以纯文本输出搜索替换块:
mathweb/flask/app.py
<<<<<<< SEARCH
from flask import Flask
=======
import math
from flask import Flask
>>>>>>> REPLACE
它的 edit-formats 文档还记录了 schema 的进一步演化:GPT-4 Turbo 用 SEARCH/REPLACE 会”lazy coding”——省略大段代码、用 # … original code here … 注释糊弄,于是为它专门设计了 udiff(简化 unified diff)格式。这就是那条”格式协议是生态妥协、不是精度最优”——模型 adherence 差到什么格式,协议就迁到什么格式。
SWE-agent 同期把这件事上升为方法论(ACI:Agent-Computer Interface),论文与文档确认了三个设计要点:
- 给模型小而精的动作集(view / search / edit),而不是一个 shell;
edit_file用 search/replace 字符串(不是行号),并附 linter 在编辑后立即运行;- 工具失败返回具体、简洁的结构化反馈——“guardrails to prevent common mistakes”。
它的结论之一后来常被引用:ACI(工具面)设计对 SWE-bench 成绩的影响,不亚于换模型。
教训:编辑协议从”输出全文”收缩为”输出差异”——载荷最小化成为精度策略;校验与反馈(linter、错误信息)开始成为工具的一部分。
G3:search-replace 原生工具(2024 末–2025 中)—— Claude Code Edit / Codex CLI
模型 adherence 上来了,各家迁回原生 tool call,schema 定型为:
// Claude Code Edit
{ "file_path": "...", "old_string": "...", "new_string": "...", "replace_all": false }
这代 schema 里有几个极其刻意的约束(Claude Code 文档 + CHANGELOG 均可证):
old_string必须唯一,否则工具返回Error: old_string is not unique——不是在 prompt 里”请求”模型写全上下文,而是工具层强制:不唯一就拒绝并给出可操作的错误信息,逼模型把锚点加长。- 精确匹配 + indentation 严格一致(tab/space 打错就 “String not found”)——应用器是确定性的,任何模糊性都不留给”猜”。
- ASCII-only 限制——规避编码错位;CHANGELOG 里还躺着大量编码 bug 修复(弯引号被静默改写
#26141、escaped\uXXXX误判等),说明这正是”token ≠ 字符”问题的编辑版。 - read-before-edit 规则:只能编辑本会话读过的文件;CHANGELOG 甚至记录了”新模型可以覆盖未读文件、旧模型仍要求先读”的按模型能力分级放开——约束随模型能力动态调节。
- 后续版本又加了:“Edit tool now uses shorter
old_stringanchors, reducing output tokens”(CHANGELOG 里明确写着的优化)——schema 的 token 效率被当成一等优化项,说明厂商把”参数长度 × 错误率 × 成本”当成了可调参数。
Codex CLI 走的是另一条 G3 支线:早期把编辑做成 apply_patch(模型输出 unified diff 文本)+ shell,patch 应用失败时把 git apply 的错误回填给模型重试——校验器同样在工具端,只不过格式是 diff 而非 search-replace。
教训:这一代完成了核心飞跃——“校验 + 错误生成”从模型端迁移到工具端。模型负责”生成”old/new,工具负责”是否成立”,不成立时的错误信息本身就是最好的下一个提示。
G4:多文件 · 异步 · 门禁(2025–)—— 把决定权从模型手里拿走
- Claude Code 2.0(2025-08):
/rewind回滚撤销代码改动、checkpoints;随后加入一次调用编辑多个文件的能力(SDK 文档称 MultiEdit)。此前每个文件一次调用,一次重构要串十几个 tool call。 - Gemini CLI:
replace工具提议改动,write_file建新文件,但应用前必须向用户展示 unified diff、按 y 确认——执行的最后一步不归模型。 - Amazon Q Developer CLI:早期设计把编辑做成计划/投票/应用的异步授权流程(模型提交 EditPlan,CLI 对
allow_edits结果投 allow/deny/partial,然后才给apply_edit动作);当前文档收敛为fs_read/fs_write+allowedPaths/deniedPaths(glob)白黑名单,且”写”默认必须弹授权——注意这两份built-in-tools.md里规则是”Deny rules are evaluated before allow rules”的确定性优先级语义。 - GitHub Copilot coding agent:改动先进 proposed changes 工作区,应用后仍需人工 review 的 diff;
fs_write与execute_bash、use_aws一起被 Sessions Agent 的异步授权机制罩住。
教训:这一代不再优化”模型怎么改得更准”,而是承认模型会犯错,把不可逆副作用的闸门交给运行时与用户。失败成本结构变了——坏改动被拦在应用前,而不是事后靠 git 恢复。
2. 从 schema 变化中提取的六条通用策略
| # | 策略 | edit 工具里的体现 | 对 function call 的通用映射 |
|---|---|---|---|
| 1 | 载荷最小化 | 整文件 → search-replace → “更短 old_string anchors” | 结构参数越短,漂移率越低、成本越低;约束解码只能保语法,保不了”参数该写多长” |
| 2 | 校验器放工具端 | unique 检查、exact match、ASCII-only、read-before-edit | 对应”解析校验层”与”validator 层”——模型不该对自己的输出做裁判 |
| 3 | 失败信息即反馈 | “not unique / not found” → 加上下文重试;SWE-agent 结构化错误 + linter;apply_patch 失败回填 git 错误 | 呼应 tool_result 错误回填循环;误差沿轨迹累积,反馈质量 = 精度放大器(AlphaCodium 称之为 “error messages as prompts”) |
| 4 | 合并调用、减少轮次 | G4 一次调用多文件(MultiEdit / edits[]) | 整条轨迹成功率 = Π 单步成功率;少一次往返 = 少一次污染上下文的机会 |
| 5 | 副作用权限反转 | plan/vote/apply、应用前 diff 确认、allowedPaths 白黑名单 | 破坏性工具沙箱化/授权化;不提升单次精度,但把失败从”灾难”降为”被拦下” |
| 6 | 协议随模型 adherence 迁移 | Aider 文本 diff → 原生 tool call | 文本协议是生态妥协,模型够强就迁原生 |
其中第 2 条和第 3 条特别值得和”约束解码”那一层互文:
- 约束解码的”结构收紧、内容放开”,在 edit schema 上的同构是:
old_string(锚点/结构)被收得非常紧(必须唯一、必须精确匹配),而new_string(内容)完全放开——两个领域用的是同一条原则,只是方向相反:前者约束输出,后者约束输入参数。 - “唯一性校验”本质上是一个不要模型动脑的廉价 validator:它把”这段代码在文件里是否歧义”这件模型大概率判不准的事,变成一个确定性布尔判断,歧义时返回的错误句就是下一轮最好的 few-shot。
3. 总表
| 世代 | 代表 | 形态 | Schema/协议要点 | 主导策略 |
|---|---|---|---|---|
| G0 | AutoGPT/BabyAGI | shell + prompt 约定 | 无 | 文本协议,易漂移 |
| G1 | 早期 function-calling 应用 | write_file(path, content) | 两字段 | 载荷爆炸 → 隐藏回归 → 长参数漂移 |
| G2 | Aider / SWE-agent | 文本 SEARCH/REPLACE / udiff;edit_file | 纯文本协议 + linter + 结构化错误 | 载荷最小化;ACI 方法论 |
| G3 | Claude Code / Codex CLI | 原生 tool call:search-replace / apply_patch | unique 强制、exact match、ASCII、read-before-edit | 工具端确定性校验 + 错误回填 |
| G4 | Claude Code 2.0 / Gemini / Q / Copilot | 多文件、raw diff、异步门禁 | 一次多改;应用前 diff 确认;allowedPaths 白黑名单 | 减少轮次;副作用权限反转 |
4. 回到现在:实际在用的这个 edit 工具
本次调查所参照的 edit 工具是这条演进线的”当代节点”:{path, edits: [{oldText, newText}]}——一次调用多个不重叠的精确替换(G4 合并调用)+ oldText 必须在原文中唯一匹配(G3 的确定性校验)+ 每一处修改都是最小局部 diff(G1→G2 的载荷教训)。
把视角拉回 function call 的主题,edit 工具史上完整重演了四个层次:
- 语法保证 → G1/G2 的”格式协议”,保证”输出能被解析”;
- 语义/应用保证(validator 层)→ G3 的”工具端唯一性校验”,保证”参数确实指向目标”;
- 反馈迭代(tool_result 回填)→ G2/G3 的”错误信息即下一轮 prompt”,保证”一次不成能收敛”;
- 新加的第四层:运行时门禁(G4),保证”错了也不至于造成不可逆伤害”。
所以”schema 约束提升 function call 准确度”可以浓缩成一句:好的工具 schema 不追求”让模型一次说对”,而是追求”模型说错时,工具能确定性地发现、并给出能让它自己纠正的错误信息”。 edit 工具把这套哲学用到了最极端的参数形态上,因此成了最好的教材。
主要一手来源
Aider edit-formats 文档(whole/diff/udiff 及 GPT-4 Turbo elision)· SWE-agent ACI 文档与论文 · Claude Code CHANGELOG(read-before-edit、shorter anchors、编码修复)· Gemini CLI file-management 文档(replace + 应用前 diff 确认)· Amazon Q Developer CLI built-in-tools.md(fs_read/fs_write + allowedPaths/deniedPaths)· Anthropic《Writing effective tools for AI agents》。