DAY 19 / PHASE 2 · 应用与系统

Coding Agents

Edit Format · Plan Mode · 自主度光谱 · Closing the Loop

2026-06-02 · BigCat

同一个模型,装进 Aider / Cursor / Claude Code 是三种生物——差别在 harness,不在权重。

// WHY THIS MATTERS

你每天用 Cursor 的 tab、Claude Code 的 agentic loop、偶尔回 Aider 跑批量重构——但很少有人能说清这三者架构上到底差在哪。它们底层都是 Claude / GPT,差距却大到判若两个产品。原因是 coding agent 的真正难点不在「让模型写出对的代码」,而在两件被低估的工程:怎么把模型意图可靠地落到文件系统(edit format),以及怎么控制它的自主度(plan / pair / full-auto)。这一期不教你用某个工具,而是拆开三大 coding harness 的设计分野:edit format 的 token-成功率权衡、plan mode 为什么是工程必需而非 UX 装饰、自主度光谱怎么选档、以及为什么 SWE-bench 高分 agent 在你的真实仓库里可能更难用。读完你能用「剥皮」的眼光看任何 coding 产品。

// 01

三大 Coding Harness 的架构分野

论断:Aider / Cursor / Claude Code 的差异不在模型,在「谁掌握控制流」和「edit 怎么落地」两个轴。

背景与原理

把三者放进同一张坐标系,分野立刻清楚。横轴是自主度(谁决定下一步:你 or 模型),纵轴是 edit 落地方式(模型怎么改文件):

关键 insight:这三者不是「谁更强」,是三个自主度档位。Aider 适合你心里有明确改动的批量执行;Cursor 适合编辑器内的高频小迭代;Claude Code 适合「我不确定怎么改、你去探索」的开放任务。选错档比选错模型代价大。

低自主度 ◀───────────── 控制流归属 ─────────────▶ 高自主度 (你掌控) (模型掌控) Aider ────────────── Cursor ────────────── Claude Code /add 显式选文件 tab + composer 自己 Grep/Read 探索 diff 块 + 自动 commit fast-apply 模型落地 Edit 工具 string replace 你驱动每一步 编辑器内高频小迭代 agentic loop 自主多步 ─────────────────────────────────────────────────────────── 「我知道改哪」 「边写边补」 「你去搞定」
失败模式:用错档位。拿 Claude Code 的全自主 loop 去做一个你心里已有精确 diff 的机械替换——它会「自作主张」探索半天、改到你没让它碰的地方。反过来用 Aider 做开放调试——你得手动喂它每个文件,它不会自己找。自主度要匹配任务的「不确定性」
进阶资源 · Aider Edit Formats 文档, aider.chat/docs/more/edit-formats · Cursor Instant Apply, cursor.com/blog/instant-apply · Anthropic Claude Code Best Practices, anthropic.com/engineering/claude-code-best-practices
// 02

Edit Format:Coding Agent 被低估的隐藏瓶颈

论断:模型「会写对代码」不等于「能把改动落进文件」——edit format 决定了一半的可靠性。

背景与原理

一个反直觉事实:很多 coding agent 的失败不是逻辑错,是改动应用失败——模型生成的 search 块和文件里的实际文本对不上(空格、引号、它脑补的旧代码),patch 静默丢失或报错。Aider 的 leaderboard 把这点量化成核心指标:模型不仅要写对代码,还要不靠人工干预把所有改动成功 apply。四种主流 edit format 各有权衡:

核心权衡:whole file 最易写对但最贵;diff 最省但最易 apply 失败;search/replace 取中;apply model 用第二个模型买可靠性。这就是为什么不同 harness 在同一个 base model 上表现差很多——edit contract 不同。

实战示例

search/replace 块的精确长相(Aider / Claude Code 同源思路)——SEARCH 段必须和文件逐字符匹配

