笔记日期: 2026 年 10 月 5 日
笔记作者: Zhongzhu Zhou
论文题名: A Self-Improving Coding Agent
论文作者: Maxime Robeyns、Martin Szummer、Laurence Aitchison
arXiv 与版本: 2504.15228v2,2025 年 5 月 16 日
1. 我想先分清:到底是谁在变强?
读完昨天的 DGM,再看 SICA,我最关心的不是“模型能不能修改代码”这个已经很熟悉的问题,而是:如果修改对象就是 agent 自己,下次负责修改的又换成改进后的版本,这个循环究竟多带来了一层什么能力?SICA 给出了一个可以实际观察的系统:保存旧版本及其测评结果,挑出效用最高的版本,让它阅读历史、提出改动并生成下一个版本,再继续评估。
这里的变化主要发生在模型外面的程序。这个程序决定有哪些工具、怎样调用子 agent、如何组织文件内容、什么时候返回结果,以及怎样把工具反馈交还给模型。基础模型权重保持不变。因此,“自我改进”不意味着模型的参数在这个实验里自动训练得更强,而是同一批模型获得了不同的工作方式。
我的主要理解是:SICA 把一部分 agent 工程变成了可积累的学习过程。有效改动不一定是新颖的推理理论,可能只是让小修改不再需要重写整个文件,让找符号不再依靠大量盲搜,或者让父 agent 少背负一大段已经没用的工具输出。在有限时间内,这些改动可以把原本浪费在操作上的预算释放出来,留给定位、验证和修错。
先把最容易传播错的数字说完整。论文在固定随机抽取的 50 道 SWE-bench Verified 题目上,报告分数从 17% 上升到 53%。表 1 中,17% 对应初始版本,53% 对应第 14 轮;最后列出的第 15 轮是 51%。这不是完整 SWE-bench Verified 榜单成绩,也不是每轮都提高。单题 300 秒超时和成本相关的选择目标,都是理解这组数字必须带上的条件。

图 1. 根据论文第 3 节及算法 1 重绘的流程。档案既提供历史证据,也提供下一轮负责修改的 agent;基础模型权重保持固定,参与下一轮工作的 agent 程序可以变化。
另一个值得认真看的结果是“没有明显变好”。作者把同样的自指思路用于 AIME 2024 和 GPQA Diamond,发现额外的数学验证器、专业角色和推理流程没有稳定带来提升。当系统已经能把题目交给一个强推理模型时,再加一层编排可能只是增加开销,甚至干扰原来的解题过程。这个负结果比笼统地宣称递归改进无所不能更有启发。
这篇笔记依据 v2 全文 18 页,包括附录中的提示词、运行轨迹、函数调用说明和改动记录。下面会区分三类内容:论文报告的测量、我为解释机制所做的推导、以及我认为值得补充的实验。图中的自拟算例不是复现结果;表 1 重绘图只使用论文已经给出的数字。
2. 前置知识:模型、程序与运行状态是三件事
2.1 权重不变,行为仍然可以变化
把 agent 拆开看,可以看到三个对象。第一是参数为 的语言模型,它根据上下文生成下一段内容。第二是 agent 程序 ,它负责把模型输出变成工具调用,再把观察写回上下文。第三是某一次运行的临时状态,例如已打开的文件、已经尝试过的补丁、当前任务的半成品和对话历史。
SICA 主要把改进保存在第二个对象里。一次运行结束后,对话状态可能消失,但新工具、新路由或新的上下文策略可以作为程序保留下来,供下一道题使用。为了方便讨论,我用下面的记号表示一次任务执行;这是解释性建模,不是论文额外训练了一个轨迹模型:
是任务, 是包含动作和反馈的轨迹, 是最终输出。即使 不动,换一个 也会改变下一步能看到什么、可以做什么。一个精确的符号定位工具可以省去十次无效搜索;一个可靠的局部编辑工具可以避免生成大量未修改代码;一个直接调用强推理模型的路由可以减少不必要的讨论。
这也是为什么“模型没有训练”不等于“系统没有学习”。学习可以表现为外部程序积累了更好的行为方式。但反过来也要注意:一次对话里说了“下次别这样做”,不等于这个教训已经跨任务保存。只有当它转化为可复用的程序、记忆或策略,才会影响新的独立运行。SICA 的档案把程序版本与结果联系起来,给这种变化一个可以追踪的载体。
2.2 会解题,不一定会发明更好的解题器
自我改进有两个容易被合并的能力:完成外部任务,以及设计更好的自己。一个擅长修业务代码的 agent,未必擅长发现哪一个系统性瓶颈值得先改。元改进过程至少需要诊断、选题和实现三种能力,而普通任务分数并没有直接把它们分别测出来。
设 是档案中的一个版本, 是测得的效用, 是当前档案。我把论文的核心选择机制写成:
这里的 只是“被选中的 agent 收到改进任务后,会生成什么候选程序”的简写。它不是论文另外定义或训练的网络。式子强调的是依赖关系:解题效用决定谁来当下一轮修改者,而这个修改者的程序又会影响下一轮产生什么修改。
这比固定一个永远不变的设计者、让它修改另一个目标 agent,多了一层反馈。SICA 用这个区别解释自己与 ADAS 的关系。不过,我不想把“谁才算真正自我改进”变成术语争执。更有用的分析方式是逐项问清楚:什么会变、什么保持固定、谁选择版本、选择依据是什么、改变后会不会参与下一次改进。
如果要证明这层反馈带来了递归优势,就要测“更强的解题 agent 是否更会生成有用后代”。只看到后代的解题分数上升,还不能完全回答这个问题。固定设计者也可能在一个不错的搜索空间中不断找到更好的程序。
2.3 档案保存的是证据,不是正确性证明
档案通常包含程序和测评结果,但结果有噪声。任务数量有限,模型输出随机,网络延迟和 API 服务状态也可能变化。取最高分会倾向于挑中那些真实能力不错、同时又恰好比较幸运的版本。保存了全部历史,也不意味着选择器就已经自动处理了这些不确定性。
尤其要警惕“历史最佳曲线一直上涨”带来的直觉。记历史最高测量值为:
它不下降,是最大值这个运算的性质。即使大部分新候选都退步,历史最高值也不会因此下降。这条曲线不能单独证明每轮编辑都有用,不能证明获胜版本能泛化,也不能证明继续运行就一定能继续进步。必须同时看每轮原始分数、测评任务的构成,以及选择之后有没有独立验证。
失败版本仍可能有价值。例如一次修改让文件编辑更快,却破坏了复杂任务所需的信息,档案可以帮助下一轮理解这个权衡。但“有信息被保存”和“下一轮正确利用了信息”是两回事。后面讨论路径依赖时,这个差别会再次出现。
3. 初始 agent 并不是一张白纸
3.1 工具决定哪些改进能够被表达
论文的起点已经是一个相当完整的代码 agent。它能把文件加入或移出上下文、覆盖文件、运行 shell 命令、使用计算器、提交答案,也能从子 agent 返回结果或提前退出。还有专门的档案分析工具,用来获取不同版本的高层统计信息。也就是说,它既具备修改代码的基本手段,也具备回看历史的入口。
初始结构包含负责路由的主 agent,以及编码、问题求解和推理子 agent。调用子 agent 在接口上类似调用工具:传入参数,得到一个字符串结果。它可以承担分工,也可以承担上下文管理。某个子任务的详细过程在子 agent 返回后不必全部留在父 agent 的窗口里,父级可以只保留结果摘要。
这种方式容易被描述成“多一个专家就更强”,但真正需要核对的是结果是否足够、开销是否值得。摘要可能遗漏一个失败前提、一处准确文件位置,或者“验证通过”到底指哪一个检查。父级如果只收到一个语气肯定的结论,可能会重复劳动,也可能在错误基础上继续推进。角色数量本身不是性能指标。
把这个机制放到元改进中看就很清楚:分析历史、提出修改、开发功能、理解失败,各自可能需要不同上下文。分工让长过程可管理,但也增加了信息交接次数。一个新版本如果只是增加子 agent,却没有减少遗漏或缩短关键路径,很可能反而降低效用。
3.2 上下文结构本身就是算法的一部分
SICA 将上下文分成系统部分、核心部分和不断增长的历史。系统部分描述 agent 角色、工具、子 agent 和返回约定;核心部分放任务、已打开文件和目录结构;后续历史记录模型消息、工具结果、子 agent 返回值,以及监督器通知。

