LumenNews / 译文 / Continually improving our agent harness · Cursor A · B · C — daily
译文 · Cursor Blog · 2026-04-30 · 收录于 2026-05-07 早报

持续打磨我们的 agent harness · Cursor

译自 Continually improving our agent harness · Cursor · cursor.com

我们对待 Cursor agent harness 的方式,和对待任何一个有野心的软件产品没什么两样。很多工作是愿景驱动的——我们先对理想的 agent 体验有一个判断,然后围绕它形成假设,跑实验来验证,再用 eval 和真实用量的定量、定性信号来迭代。

这个过程依赖完善的线上和线下监测,这样我们才能判断一次改动究竟有没有让 harness 变得更好。

每次拿到新模型的早期访问权限,所有这些方法就会同时上阵。我们会花好几周时间针对模型的优势和特性来定制 harness,直到同一个模型跑在我们精心调校的 harness 里,明显比原版更快、更聪明、更省 token。

偶尔会有跃迁式的突破,但更多时候,harness 的进步是靠一个个小优化叠出来的——每一个单独看起来不起眼,加在一起却能让 agent 在写代码这件事上上一个台阶。

不断演进的 context window

和大语言模型交互的核心是 context window。当你让 agent 去构建某个东西时,context window 里的内容依次是:system prompt 和工具描述、当前对话状态,最后是用户的请求。

我们填充和管理这个窗口的方式,在 Cursor 的发展历程中已经发生了很大变化。

2024 年底我们刚开发出编程 agent 时,模型在自主选择上下文方面还差得远。我们在 context engineering 上下了大力气搭护栏——比如每次编辑后把 lint 和类型报错推给 agent,在它读取的行数太少时重写文件读取请求,甚至限制单次调用工具的最大次数。

那时我们还提供了大量静态上下文,在每个 session 开始时就让 agent 拿到。不同阶段包含过:代码库的目录结构、与查询语义匹配的代码片段、用户手动附加的文件的压缩版本。

现在这些大多都没了。

我们还是保留了一些有用的静态上下文(操作系统、git 状态、当前文件和最近查看的文件)。但随着模型能力的提升,我们逐渐拆掉了那些护栏,转向更多动态上下文——让 agent 在工作过程中自己去拉取。之前我们写过一篇深度文章,介绍动态上下文背后的一些技术,其中不少后来被其他编程 agent 借鉴了。我们现在的很多工作集中在:为 agent 提供更多动态拉取上下文、与外部世界交互的途径。

评估 harness 改动的两种方式

harness 和模型共同决定了 agent 的好坏,但”好”很难精确定义。为了找到它,我们搭建了几层度量体系。

我们维护着公开 benchmark,同时也有自己的 eval 套件 CursorBench,它能快速给出标准化的质量读数,让我们可以跨时间对比。但再好的 benchmark 也只是真实用量的近似,完全依赖它肯定会漏掉重要信号。

所以我们也做线上实验——把两个或多个 harness 变体同时部署,在真实用量上跑 A/B test。评估 agent 质量时我们用了很多指标:延迟、token 效率、工具调用次数、缓存命中率这些都相对直接,方向上有参考价值,但还是回答不了一个更模糊也更重要的问题:agent 到底干得好不好?这个我们用两种方式来衡量。

第一个是 agent 生成代码的”留存率”(Keep Rate)。针对 agent 提出的一批代码改动,我们追踪在固定时间间隔后这些改动还有多少留在用户的代码库里。这帮我们了解用户需要手动调整 agent 输出的频率,或者需要反复迭代让 agent 修复问题——这些都说明 agent 的初始响应质量不够。

第二个是用语言模型去读用户对 agent 初始输出的回复,从语义层面判断用户满不满意。用户直接开始下一个功能,是 agent 完成任务的强信号;用户粘贴一堆报错,则是可靠的失败信号。

有时候线上测试会让我们搁置看起来很有希望的想法。有个实验里,我们用了更贵的模型来做上下文摘要,结果发现对 agent 质量的提升微乎其微,完全不值得那个额外的成本。

追踪和修复劣化

随着支持的模型和能力越来越多,harness 的状态空间也越来越复杂,和任何软件一样,这意味着更大的 bug 暴露面,很多问题只有在规模上才能发现。

agent 的工具是 bug 最集中的地方之一,而工具调用报错对 Cursor 的一次 session 来说破坏性极大。虽然 agent 经常能自我修正,但报错会留在上下文里,不仅浪费 token,还会造成”上下文腐化”——累积的错误会降低模型后续决策的质量。

有时候,一次失败的工具调用会让 agent 彻底卡住或跑偏。工具调用量和出错率这类指标虽然不直接衡量 agent 表现,但能作为指标帮我们发现更深层的问题。