src/auth.py
<<<<<<< SEARCH
def verify_token(token):
    return jwt.decode(token, SECRET)
=======
def verify_token(token):
    try:
        return jwt.decode(token, SECRET, algorithms=["HS256"])
    except jwt.ExpiredSignatureError:
        raise AuthError("token expired")
>>>>>>> REPLACE

实战启发:(1)让 agent 改大文件前先让它 Read 精确片段——它脑补的旧代码是 apply 失败头号原因;(2)改动尽量小而局部,一次 replace 一个语义单元,比一次重写整函数 apply 成功率高得多;(3)模型反复 apply 失败时,换 whole-file 模式兜底比硬刚 diff 划算。

失败模式:在超长文件里让 agent 做大段 search/replace。文件越长,模型越容易记错某行的精确文本(多个空格、被它忽略的注释),SEARCH 匹配不上就静默丢改动——你以为改了,其实没动。征兆:agent 说「已修复」但测试还红。对策:缩小编辑粒度 + 改前强制 Read。
进阶资源 · Aider Code Editing Leaderboard, aider.chat/docs/leaderboards/edit · Fireworks How Cursor built Fast Apply, fireworks.ai/blog/cursor · Cursor Editing at 1000 tok/s, cursor.com/blog/instant-apply
// 03

Plan Mode:研究-计划-实现的分离不是 UX,是工程必需

论断:让 coding agent 先想后动,准确率提升来自「锁定问题」,不是「想得更久」。

背景与原理

Anthropic 的 Claude Code 最佳实践里有一条被反复强调:把研究/计划和实现分开。让 agent 直接开写,最大风险不是写得烂,是解错了问题——它对着症状打补丁,绕过你真正想改的根因。Plan mode 的工程价值有三层:

反直觉点:plan mode 的收益不来自模型多思考(那是 reasoning 的事),来自给人一个低成本的纠偏检查点。对开放任务(调试、跨文件重构、新功能),先 plan 几乎总值得;对一行修改,plan 是纯开销。

实战示例

把「explore → plan → code → commit」固化成工作流,而不是上来就让 agent 写:

# Claude Code:开 plan mode(Shift+Tab 切档),只读探索 + 出计划
> 研究 payment 模块怎么处理 retry,先别改代码,
  给我一份修复 double-charge bug 的计划:要动哪些文件、风险点、测试怎么加

# 你 review 计划,截停错误方向,确认后再切回执行档
> 计划 OK,但别碰 webhook handler。按计划实现,每改完一个文件跑一次相关测试

# Aider 等价做法:先用 /ask 只问不改,再切回 code 模式
/ask 这个 retry 逻辑哪里会导致重复扣款?应该怎么改?
# 满意后 /code 让它落地

关键纪律:计划里要求 agent 显式列「不碰什么」。coding agent 最常见的越界是顺手「优化」了你没让它动的代码——在 plan 阶段划好边界,比事后 review 拦截高效。

失败模式:对琐碎任务也强上 plan mode——改个 typo 还让它先出三段计划,纯浪费 turn 和 token。Plan 的价值随任务不确定性递增:一行改动跳过,跨文件/调试/新功能必上。判据同 §1:任务越不确定,越要先 plan。
进阶资源 · Anthropic Claude Code Best Practices(explore-plan-code), anthropic.com/engineering/claude-code-best-practices · Anthropic Building Effective Agents, anthropic.com/engineering/building-effective-agents
// 04

自主度光谱与 Closing the Loop

论断:AI pair programming 的核心技能不是写 prompt,是「选对自主度档位」+「把验证回灌给 agent」。

背景与原理

「AI pair programming」不是一个模式,是一条自主度光谱。每往右一档,吞吐越高、但你审查每行的能力越弱、错误传播越远。选档的依据是任务的可验证性——能不能让 agent 自己知道对错:

右端的 full-auto 能不能 work,几乎完全取决于 closing the loop:agent 改完能否自己跑 tests / lint / type-check,把失败信息回灌给自己再修。能闭环(有测试、报错清晰)→ 放手让它自主迭代;不能闭环(UI 微调、无测试的脚本)→ 退回低自主档,你来当那个「测试」。这也呼应 Day 3:error 回灌是 agent 自我修复的根因。

实战示例

给 full-auto agent 显式的验证闭环,而不是只给目标就撒手:

> 修复 #482 的 race condition。工作纪律:
  1. 先写一个能复现 bug 的失败测试(red)
  2. 改代码让它变绿(green)
  3. 跑 `pytest tests/ -q` + `mypy src/`全绿才算完成
  4. 任何一步红:把完整报错贴出来,分析后再改,别跳过

# 关键:给它一个客观的「完成」判据(绿)和验证工具,
# agent 才能自主闭环。没有这条,它会自我宣布「修好了」然后留一堆隐性 bug

这就是为什么 test-first 对 AI agent 比对人更重要:测试是 agent 唯一可信的「对错信号」。没有它,agent 的 self-eval 极不可靠——它倾向宣布成功(backward rationalization,Day 5 讲过)。先有红测试,full-auto 才敢放手。

失败模式:被 SWE-bench 分数误导。高分 agent 在那个 benchmark 上有明确的 PASS/FAIL 测试做闭环——你的真实仓库往往没有同等清晰的验证信号。把「SWE-bench 80%」当成「在我项目里 80% 靠谱」是错的:benchmark 帮 agent 闭了环,你的代码库可能没有。先给 agent 造出可验证闭环,分数才迁移得过来。
进阶资源 · OpenAI Introducing SWE-bench Verified, openai.com/index/introducing-swe-bench-verified · Anthropic Building Agents with the Claude Agent SDK, anthropic.com/engineering/building-agents-with-the-claude-agent-sdk

// 综合实战 · 给同一个任务选对 harness + 档位

下次接到一个 coding 任务,先别打开工具,按这张决策流走一遍——它把这一期四点串成一个可执行的选择器:

  1. 我心里有明确 diff 吗?有 → 低自主档(Cursor inline / Aider /code),别让 agent 自由发挥。没有 → 往下。
  2. 任务可闭环验证吗?(有测试 / 报错清晰)有 → full-auto agent(Claude Code),先让它写红测试再放手。没有 → 退回 chat 档,你来当验证。
  3. 不确定性高吗?(跨文件 / 调试 / 新功能)高 → 先 plan mode 锁问题、划「不碰什么」边界,再执行。低 → 直接改。
  4. 文件大吗?大 → 强制 agent 改前 Read 精确片段 + 小粒度 search/replace,降低 apply 失败。
  5. 给完成判据:无论哪档,都给一个客观「绿」信号(测试/lint/type-check 全过),别让 agent 自我宣布成功。

练几次你会发现:选对「档位」带来的体感提升,往往大于换一个更强的模型。这就是 harness 思维——模型是 CPU,你的工作流才是真正的杠杆

// ENGLISH GLOSSARY

Edit Format
模型把改动落进文件的契约:whole-file / unified-diff / search-replace / apply-model。决定 apply 成功率。
Search/Replace Block
给精确旧文本+新文本的 diff 格式(Aider 主力)。靠文本匹配而非行号,比 unified diff 鲁棒。
Apply Model
专训的小模型,把 frontier model 的粗略意图精确落成文件 diff。Cursor instant apply 的核心。
Fast Apply
Cursor 的高速编辑落地(~1000 tok/s),用 speculative edits 加速。
Plan Mode
Claude Code 的只读探索档,harness 层物理禁写。研究/计划与实现分离。
Closing the Loop
agent 改完自跑 tests/lint 并把失败回灌自修的闭环。full-auto 安全的前提。
Autonomy Spectrum
tab → chat → full-auto 的自主度光谱。依任务可验证性选档。
SWE-bench Verified
500 个人工校验的真实 GitHub issue 修复任务,resolved rate 为主指标。
Test-first for Agents
先写红测试再放手 agent。测试是 agent 唯一可信的对错信号。