图 2. 根据论文图 2 和第 3.1 节绘制。文件视图、目录和工具观察都构成 agent 的有效状态,仅看系统提示词不足以理解它的行为。
这个结构同时影响模型理解和缓存复用。论文描述的初始策略是把文件变化作为 diff 追加进上下文,累积一定数量后再合并到文件视图中。追加内容通常比频繁重写前面的长前缀更容易保留已有 KV 缓存,也可能降低重复输入的费用和等待时间。
但缓存不是唯一目标。假如一个文件已经经历很多轮修改,而上下文仍保留旧文件加十几份 diff,模型就需要自己在脑中合成当前状态。这种负担可能比重新提供完整文件更危险。定期合并能让文件状态更清晰,却会改变更长的前缀,牺牲一部分缓存。两者之间有真实权衡。
我把它理解成“物化视图加更新日志”:视图容易读取,但刷新成本高;日志容易追加,但越积越难解释。什么时候合并,取决于文件大小、编辑频率、上下文长度、任务性质以及服务端的缓存机制。SICA 的特点是让这种策略也可以被修改,而不是证明了一个所有场景通用的最优合并周期。
这里也不能从实验表中看到缓存比例上涨,就立即断言某个压缩工具带来了全部成本下降。模型调用比例、输入输出 token 的构成和任务行为都会影响费用。缓存列是有用的观察,尚不是单独的因果实验。
3.3 监督器为什么需要看全局?
初始系统有一个异步 LLM 监督器,默认每 30 秒或在重要事件时运行一次。它看到的是调用树与事件流的摘要,可以发现某个分支反复做无效工作,也可以发现不同子 agent 重复完成同一件事。它能向运行中的 agent 发通知,严重时可以取消执行。
这个角色的优势来自视角:正在修局部问题的子 agent,未必知道其他分支早已给出答案;父 agent 则未必时时看得见子级内部的重复。监督器把跨调用的行为放在一起看,有机会及早发现循环。但它自己也依赖模型判断和被压缩过的记录,可能误判一个合法但较慢的操作。
因此,我会把它看作进度控制器,而不会因为系统里有监督器,就认为过程已经天然可靠。要量化它的作用,需要统计成功干预、误取消、额外调用成本以及对最终完成率的影响。论文给出了机制、提示词和轨迹例子,没有把监督器的净贡献完整拆分出来。
附录还提到一个很普通、却在自我修改时容易忽略的软件问题:磁盘上的代码变了,当前运行进程已经加载的对象并不会自动一起更新。作者的监督器提示要求在独立执行中测试新 agent,或者使用明确的测试脚本。它提醒我们分清“正在编辑的程序”和“负责编辑的这个进程”。自指概念再有吸引力,也不能替代这些运行时边界。
3.4 工具调用格式解决了什么,又没解决什么?
附录 C 描述一种不强制约束生成的 XML 调用格式:模型输出工具名和参数,关闭标签被注册为停止标记。运行器识别停止原因,解析名称和参数,调用对应工具,再把观察送回去。作者选择这种格式的一个原因是,文件内容作为参数时,不需要承担 JSON 字符串字面量那样的转义负担。
这是一项接口设计选择,不是正确性保证。任何分隔符格式都需要清晰的终止规则、参数验证和错误处理。工具名合法,不代表参数引用了正确文件;文本成功解析,不代表动作对当前任务合适。约束生成或服务商原生函数接口可能减少某些格式错误,同时引入别的表达或兼容性限制。
我认为这里应当把贡献放在正确的层次:SICA 展示的是一个可演化的 agent 系统,而不是凭一个序列化格式解释全部成绩。没有对照实验,就不能把收益归因成“XML 比 JSON 更聪明”。
4. 效用函数:把质量、费用和时间放到同一把尺子上
4.1 先做无量纲化,再谈加权
任务分数、美元和秒不能直接相加。论文先用预算尺度把费用和时间归一化。记任务分数为 ,费用为 ,耗时为 。参考尺度是 美元和 秒。两个效率项定义为:
零费用或零耗时对应效率 1;达到参考尺度时对应 0;再继续增加,该效率项保持 0,不变成负无穷。这里的截断保证了指标范围,也说明仅凭这个式子不能推断“花到 10 美元一定会被强制停止”。论文单独描述了 300 秒的超时取消机制。
任务分数权重为一半,费用效率和时间效率各占四分之一:
所有输入符合上面的范围时, 在 0 和 1 之间。注意,一个得分为零的任务仍然可以拿到费用和时间两项的分数。这不是推导错误,而是加法效用的含义:便宜且迅速的失败,不会和昂贵又缓慢的失败完全等价。某些应用接受这种偏好,某些应用则会要求先达到最低成功标准,再优化资源。
4.2 权重实际上规定了交换价格
在费用、时间都还没有触发截断时,将式(4)代入式(5),展开括号:
比较两个都处在这个区间内的方案,常数项消掉,就得到:
如果耗时不变,多花 1 美元需要多拿 5 个百分点的任务分数,才刚好打平。如果费用不变,多花 60 秒需要多拿 10 个百分点。这个“价格”来自作者选择的系数,不是普适的经济规律。换一种 API 价格,或者换一个对交互延迟非常敏感的应用,合理权重就可能改变。

