Code Agent 无法正确调用 apply_patch,表面上像模型能力问题,实际常常是系统提示词与运行时工具契约不一致。模型按照提示选择了一个被强调的编辑方式,但宿主框架对已有文件提供的是另一套 edit 工作流;失败后错误反馈又不充分,于是模型反复提交无法匹配的补丁,看起来像长时间“卡住”。
oh-my-openagent issue 3041 报告,在 OpenCode 1.3.13 与插件 3.14.0 环境中,Hephaestus 或映射到 GPT-5.4 mini 的子代理处理已有文件时,可能长时间无法完成编辑。最初一次错误是 apply_patch 无法找到预期行,后续多次调用只显示工具执行中止,整个会话可能持续约五十分钟。
同一报告指出,另一类 Agent 使用暴露 edit 和 write 的不同系统提示词时表现正常。问题模型倾向于先尝试写文件,而文件已经存在时又触发保护,经过很久才退回 edit。这个对比把排查方向从“模型不会写代码”转向了提示词、工具清单和文件状态规则之间的冲突。
该 issue 后来由 PR 3045 关闭。修复并未重写 apply_patch 算法,而是调整 GPT-5.4 junior 的提示:已有文件优先使用 edit,write 只用于创建新文件,同时保留禁止使用 cat 或 echo 写文件等约束。这说明根因主要位于工具选择指导,而不是模型 API 本身。
大模型不会天然知道宿主框架中 apply_patch、edit 和 write 的精确差别。它只能根据工具 schema、描述、系统提示和历史示例推断。不同产品即使使用相同工具名,也可能采用不同参数格式、匹配规则和文件保护策略。
apply_patch 通常要求补丁上下文与当前文件精确对应;edit 可能接受旧字符串与新字符串,或使用框架自己的定位方式;write 往往覆盖或新建完整文件。若系统提示说“手工编辑始终使用 apply_patch”,而运行时实际期待已有文件走 edit,模型遵循提示反而会进入错误路径。
因此,“某 GPT 模型不能调用 apply_patch”不是足够精确的诊断。需要回答它收到什么工具描述、生成了什么参数、工具端如何解析、失败后返回了什么,以及框架是否又用其他规则阻止替代方案。
不同模型对指令优先级、工具示例和失败恢复的敏感度不同。有的模型会严格遵循“始终使用”这类强约束,即使连续失败也不愿换工具;有的模型会根据错误自行回退到 edit。后者看似更健壮,却可能违反宿主的安全约束。
小型或快速模型通常更依赖清晰的局部规则。提示中同时出现“已有文件不能 write”“始终 apply_patch”“优先 edit”等近义但冲突的指令时,它们更容易选错。长上下文中,工具说明分散在多个系统片段,也可能导致后出现的规则覆盖前面的规则。
这不意味着某个模型系列固定不支持 patch。只要工具契约、提示和训练时熟悉的调用格式对齐,同一模型可以稳定使用;反之,再强的模型也可能在互相矛盾的约束中反复试错。
首次失败通常来自搜索上下文过时、缩进差异或目标行已经被修改。若错误只返回“Failed to find expected lines”,模型缺少实际文件附近内容,只能猜测新补丁。连续猜测会产生相同失败。
框架若在工具调用外层还有自动重试、子代理重启或超时恢复,单次失败可能被放大。日志中后续只出现“Tool execution aborted”,模型看不到可操作原因,又会继续选择系统提示要求的工具。最终表现就是会话有输出活动,却没有文件变更。
当 write 对已有文件设有保护,而 edit 又被提示词降为最后手段时,所有退出路径都被阻塞。真正修复点应是消除工具选择冲突,并提供足够的失败上下文,而不是简单增加超时时间。
第一步是让三类操作边界互斥。已有文件的局部修改使用 edit;新文件创建使用 write;只有当运行时确实注册并支持补丁语法时,才向模型推荐 apply_patch。不要用“始终”描述存在例外的规则。
第二步是让工具 schema 与提示使用相同术语。若工具名叫 edit,示例和错误信息都应叫 edit,不能在提示中使用抽象的“patch”让模型猜测映射。每个工具都应说明适用文件状态、是否允许多处匹配、是否需要精确上下文和失败后的下一步。
第三步是在执行前验证参数。工具可以检查路径、文件存在状态、必填字段和补丁格式,并返回稳定错误代码。模型收到 FILE_ALREADY_EXISTS 时应切换 edit;收到 SEARCH_TEXT_NOT_FOUND 时应读取目标区域或依据候选内容修正。
有效提示应短而确定,例如:“修改现有文件使用 edit;仅在创建新文件时使用 write;不要通过 shell 重定向写文件。”如果 apply_patch 是共享能力但某类子代理不适合优先使用,可说明只有在工具清单实际提供且补丁上下文已核实时才使用。
提示中不应同时保留旧规则。PR 3045 增加了回归测试,断言新指导存在,并确保不再出现“手工代码编辑始终使用 apply_patch”一类旧文本。这类负向断言很重要,因为多个提示模板拼接时,删除一处不代表最终消息中完全消失。
还应测试最终渲染后的系统提示,而不只测试模板源码。模型实际收到的内容可能经过角色、模型族和子代理配置层层合并,冲突往往在组合后才出现。
apply_patch 匹配失败时,应返回文件路径、失败的搜索块、最接近的真实内容、行号和文件当前版本。这样模型能区分空格差异、内容漂移和选错文件。若没有相似候选,应明确要求重新读取,而不是自动模糊应用。
工具执行中止也要保留底层原因。超时、用户取消、进程异常和前置校验失败不能统一成一个“aborted”。稳定的错误分类既方便模型恢复,也便于维护者统计是哪一层造成故障。
每次重试需要硬性预算和停滞检测。连续出现相同错误、相同补丁或文件没有变化时,应停止自动循环并报告诊断,避免几十分钟的无效调用。
关联 PR 在更新提示后运行了目标测试,记录为 48 项通过,同时完成类型检查和差异检查;合并页面显示 7 项检查通过。这些证据说明修复经过了项目测试,但用户仍应确认自己安装的版本是否包含 2026 年 5 月 20 日合并的提交。
先保存完整工具调用和原始错误,不要只截取最终超时。其次打印模型实际收到的工具清单与最终系统提示,搜索 apply_patch、edit、write、existing file 等关键规则。然后对比正常模型和异常模型的提示差异。
接着用最小文件复现:一个精确匹配的局部替换、一个故意失配的替换和一个新文件创建。若精确替换成功,说明工具本身可用;若模型仍选错工具,则问题在路由或提示。最后再检查版本、插件缓存和模型映射是否与预期一致。
部分 GPT 模型在该项目中无法正确使用 apply_patch,根因不是它们普遍缺少文件编辑能力,而是模型专用提示要求优先使用 apply_patch,与现有文件应走 edit、write 仅创建新文件的运行时契约冲突。匹配失败后的泛化错误和重复重试进一步放大了问题。
可靠修复需要统一工具边界、删除冲突提示、增加最终提示回归测试,并让失败响应携带可操作上下文。关联修复已经合并,因此遇到同类现象时应先检查所用版本与模型映射,再依据实际工具契约排查,不能把历史 issue 直接当作当前模型能力结论。
MCP Server 的工具和资源发生变化时,客户端如何重新发现能力?
DeepSeek Harness 系列(07):Capability Seam 如何通过配置切换能力
MCP Server 能否按需改变工具列表并通过 listChanged 控制工具膨胀?
MCP Server 动态增删工具时如何让客户端更新可用能力?
.NET中的MassTransit分布式应用框架详解
ASP.NETIdentity的基本用法