// 深入思考

Cursor 用第二个模型做 apply,Claude Code 让同一个模型直接产出 string-replace。这两条路线各自的代价是什么?
Cursor 路线:frontier 只管「想」、apply model 管「准」——frontier 可用更省的粗 diff 表达意图,apply 飞快且成功率高;代价是多养一个模型,且两个模型的理解可能错位(apply model 误解意图)。Claude Code 路线:单模型端到端,无错位、无额外基础设施;代价是 frontier 要亲自产出逐字符精确的 SEARCH 块,长文件易记错、apply 失败率随长度上升。本质是「可靠性 vs 简洁性」的架构选择,取决于你能否养得起一个 apply model。
plan mode 物理禁写带来安全,但也切断了「边做边发现计划要改」的可能。这个 trade-off 怎么权衡?
plan/execute 分离的隐性假设是「计划能在不动手的情况下基本定下来」。对很多任务这不成立——真正的约束往往在你开始改才暴露(某个 API 不存在、依赖冲突)。死守 plan 会让 agent 拿着过时计划硬撞。务实做法:plan 不是一次性合同,是checkpoint。让 agent 执行中发现计划失效时主动停下来重新 plan,而不是闷头按错计划做完。好的 harness 支持「执行→撞墙→回 plan」的循环,而非单向瀑布。这也是为什么 evaluator-optimizer 这类带反馈的 workflow 比纯线性 plan-execute 更鲁棒。
如果 test-first 是 agent 自主的前提,那对「无法写测试」的领域(前端视觉、prompt 调优、探索性数据分析),coding agent 的自主上限在哪?
上限被「验证信号的客观性」锁死。这些领域的对错要么主观(视觉好不好看)、要么需人判断,agent 无法自己闭环→只能退低自主档,人做 oracle。出路:(1)造代理指标——视觉用 screenshot diff、prompt 用 LLM-as-judge + 固定 eval set,把主观转成可跑信号;(2)人在环高频审查;(3)缩小到可验证子问题(前端逻辑可测、样式人审)。核心:agent 的自主度 = 你能为它造出多客观的验证闭环。造不出,就别假装 full-auto。
为什么 SWE-bench 分数高的 agent,迁移到你的真实仓库常常「掉分」?除了测试闭环,还有哪些隐藏差异?
除了 §4 的闭环差异,还有:(1)SWE-bench 任务自包含、范围明确,真实工作常是模糊的「让它更好」,问题定义本身就难;(2)benchmark 仓库文档/测试齐全,你的私有库可能文档烂、隐性约定多,agent 缺上下文;(3)benchmark 允许多次尝试取最好(pass@k),生产里你常只看第一次;(4)数据污染——热门 issue 可能在训练数据里见过。所以 leaderboard 是「能力上界的相对排序」,不是「在我这能用多少」的绝对预测。选 agent 看趋势,别迷信绝对数字。
Aider 每次改动自动 git commit,Claude Code 倾向攒一批再让你 review。两种「改动粒度」哲学对人机协作有什么不同影响?
Aider 的细粒度 commit:每步可 /undo、git 历史即审计、回退便宜→鼓励你「放手让它多试」,错了就退;代价是历史碎、需事后 squash。Claude Code 的攒批:一次给你一个语义完整的块 review,认知负担集中、diff 连贯,但中间某步错了回退成本高。哲学差异:Aider 把「可逆性」做到极致,适合探索容错的工作;Claude Code 赌「一次做对一个完整单元」,适合你信任它、想要干净历史。好习惯:无论哪个都自己控制 commit 边界——让每个 commit 是可独立 review/revert 的语义单元,别被工具默认粒度牵着走。

// 延伸阅读