图 3. 根据论文公式计算的示意热图,固定任务分数为 0.5。10 美元之后,费用项不再下降。图中尚未乘超时惩罚系数,不能把它当作实测性能分布。
用一个自拟例子检查直觉:A 的任务分数是 0.50,费用 2 美元,耗时 120 秒,代入得到 。B 的任务分数提高到 0.54,但费用变为 3 美元、耗时变为 150 秒,效用反而只有 0.57。B 的质量指标更高,A 却会在这套目标下获胜。这两个方案只是算例,不对应任何实际 SICA 轮次。
这个例子有助于理解“选最好的 agent”究竟是什么意思。这里的“最好”是作者选定效用下的最好,不一定是准确率最高、最快或者最便宜。把标量目标写出来,比直接说系统自动寻找最优架构更诚实,也更便于迁移到自己的应用。
4.3 超时惩罚带来一个跳变
论文在超时之后将基础效用减半,惩罚参数取 0.5:
这不仅是“稍微快一点就稍微好一点”。一个刚好在截止前完成的运行,与一个被判为超时的运行,最终效用可能发生明显跳变。假设任务分数 0.5、费用 2 美元,在 299 秒完成时,基础效用约为 0.4508。若到 300 秒被判为超时,在相同分数和费用下,最终效用变为 0.225。这是在解释规则,不是在断言运行器在边界毫秒上的事件先后顺序。
这种结构会强烈奖励消除操作瓶颈。原本重写文件太慢,导致来不及测试;换成局部编辑后,也许同样的模型就有时间运行测试并修掉第二个错误。于是准确率和耗时一起改善。它是实实在在的系统收益,但不能直接推导成模型新增了某种抽象推理能力。
最后,这个分数用来选择档案中的下一位修改者,也作为下一轮可阅读的信息。它没有被反向传播进模型参数。因此,若把它叫作 reward,应当记住它的实际作用是搜索与选择,不能与策略梯度训练中的奖励机制混为一谈。
5. 把循环展开:哪些账目必须分别保存?
算法 1. 明确评估步骤的自我改进循环
下面是我根据第 3 节整理的解释性伪代码,把候选评估写全,不是逐字抄录论文的紧凑下标形式。
1. 建立初始 agent 程序 g0,并固定本次使用的任务集合 B。
2. 评估 g0,保存任务结果、资源消耗和效用。
3. 对每一次允许的改进尝试:
4. 从档案里选择测得效用最高的 agent。
5. 把改进任务及档案证据提供给这个 agent。
6. 让它诊断问题、提出修改并生成候选程序。
7. 在相同任务条件下评估候选。
8. 将程序、观察和效用一起加入档案。
9. 分别报告最后候选,以及测量结果最好的历史版本。
最后一行是我对报告方式的补充。论文算法 1 写的是返回最后生成的 agent,但循环中负责继续修改的是历史最优者。这两个对象不一定相同。紧凑伪代码先评估当前版本,再生成下一版,因此最后一个候选的评估在完整实验流程中还需要说明;不能只凭略写的算法就擅自补出实验细节。
另一点是,保留失败候选,不意味着下一轮会选择这个失败候选当编辑者。SICA 描述的规则是贪心地选择当前最高效用的版本。档案当然也能提供失败经验和过去的不同设计,但父版本选择仍可能比较集中。档案的信息丰富度,与实际搜索路径的多样性,并不是同一个量。
这也是它与昨天读的 DGM 值得对照的地方。两者都保留历史,也都允许 agent 程序被编辑。SICA 的主线是让当前最优版本成为下一位修改者;DGM 更强调从档案中探索不同谱系。我们可以比较这两种选择机制的偏好,但不能直接拿两个论文的头条百分比排高下,因为任务集合、预算和设置不一致。
一个例子可以帮助理解贪心的边界:某次重构先增加了模块化开销,短期分数下降,却让下一步接入新工具更容易。如果只让当前最高分版本继续当父级,可能很难走过这段暂时退步。档案保留了那次重构,并不自动意味着它最终会被组合回来。要实现这种探索,需要选择机制或提案机制真正利用这个中间状态。
算法 2. 单次任务运行的效用计算
公式简单,但保留原始分量非常重要,尤其不能拿跨任务均值代替每次运行后再进行非线性计算。
1. 读取任务分数 p、费用 c、耗时 t 和超时标记 z。
2. 费用效率 ec = 1 - min(1, c / 10 美元)。
3. 时间效率 et = 1 - min(1, t / 300 秒)。
4. 基础效用 u = 0.5*p + 0.25*ec + 0.25*et。
5. 若 z 为真,v = 0.5*u;否则 v = u。
6. 将 p、c、t、z 与 v 一同保存,供后续聚合。
为什么不能只保存均值?因为截断和超时乘数都是非线性的。举一个为说明数学问题而构造的极端例子:两次费用分别为 0 美元和 20 美元,它们的平均费用是 10 美元。分别算效率再取平均,得到 0.5;先平均费用再算效率,得到 0。两种做法不是同一个统计量。
表 1 提供了各类任务的分数,以及跨任务汇总的成本和时间,但没有给出全部任务级的超时标记与分量。因此,不能诚实地从这些均值恢复每轮精确的最终效用,也不能替作者重算完整置信区间。本文选择重绘已报告的原始维度,不制造一条看上去很精确、实际缺少输入的效用曲线。
实际阅读中,我更愿意多保留一列看似琐碎的超时统计,也不愿用一个均值掩盖不同失败模式。快速失败、超时失败、成功但费用高,可能需要完全不同的下一步改进。一个总分有利于选择,却不一定足以诊断。
算法 3. 怎样把档案读成证据?
这是我用来理解论文方法和轨迹的分析步骤,不是作者额外做过的一项实验。
1. 找到当前版本失败或耗尽预算的任务。
2. 将问题区分为定位、编辑、推理和执行瓶颈。
3. 对照同类任务中成功与失败的轨迹。
4. 提出一个修改,并写清它预期改善的机制。
5. 列出它可能损害的任务类型或资源指标。
6. 比较新候选与相关前序版本的实测变化。
7. 把因果假设和观察到的分数变化分开保存。
附录 B 给出的元改进轨迹,与这个思路相呼应:档案分析子 agent 比较不同轮次,查看成功案例与失败案例,最后建议一个方向;编码子 agent 实现这个方向,再由另一个编码子 agent 做独立的一轮检查。它把“看历史—提想法—做修改”的过程具体展示出来。
但一个代表性轨迹不是频率统计。不能因为附录展示了这样的顺序,就声称每轮都严格遵循它,或者独立检查永远能发现回归。轨迹中同时存在长时间调用、测试失败和重新调整,恰好说明元改进本身也是一个会走弯路的工程任务。
我从中提炼的重点不是“再安排一个角色就够了”,而是让每一步有可追溯的依据:为什么选这个问题、改动针对什么瓶颈、结果在哪些任务上改善、哪些任务退步。只有把这条证据链保留下来,下一轮才有可能学到比“上一版总分更高”更丰富的信息。
6. 实验里的四种任务分别在量什么?
6.1 文件编辑和符号定位是操作能力探针
主实验包含四类任务。文件编辑任务从代码仓库历史中构造:给 agent 一个旧版本文件,要求修改到目标内容,再根据结果与目标的接近程度评分。符号定位任务给出一次符号引用,要求返回定义所在文件、行和列。另两类是 SWE-bench Verified 的仓库问题修复,以及更偏算法求解的 LiveCodeBench。
合成任务的好处,是能把端到端失败拆成更具体的问题。一个 agent 解不出仓库 issue,可能不是不会推理,而是编辑接口太笨,或连正确函数都没找到。单独测编辑和定位,有助于看清这些环节。它们也比较适合作为细粒度反馈,指导工具改进。
但代理指标不能等同于最终语义。文件内容接近目标,不一定证明程序行为正确;符号位置不一致,也不一定是 agent 的错。作者明确指出符号任务的数据质量问题,例如部分目标实际上来自未安装的外部库。这样的任务会把“没有可用目标”和“搜索能力不足”混在一起。
因此,一条很低的符号定位曲线,既可能暴露工具不足,也可能暴露任务定义缺陷。把所有失败都交给 agent 自我修正,未必是合理的归因。某些问题需要修测评集,某些问题才需要修 agent。这也说明未来自动生成基准时,基准验证的重要性不会因为生成过程自动化而降低。
6.2 模型与预算是实验的一部分
SWE-bench Verified 固定抽取 50 题,LiveCodeBench 随机抽取 50 题。系统中的大部分 agent 使用 Claude 3.5 Sonnet v2,推理子 agent 使用 o3-mini。这是一个混合模型系统,不能把整体分数简称为 Sonnet 的独立成绩。
例如,一个路由修改让系统更经常把适合的题交给强推理子 agent,最终成绩可能提高。这是有价值的系统工程,但没有证明较弱模型的内部推理能力发生了训练式变化。测量对象应该始终是“带着这组模型、工具和调度规则的系统”。
论文报告 15 轮运行的 API 总费用约 7,000 美元。这个数字描述的是搜索过程,与表 1 中每道测评题的平均费用不是同一件事。把最终 agent 用于实际工作,需要分别考虑找出它的成本和使用它的成本。迭代次数少、样本利用充分,并不必然意味着花的钱少。
模型服务价格、历史 API 延迟和缓存规则,也会影响这组资源数字。本文引用的是论文当时的记录,不是今天的报价。如果把相同程序迁移到本地推理或另一种模型服务上,最佳版本与效用排序都可能变化。这并不否定实验,只是说明它有明确的运行条件。
7. 重看表 1:收益在哪里,代价又在哪里?
7.1 各条曲线并不一起上升