任何未知错误都是 harness 里的 bug,我们会这样对待它。但很多错误是”预期之内”的,比如模型偶尔提出一个不正确的编辑,或者尝试读一个不存在的文件。我们按原因对这些预期错误分类:InvalidArgumentsUnexpectedEnvironment 对应模型犯错和上下文矛盾,ProviderError 对应 GenerateImageWebSearch 这类工具的供应商故障。

此外还有 UserAbortedTimeout 等几个分类,一起覆盖了大多数预期错误。

我们基于这些指标配置了告警,来捕捉进入生产的重大劣化。由于未知错误必然是 bug,一旦任何工具的未知错误率超过固定阈值就会触发告警。但对于预期错误,要判断它是 harness 的 bug 还是正常行为就比较麻烦。

比如 grep 搜索超时,可能是工具性能问题,也可能只是代码库太大、模型构造了一个低效的查询。为此,我们做了异常检测告警——当预期错误显著超过基线时触发。基线是按工具和模型分别计算的,因为不同模型出错率本来就不一样。

我们还跑了一个每周执行的 Automation,配备了一个教会模型搜索日志的 skill,让它自动找出新出现或近期激增的问题,然后在 backlog 里创建或更新 ticket 并附上排查思路。我们大量借助 Cloud Agents 同时启动对多个问题的修复,甚至可以直接从 Linear 触发

这是我们在 agent harness 上构建自动化”软件工厂”的一部分。在今年初的一次专项冲刺中,我们把未知工具调用错误降低了一个数量级。

针对不同模型定制 harness

我们所有的 harness 抽象都是模型无关的,可以针对每个支持的模型深度定制。举个例子,OpenAI 的模型在训练时用的是基于 patch 的文件编辑格式,而 Anthropic 的模型用的是字符串替换。两种模型都能用对方的工具,但用不熟悉的格式会额外消耗推理 token,出错也更多。所以在我们的 harness 里,每个模型拿到的是它在训练时用过的那种工具格式。

这种定制化非常深入,包括针对不同供应商甚至不同模型版本的自定义 prompt。OpenAI 的模型倾向于更字面、更精确地遵循指令,而 Claude 更偏直觉,对不够精确的指令容忍度更高。

拿到新模型的早期访问权限后,我们会从最接近的现有模型 harness 出发,开始迭代。我们跑离线 eval 找出模型困惑的地方,让团队成员实际使用并反馈问题,再针对性地调整 harness。如此循环,直到我们对这个模型和 harness 的组合有足够信心再发布。

大部分调优工作是让 harness 适配新模型的优势,但有时候我们会碰到真正的模型怪癖,可以用 harness 来缓解。比如我们曾观察到某个模型出现了我们称之为”上下文焦虑”的行为:随着 context window 越填越满,它开始拒绝工作,找借口说任务太大了。我们通过调整 prompt 成功减轻了这个现象。

支持对话中途切换模型

要让 harness 支持用户在对话中途切换模型尤其棘手,因为不同模型有不同的行为、prompt 和工具形态。

用户切换模型时,Cursor 会自动切到对应的 harness,带上那个模型专属的 prompt 和工具集。但模型还是要把这些工具用在一段由另一个模型产生的、偏离其训练分布的对话历史上。

为此,我们加了自定义指令,告知模型它是在对话中途接手另一个模型的工作,同时引导它不要调用那些出现在历史记录中但不在自己工具集里的工具。

第二个挑战是缓存是按供应商和模型隔离的,所以切换意味着缓存未命中,第一轮响应会更慢、更贵。我们尝试过在切换时对对话做摘要来缓解这个问题,给新模型一个干净的摘要来降低缓存惩罚。但如果用户已经深入到一个复杂任务中,摘要可能会丢失重要细节。我们通常建议,除非有充分理由,否则在一次对话里坚持用同一个模型。

另一个绕开中途切换难题的方式,是改用 subagent——它从一个全新的 context window 开始。我们最近在 harness 里加入了让用户直接指定用特定模型运行 subagent 的能力。

Harness 与软件开发的未来

AI 辅助软件工程的未来是多 agent 的。与其把每个子任务都压给单个 agent,系统会学会把工作分发给专门化的 agent 和 subagent:一个负责规划,一个负责快速编辑,一个负责调试,各司其职。

要让这套体系运转良好,本质上是 harness 的挑战。系统需要知道派哪个 agent、怎么把任务包装成适合那个 agent 发挥的形式,以及怎么把各方结果拼接成一个连贯的工作流。这种协调编排能力会住在 harness 里,而不是任何单个 agent 里。这意味着 harness engineering 一直以来对 agent 成功都至关重要,而往后只会越来越关键。