图 4. 使用论文表 1 的 16 行原始舍入值重绘。SWE-bench 与 LiveCodeBench 均为论文使用的子集。图中没有额外估计的置信区间,也没有把历史最佳曲线代替每轮实际分数。
最明显的变化来自 SWE-bench:初始 0.17,第 14 轮达到 0.53,第 15 轮为 0.51。从初始到峰值,绝对提升是 36 个百分点。如果计算倍数,约为原来的 3.12 倍;我更愿意先报告百分点,因为起点较低时,倍数很容易让读者高估其普遍意义。
文件编辑从 0.82 到最终 0.91,但中途第 6 轮已经达到过 0.96。符号定位从 0.35 到最终 0.40,中途最高 0.43。LiveCodeBench 从 0.65 到 0.71,改善较温和,而且第 4 轮曾降到 0.54。同一个系统改动可能改善某类任务、损害另一类任务;最后总分更好,不代表所有能力都单调上升。
这提醒我不要把迭代轮数当成天然进度条。第 13 轮的 SWE-bench 分数明显回落,后面又恢复,这个形状与“每轮都把上轮能力完整继承并增强”的想象不同。它更像有噪声、有冲突目标、会产生回归的软件搜索过程。
还有一个细小但重要的统计边界:50 道题如果每题只进行一次二元成功判定,原始比例会以 0.02 为步长变化,而表中出现了 0.17、0.53 等值。仅凭这些打印出来的小数,我们不能擅自声称某轮恰好解出多少道,也不能反推一个不存在的二项分布置信区间。需要额外的重复运行、聚合和任务级结果说明,才能准确恢复这些统计。
因此,本文保留论文报告的分数,不把它改写成虚构的整数成功数。这不是说结果没有价值,而是把“作者给出的平均数”和“我们可以独立重建的不确定性”分开。论文原图中的置信带可以按原图引用,但表 1 重绘图不应该额外添加没有依据的误差带。
7.2 最后更便宜,不代表中途每轮都更便宜

图 5. 论文表 1 的每题平均美元费用、时间和缓存 token 比例。这些资源量是跨测评任务汇总的均值,不是 SWE-bench 子集专属的开销。
初始版本平均每题花费 1.91 美元、130.2 秒;第 15 轮变成 1.70 美元、114.5 秒。用表中的舍入数字计算,费用约下降 11.0%,时间约下降 12.1%。这些变化说明最终版本在这套测量下更经济,但不能据此说每一次改动都降低开销。
更有意思的是,表中每题 token 量从 0.24 百万增加到 0.30 百万。因此“费用更低”不能简单翻译成“token 更少”。缓存命中、输入输出构成、不同模型的调用比例以及重试行为,都可能影响价格。论文数据足以显示这种现象,不足以把差异唯一归因到某一个因素。
缓存 token 比例从 32.5% 到最终 36.3%,最高却出现在第 10 轮,为 40.9%。缓存更高的版本,也不必然是所有任务上最强的版本。对实际 harness 来说,缓存是一个资源杠杆,必须和信息质量、任务完成率一起看。
最需要避免的拼接是:用第 14 轮的 53% 准确率,再拿第 15 轮的低成本,宣称一个版本同时达成了两者。事实上,第 14 轮每题平均成本是 2.20 美元,高于初始 1.91 美元;它的时间为 117.1 秒。最高准确率对应的版本确实更快,却不是那个更便宜的最终版本。每个数字都要保留自己的行号。
7.3 “最好”取决于目标

图 6. 将表 1 的 SWE-bench 分数与跨任务平均费用放在一起,数字标记为迭代轮次。两轴的任务总体不同,因此它只是展示记录维度的权衡,不能当作 SWE-bench 单独的成本效率前沿。
第 12 轮的平均费用最低,为 1.58 美元;平均时间也最低,为 103.9 秒。它的 SWE-bench 分数是 0.44,没有达到峰值。第 15 轮的 LiveCodeBench 分数最好,第 6 轮文件编辑最好。公开表格里没有一个版本在所有标准上都胜过其他版本。
因此,一个实际产品未必只需要保存一个冠军。强调交互响应的场景可能选快的版本,困难仓库修复可能愿意付更多成本。甚至可以根据任务类型选择不同版本。但是,这属于可以扩展的决策策略,不能说论文已经验证了这种按任务动态组合一定有效。
标量效用的优点是方便:它能给出一个明确排序,循环无需每次人工讨论取舍。缺点也正是把多维取舍压成一个数。某些应用可能要求准确率不低于某条线,然后才比较费用;另一些应用可能对超时有不可接受的硬约束。迁移 SICA 思路时,首先应该重新定义这一层,而不是原样复制权重。
8. 改动记录究竟揭示了什么机制?
8.1 从整文件覆盖转向局部修改
附录 D 中大量改动围绕编辑接口:智能编辑、快速覆盖、基于 diff 的策略选择、输入规范化、文件状态追踪。共同方向是减少一次小修改所需要生成和核对的无关内容。整文件重写会重复大量未变文本,也给意外删除或改坏附近代码留下更多机会。
局部补丁可以更集中地表达意图,但也引入新的失败模式:目标文本已经过时,匹配不唯一,或者同一个片段在文件中出现多次。一个快但经常贴错位置的工具并不能真正提升系统。输入规范化和状态追踪之所以重要,就在于它们帮助维持“这个编辑针对的是哪一个文件状态”。
在 300 秒预算下,编辑速度与任务成功率可能强烈耦合。一次补丁省下的时间,可能刚好够运行测试、发现错误,再补一次修复。因此,操作工具改良可以改变最终任务分数,而不只是改善用户体验。这个解释与论文关于早期收益来源的讨论一致。
但不能把改动清单当作消融实验。某轮引入了新编辑工具、分数随后变化,只能提供关联和机制线索。模型随机性、其他同时发生的改动、任务分布和不同版本的选择,也会影响结果。若要说某一工具贡献了多少百分点,需要额外的受控比较。
8.2 定位工具:先缩小候选,再做结构判断
第 9 轮出现 AST 符号定位器。抽象语法树把代码结构显式表示出来,比单纯搜索一个名字更容易区分定义和普通提及。它能帮助精确定位函数或类,但前提是语言和代码形态适合解析。论文也指出,这可能利用了基准主要由 Python 构成的特点。
后来的混合定位器把文本搜索与 AST 验证结合:先用快速搜索缩小候选,再用结构化方法确认。这是很直观的系统设计,昂贵或复杂的操作不必作用于整个仓库。进一步的定向解析只处理相关区域,而不是整份文件,也沿着相同方向减少工作量。
边界在哪里?动态绑定、生成代码、未安装依赖,以及没有相应解析器的语言,都可能让这种结构假设失效。既然符号任务本身就有外部库目标的问题,不能把一个 Python 上的改进概括为所有语言通用的代码导航能力。更合适的下一步是跨语言、跨仓库测评。

图 7. 根据附录 D 按功能归类,组之间允许重叠。附录的文字改动清单列到 14,表 1 却还包含第 15 轮;本文不会为缺少说明的最后一轮编造改动名称。
8.3 压缩观察也可能压掉关键证据
代码摘要和更小的 diff 输出可以节省上下文,但工具反馈不只是需要清理的噪声,它也是模型判断外部世界的证据。过度压缩可能去掉一个导入语句、一条错误栈、一段邻近约束,或前次失败所依赖的条件。结果是输入更短,下一步决策却更差。
所以我不把“摘要越多越好”当作结论。更值得尝试的是保留准确位置和修改行,压缩重复信息,同时在遇到决策相关的不确定性时重新获取原始材料。SICA 的可编辑程序能够表达这样的策略,但论文没有求出保真度与开销之间的最优点。
相同改动还可能影响不同任务。文件编辑探针只需要快速匹配局部内容,复杂仓库问题则可能依赖远处的调用关系。激进压缩在前者有帮助,在后者可能有害。表中的非单调曲线与这种权衡相容,但也与测量噪声等其他解释相容,不能单凭曲线形状确定原因。
8.4 改善工具和改善选题是不同瓶颈
我读改动记录时还有一个感受:实现工具的能力往往比发现新方向更容易积累。补丁更可靠之后,下一次做补丁工具也更方便;但“下一次到底应该改什么”仍然需要判断。若初始思路一直围绕同一个局部问题打转,再好的编码能力也未必能把系统带到新的能力区间。
这对应作者在局限中讨论的路径依赖。一个普通想法可以衍生很多变体,看起来每轮都有新名字,实质上却没有离开同一条窄路线。档案如果只强调历史最优分数和最近成功经验,可能进一步加强这种锚定。把失败原因、未探索方向和不同任务的瓶颈也写清楚,才有机会帮助下一轮重新选择方向。
9. 为什么推理任务的“几乎没提升”值得保留?

图 8. 引自 Robeyns、Szummer 与 Aitchison 的 SICA v2 第 7 页图 4,按 CC BY 4.0 使用。图中平均分与历史最佳分针对 AIME 2024、GPQA Diamond;置信带来自原图,不是本文根据缺失的任务级数据重新估算。
第二组实验的初始系统在 AIME 与 GPQA Diamond 上平均约 76%。论文引用的 o3-mini-high 独立成绩分别为 87% 和 79%。这些数字提供强推理模型已经具备较高能力的背景,不应该被当作作者在完全匹配所有设置后重新做出的严格对照。
轨迹分析显示,主 agent 常常直接把问题交给 o3-mini 推理子 agent。此时外层系统可能已经获得了最主要的能力来源,再增加独立数学验证器、符号计算工具或某个专家角色,并不必然改善答案。作者提出一种解释:外部强加的粗糙推理流程可能打断一个已经训练好的推理模型的内部解题方式。
这个解释合理,但仍是解释,实验没有把“打断推理”隔离成唯一原因。也可能是新改动质量不高、任务本来不太需要外部工具、选择信号过于嘈杂,或者额外验证的时间代价抵消了收益。初始路由已经足够好,也可能让可改进空间变小。
我会把这个负结果用来校准对 harness 的预期。若瓶颈是找文件、用工具、维护状态、把复杂流程组织起来,外层程序可以释放很多被浪费的能力。若题目几乎不与外界交互,而基础模型已经有很好的内部解法,多层协调可能只是增加噪声和费用。两种情况都叫 agent,但需要优化的地方并不一样。
这不是一条“代码任务一定适合,数学任务一定不适合”的定律。数学中也可能需要可靠的计算工具、定理检索和长程状态维护;代码任务也可能主要卡在模型理解能力。更好的做法是根据具体失败模式判断,先找瓶颈,再决定是否值得增加结构。
10. 局限与失败边界
10.1 固定小集合上的反复选择
当相同任务集合持续指导修改和选择,它就承担了开发反馈的角色。成绩在这个集合上提高,是有意义的进展,但不能自动推出对未见仓库、语言和任务的泛化。一个 AST 工具可能同时是通用的好主意,又特别适合当前 Python 任务分布,两者不矛盾。
要估计泛化,需要另外的任务总体。只把旧问题换个顺序并不够;如果相同仓库模式和相同错误类型仍不断泄漏进提案,选择过程仍可能围绕有限分布调整。保留从未指导过修改的最终评估集,能帮助区分真正可迁移的改进与开发集上的适应。
反复测量还带来选择偏差。比较很多候选后挑最高分,与只测一个预先确定的系统,不是同一个统计问题。获胜数字可能包含好运气。论文让我们看到了一条有进步的开发轨迹,但还不足以给出所有外部分布上都成立的优势。
10.2 路径依赖与昂贵的坏想法
作者明确提到,要自主产生真正新颖、可行而且值得做的想法并不容易。早期建议可能影响后续建议,使系统不断围绕同一主题做变体。失败经历虽然进入档案,也不保证下一轮能正确理解,更不保证它会主动探索另一条路。
坏提案的费用不是只花在生成几段文字上。它可能引出很长的开发过程,最后还要跑一轮更贵的测评。因此,“能写代码”只是元改进的一部分,“值得写什么”同样决定了搜索效率。更好的编辑工具可以降低实现成本,却不一定解决提案品位的问题。
这也解释了为什么一次成功长跑不足以描述整个方法。独立重启可能从不同早期建议出发,走向不同结局。如果只展示最顺利的一条轨迹,就很难判断一般情况下要付多少费用才能得到相似收益。论文承认路径依赖,后续研究应当把它转化为多次运行的测量。
10.3 预算定义了我们正在回答的问题
五分钟超时会让一些长程代码题的初始分数偏低,也会放大快速编辑的收益,作者对此有明确讨论。消除紧预算下的瓶颈仍然是正当贡献,只是它回答的是“给定预算内能完成多少”,而不是“无限预算下模型能力上限提高了多少”。
因此,将 SICA 与另一套系统比较时,需要对齐任务集、模型、时间限制和费用目标。一个系统花更多时间拿到更高分,并不直接反驳另一系统在低延迟区间的价值;同样,受限预算下的巨大相对改善,也不能直接外推到其他工作点。
历史美元价格和延迟还会随服务环境变化。本文保留时间、token 和缓存等多个维度,是为了让读者看见这种依赖。不能只看某一列最吸引人的数字,忽略它对应的测量总体与运行条件。
10.4 可观察,不等于所有行为都已得到保证
论文把丰富轨迹和监督器视为有价值的控制手段。它们能帮助人理解发生了什么,但一段易读的记录并不保证所有重要影响都被完整捕获。摘要可能遗漏行为,检查者可能与执行者共享错误假设,可编辑组件也可能改变后续观察的形式。
作者提出,可以把额外的行为评估纳入版本晋级流程。这是合理的扩展方向,但不能据此说论文已经给任意未来修改提供了完整保证。对于当前实验,更准确的描述是一个有边界、成本不低、依赖测评反馈的程序搜索循环。
我认为保持这种比例感很重要。既不能把一次自我编辑夸大成无界的自主能力爆发,也不必因为它没有解决所有问题,就否认它对自动化 agent 工程的实际价值。范围清晰,才有办法判断下一项实验应该测什么。
11. 独立批判性分析:更好的解题者会成为更好的发明者吗?
11.1 递归收益需要一个额外对照
这篇论文让我相信“程序层面的自动改进值得认真研究”。更强的命题是:改善后的 agent 更会改进自己,所以后续搜索也会越来越有效。前者是自动工程的价值,后者是递归反馈的价值。它们相关,但不能靠同一条上升曲线同时证明。
为了把问题讲清楚,我定义一个分析量 :在固定提案预算下,让 agent 负责提出并生成下一版,它带来的独立任务效用增量的期望。写成:
这里不是给 SICA 增加一个它已经测过的指标,而是在明确缺口。论文主要测了候选程序的解题效用 ,尚没有建立“ 越高, 就越高”的普遍关系。更快的补丁工具很可能同时改善两者;过度适配开发题的路由,可能只提高前者,甚至降低后者。

图 9. 本文提出的实验设计,并非论文已完成的结果。固定起点、档案信息和提案预算,对照固定编辑者与随选择变化的编辑者,再看后代在独立任务上的收益和搜索成本。
我希望看到两组搜索:一组让初始编辑 agent 始终不变,但允许被修改的目标程序更新;另一组使用当前改进后的 agent 继续编辑。两组获得相近的历史信息、评估预算和任务,进行多次独立运行。最后既比较后代解题成绩,也比较找到这些后代花了多少次无效尝试和多少资源。
为什么不能只延长原来的运行?因为延长以后仍可能是同一套固定能力在一个丰富空间里继续搜索。必须改变“编辑者是否随版本更新”这个因素,才能更接近递归贡献。论文已经把这个问题具体化,下一步应当沿着这个因果结构设计对照。
11.2 数据效率与经济效率需要分开算
约 7,000 美元是整次搜索的开销,最终每题省下的费用是另一个量。使用表 1 初始和最终的舍入数,每题名义上节省 0.21 美元。若极其简化地假设,搜索的全部价值都只来自这点费用节约,则回本题量为:
这个算例不是部署预测。它忽略了成功率提高的价值、人工工程时间、基础设施开销、真实任务分布和价格变化。它只想说明:用很少的改进轮次找到好程序,不代表总推理成本很低。样本利用充分、迭代次数少与经济上划算,必须分别讨论。
另一个诱人的指标是“每成功修好一题花多少钱”。但不能直接拿跨全部任务平均的费用除以 SWE-bench 分数,因为分子分母来自不同总体。一个可靠的估计需要相同任务分布上的成本与结果,并计入失败、重试和超时。宁可暂时不算,也不要给出一个表面直观、实际混合了不同总体的比值。
真正有用的经济分析还需要区分一次性与持续性支出。发现程序的搜索费可能被大量未来任务摊薄;基础模型变化、API 行为变化或仓库分布变化,又可能要求重新搜索。一个版本是否值得保留,不只由眼前的一次平均费用决定,还取决于它的有效使用寿命。
11.3 档案里应该有不确定性,而不只是成功故事
若两个版本平均分相近,但解决的题完全不同,这个差异可以指导任务路由或组合工具。若两个名字不同的改动总在相同题上失败,它们可能没有带来多少真实多样性。单一分数排序会遮住这些信息。
因此,我希望档案保留任务级变化、预算耗尽方式、涉及语言和仓库类型,并明确区分观察与解释。“某轮费用下降”是观察;“因为缓存策略更好所以费用下降”是需要检验的解释。把两者混写,会让后续 agent 把未经验证的故事当作事实继续优化。
这是一项对未来证据组织方式的建议,不是说论文已经实现了完整的不确定性档案。SICA 已有的轨迹、程序和测评摘要提供了一个很好的起点,因为它至少让这种细粒度诊断成为可能。下一步应该让选择器真正利用这些信息,而不仅仅从中挑一个最高均值。
还要保护所谓“独立评估”。一旦某个留出集的分数反复被用来决定下一项修改,它就已经变成开发反馈。文件名写着 held-out,并不会自动消除适应。最终未参与搜索的任务,以及多次独立搜索轨迹,才能更有力地支持泛化结论。
11.4 我会把哪些原则带进自己的 harness?
第一,保留程序与结果的关联。每个结论都应知道它属于哪个版本、哪组任务、什么预算,避免把不同轮次的最好数字拼接起来。第二,把操作瓶颈变得可观察、可修改。与其先增加复杂角色,不如看当前失败到底卡在定位、编辑、状态、验证还是推理。
第三,把解题能力和改进能力分别对待。一个更高分的版本值得保留,但未必自动值得成为所有后续改动的唯一设计者。第四,在增加协调前,先与简单直接调用比较。推理任务的结果已经提醒我们,层次更多不代表净收益更大。
我不会把论文的权重原封不动移植到每个产品。交互式编码助手与无人值守批处理有不同的延迟要求;一些关键任务不接受以失败换取省时。最低质量约束、多目标保留或不同场景选不同版本,都可能比一个固定加权和更合适。SICA 最值得借鉴的地方,是把这些外层程序选择本身也纳入了可以学习的对象。
12. 结论
SICA 展示了一条具体而有价值的路线:基础模型权重不动,通过阅读历史、修改程序和评估选择,让 agent 的工作方式持续积累改进。主代码实验在选定的 SWE-bench 任务上获得了明显收益,其他任务和资源指标则呈现不同程度、并不单调的变化。把它理解成有限预算下的系统改良,比把它概括成无限递归变强更贴近证据。
真正还没有被完整回答的是,更好的任务求解者是否稳定地成为更好的下一代设计者。要回答这个问题,需要固定与演化编辑者的比较、匹配的搜索预算、多条独立轨迹,以及没有反复指导修改的任务集合。SICA 让这个问题从口号变成了可测量的实验问题,而推理任务改善有限的结果则提醒我们:先找到瓶颈,再决定让哪一层进化。
参考资料与配图来源
- Maxime Robeyns、Martin Szummer、Laurence Aitchison:A Self-Improving Coding Agent,arXiv v2,2025-05-16。本文实验数字、效用规则与方法描述的一手来源;已阅读全文及附录 A-D。
- 论文提供的 SICA 官方代码资源入口。
- Shengran Hu、Cong Lu、Jeff Clune:Automated Design of Agentic Systems。用于理解论文讨论的固定设计者与可变目标 agent 路线,不做跨论文成绩排名。
- Jenny Zhang、Shengran Hu、Cong Lu、Robert Lange、Jeff Clune:Darwin Gödel Machine。作为档案搜索与 agent 演化的相邻阅读,两篇的任务与预算并不相同。
图 1-3、7、9 为 Zhongzhu Zhou 绘制的解释性图示或计算;图 4-6 重绘论文表 1 的舍入值;图 8 引用论文图 4,依据 CC BY 4.0 标注来源。文中的假想候选、回本算例和建议对照均为本文分析,不是论文新增实验或独立复现结果。