Cursor Blog
精选
55AI 编辑部评分,满分 100

持续优化智能体工具链:上下文演进与效果评估

2026-04-30 20:00· 97天前· Stefan Heule & Jediah Katz
AI 导读

Cursor团队以构建软件产品的方式迭代优化其智能体工具链,核心围绕上下文窗口的演进。早期模型能力有限,工具链依赖大量静态上下文和防护机制;随着模型能力提升,团队已转向提供更多动态上下文获取方式并移除限制。评估改进效果采用线上线下结合:通过CursorBench等基准测试进行标准化质量评估,同时进行线上A/B测试,使用“代码保留率”和用户反馈语义分析衡量真实场景表现。团队持续监控并修复工具调用错误,以应对日益复杂的工具链状态。

推荐理由

Cursor 这篇 agent harness 复盘是今年聊 agent 基础设施最好的文章之一,从上下文管理到多 agent 调度,全是实战迭代的血泪经验,做 agent 的团队该逐字读。

正文 · AI 翻译
视频封面视频 · 前往原文观看

我们构建 Cursor 智能体框架的方式,与打造任何雄心勃勃的软件产品如出一辙。大部分工作由愿景驱动——我们首先对理想的智能体体验应该是什么样形成自己的判断。

在此基础上,我们提出如何更接近这一愿景的假设,通过实验进行验证,并利用来自评测和实际使用中的定量与定性信号进行迭代。这个过程依赖于拥有合适的在线和离线检测手段,以便我们能够判断某项改动是否真正改进了框架。

当我们提前获得新模型的访问权限时,所有这些方法都会汇聚在一起。我们会花费数周时间,根据模型的优势和特性来定制我们的框架,直到经过我们特别调校的框架中的同一模型,在速度、智能和效率上都有显著提升。

偶尔,我们会发现阶跃性的改进。但更多时候,改进框架靠的是痴迷地堆叠微小的优化,这些优化累积起来,让智能体在构建软件方面变得更强。

上下文窗口的演进

与大语言模型交互的核心在于上下文窗口。当要求智能体构建某些内容时,上下文窗口从系统提示词和工具描述开始,接着是对话的当前状态,最后是用户的请求。

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

当我们在 2024 年底首次开发编程智能体时,模型自主选择上下文的能力要差得多,我们投入了大量上下文工程工作来创建护栏——例如,在每次编辑后向智能体展示 lint 和类型错误,当它请求的行数太少时重写其文件读取,甚至限制它单轮调用工具的最大数量。

我们还提供了大量静态上下文,这些上下文在每个会话开始时始终可供智能体使用。在不同阶段,这包括代码库的文件夹结构、与查询语义匹配的代码片段,以及用户手动附加的文件的压缩版本。

这些做法如今大多已不复存在。

我们仍然会包含一些有用的静态上下文(例如操作系统、git 状态、当前及最近查看过的文件)。但我们已经适应了不断增强的模型能力,方法是拆除护栏并提供更多动态上下文,让智能体在工作过程中可以获取这些信息。在之前的一篇文章中,我们深入探讨了动态上下文背后的一些技术,其中许多已被其他编码智能体所采用。我们目前的大部分工作都集中在为智能体提供更多动态获取上下文并与世界交互的方式上。

评估框架变更的两种方式

框架和模型共同决定了智能体的优劣,但“优劣”很难界定。为了找到这个标准,我们构建了多层测量体系。

我们在维护公开基准测试的同时,也拥有自己的评估套件 CursorBench,这能让我们快速、标准化地了解质量水平,并能够进行跨时间维度的比较。但即使是最好的基准测试也只能近似反映真实使用情况,这意味着如果我们完全依赖它们,就会错过重要的信号。

因此,我们还会进行在线实验,同时部署两个或更多框架变体,并在真实使用场景中对它们进行 A/B 测试。在这些测试中,我们通过多种指标来衡量智能体的质量。有些指标很直观,比如延迟、模型 token 效率、工具调用次数和缓存命中率。这些指标在方向上是有用的,但仍然无法触及那些更模糊、更重要的问题——智能体是否真的完成了出色的工作。我们通过两种方式来衡量这些。

第一种是智能体生成代码的“保留率”。对于智能体提出的一组特定代码更改,我们会追踪在固定时间间隔后,这些更改中有多少仍保留在用户的代码库中。这让我们能够了解用户何时需要手动调整智能体的输出,或者需要反复迭代让智能体修复问题,这表明智能体的初始响应质量较低。

其次,我们使用一个语言模型来读取用户对智能体初始输出的回复,从而在语义上判断用户是否满意。用户转而处理下一个功能,是智能体完成工作的强烈信号;而用户粘贴一段堆栈跟踪信息,则是智能体未能完成工作的可靠信号。

有时这些在线测试会告诉我们,某个看似有前景的想法应该搁置。在一次实验中,我们尝试用更昂贵的模型进行上下文摘要,结果发现它对智能体质量的影响微乎其微,根本不值得付出更高的成本。

追踪与修复性能退化

随着我们加入更多模型和功能,测试框架也像任何软件一样变得愈发复杂,潜在状态也更多。随之而来的是更多可能出现漏洞的环节,其中许多问题只有在规模化运行时才能被发现。

智能体的工具是漏洞最常出现的区域之一,而工具调用错误对 Cursor 中的会话可能造成极大损害。虽然智能体通常能自行纠正,但错误仍会保留在上下文中,浪费模型 token 并导致“上下文腐败”——即累积的错误会降低模型后续决策的质量。

有时,智能体在工具调用失败后可能被阻塞,或完全偏离正轨。尽管工具调用量和错误率等指标并不能直接衡量智能体是否表现良好,但它们可以作为指示器,指向更广泛的问题。

任何未知错误都代表测试框架中存在漏洞,我们会据此处理。但许多错误是“预期内的”,例如模型偶尔提出错误的编辑,或试图读取一个不存在的文件。我们按原因对这些预期错误进行分类。InvalidArguments 和 UnexpectedEnvironment 捕获模型在上下文窗口中的错误和矛盾,而 ProviderError 则捕获 GenerateImage 或 WebSearch 等工具出现的供应商故障。

我们还有其他几类分类,如 UserAborted 和 Timeout,它们共同涵盖了大多数预期错误。

我们根据这些指标定义告警,以捕获进入生产环境的重大性能退化。由于未知错误始终是漏洞,因此只要任何工具的未知错误率超过固定阈值,我们就会触发告警。但要判断预期错误究竟代表测试框架中的漏洞还是预期行为,则可能相当棘手。

例如,grep 搜索超时可能是由于工具本身的性能问题,也可能是代码库过于庞大,导致模型生成了低效的查询。为此,我们设置了异常检测告警,当预期错误显著超过基线时便会触发。我们会按工具和模型分别计算基线,因为不同模型调用工具时出错的频率可能不同。

我们还每周运行一次自动化流程,配备一项技能,让模型学会如何搜索我们的日志、发现新出现或近期激增的问题,并在待办事项中创建或更新工单以进行调查。我们大量依赖 Cloud Agents 来同时启动多个问题的修复,甚至可以直接从 Linear 触发它们。

这一流程是我们为智能体框架构建自动化“软件工厂”的一部分。在今年早些时候的一次集中冲刺中,我们将意外的工具调用错误降低了整整一个数量级。

针对不同模型定制框架

我们所有的框架抽象都是模型无关的,并且可以针对我们支持的每个模型进行深度定制。例如,OpenAI 的模型经过训练,使用基于补丁的格式编辑文件,而 Anthropic 的模型则经过字符串替换的训练。两种模型都可以使用对方的工具,但使用不熟悉的工具会消耗额外的推理 token,并产生更多错误。因此,在我们的框架中,我们会为每个模型配备其在训练期间使用的工具格式。

这种定制非常深入,包括针对不同提供商甚至不同模型版本的定制提示词。OpenAI 的模型在遵循指令方面往往更字面化、更精确,而 Claude 则更直观一些,对不精确指令的容忍度也更高。

当我们在新模型发布前获得早期访问权限时,我们会从最接近的现有模型框架开始,并进行迭代。我们运行离线评估来找出模型容易混淆的地方,让团队成员使用它并反馈问题,然后相应调整框架。我们这样反复迭代,直到得到一个我们认为可以放心发布的模型-框架组合。

这种调优过程很大程度上是为了根据新模型的优势来定制适配层,但有时我们也会遇到真正的模型怪癖,并可以通过适配层来缓解。例如,我们观察到某个模型出现了一种我们称之为“上下文焦虑”的现象:随着其上下文窗口被填满,它会开始拒绝工作,推脱说任务似乎太大了。我们通过调整提示词成功减少了这种行为。

支持在对话中途切换模型

设计适配层以支持用户在对话中途切换模型尤其棘手,因为不同模型有不同的行为、提示词和工具形态。

当用户切换模型时,Cursor 会自动切换到相应的适配层,并应用该模型定制的一套提示词和工具。然而,模型仍然需要将这些工具应用于由另一个模型产生的对话历史,而这部分历史数据分布与它训练时所接触的数据分布是不同的。

为了解决这个问题,我们添加了自定义指令,告知模型它正在对话中途接替另一个模型。这些指令还会引导它不要调用对话历史中出现但并非其自身工具集一部分的工具。

第二个挑战是,缓存是特定于提供商和模型的,因此切换模型意味着缓存未命中,导致首次交互更慢、成本更高。我们尝试通过在切换时对对话进行摘要来缓解这个问题,这为模型提供了一个干净的摘要,从而减少了缓存惩罚。但如果用户正深入处理一个复杂任务,摘要可能会丢失重要的细节。我们通常建议在单次对话期间坚持使用同一个模型,除非你有理由进行切换。

另一种规避对话中途模型切换挑战的方法是改用子智能体,它会从一个全新的上下文窗口开始。我们最近在适配层中增加了功能,允许用户直接请求使用特定模型来运行一个子智能体。

适配层与软件开发的未来

AI 辅助软件工程的未来将是多智能体协同。系统不会通过单一智能体运行每一个子任务,而是学会将任务分派给专门的智能体和子智能体:一个负责规划,另一个负责快速编辑,第三个负责调试,每个智能体都专注于自己最擅长的领域。

要让这套机制良好运转,本质上是一个编排层(harness)的挑战。系统需要知道该分派哪个智能体,如何根据该智能体的优势来构建任务,以及如何将结果整合成一个连贯的工作流程。这种协调编排的能力将存在于编排层中,而非任何单一智能体。这意味着,尽管编排层工程对于智能体的成功一直很重要,但未来它将变得更加关键。

我们在构建云端智能体过程中学到的东西

Josh Ma

更优秀的 AI 模型能够支撑更具雄心的任务

Luke Melas-Kyriazi

通过实时强化学习改进 Composer

Jacob, Ben, Nathan & Wanqi

来源:Cursor Blog · cursor.com

持续优化智能体工具链:上下文演进与效果评估

Cursor Blog·2026-04-30 20:00·97天前·Stefan Heule & Jediah Katz
AI 导读

Cursor团队以构建软件产品的方式迭代优化其智能体工具链,核心围绕上下文窗口的演进。早期模型能力有限,工具链依赖大量静态上下文和防护机制;随着模型能力提升,团队已转向提供更多动态上下文获取方式并移除限制。评估改进效果采用线上线下结合:通过CursorBench等基准测试进行标准化质量评估,同时进行线上A/B测试,使用“代码保留率”和用户反馈语义分析衡量真实场景表现。团队持续监控并修复工具调用错误,以应对日益复杂的工具链状态。

正文 · AI 翻译
视频封面视频 · 前往原文观看

我们构建 Cursor 智能体框架的方式,与打造任何雄心勃勃的软件产品如出一辙。大部分工作由愿景驱动——我们首先对理想的智能体体验应该是什么样形成自己的判断。

在此基础上,我们提出如何更接近这一愿景的假设,通过实验进行验证,并利用来自评测和实际使用中的定量与定性信号进行迭代。这个过程依赖于拥有合适的在线和离线检测手段,以便我们能够判断某项改动是否真正改进了框架。

当我们提前获得新模型的访问权限时,所有这些方法都会汇聚在一起。我们会花费数周时间,根据模型的优势和特性来定制我们的框架,直到经过我们特别调校的框架中的同一模型,在速度、智能和效率上都有显著提升。

偶尔,我们会发现阶跃性的改进。但更多时候,改进框架靠的是痴迷地堆叠微小的优化,这些优化累积起来,让智能体在构建软件方面变得更强。

上下文窗口的演进

与大语言模型交互的核心在于上下文窗口。当要求智能体构建某些内容时,上下文窗口从系统提示词和工具描述开始,接着是对话的当前状态,最后是用户的请求。

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

当我们在 2024 年底首次开发编程智能体时,模型自主选择上下文的能力要差得多,我们投入了大量上下文工程工作来创建护栏——例如,在每次编辑后向智能体展示 lint 和类型错误,当它请求的行数太少时重写其文件读取,甚至限制它单轮调用工具的最大数量。

我们还提供了大量静态上下文,这些上下文在每个会话开始时始终可供智能体使用。在不同阶段,这包括代码库的文件夹结构、与查询语义匹配的代码片段,以及用户手动附加的文件的压缩版本。

这些做法如今大多已不复存在。

我们仍然会包含一些有用的静态上下文(例如操作系统、git 状态、当前及最近查看过的文件)。但我们已经适应了不断增强的模型能力,方法是拆除护栏并提供更多动态上下文,让智能体在工作过程中可以获取这些信息。在之前的一篇文章中,我们深入探讨了动态上下文背后的一些技术,其中许多已被其他编码智能体所采用。我们目前的大部分工作都集中在为智能体提供更多动态获取上下文并与世界交互的方式上。

评估框架变更的两种方式

框架和模型共同决定了智能体的优劣,但“优劣”很难界定。为了找到这个标准,我们构建了多层测量体系。

我们在维护公开基准测试的同时,也拥有自己的评估套件 CursorBench,这能让我们快速、标准化地了解质量水平,并能够进行跨时间维度的比较。但即使是最好的基准测试也只能近似反映真实使用情况,这意味着如果我们完全依赖它们,就会错过重要的信号。

因此,我们还会进行在线实验,同时部署两个或更多框架变体,并在真实使用场景中对它们进行 A/B 测试。在这些测试中,我们通过多种指标来衡量智能体的质量。有些指标很直观,比如延迟、模型 token 效率、工具调用次数和缓存命中率。这些指标在方向上是有用的,但仍然无法触及那些更模糊、更重要的问题——智能体是否真的完成了出色的工作。我们通过两种方式来衡量这些。

第一种是智能体生成代码的“保留率”。对于智能体提出的一组特定代码更改,我们会追踪在固定时间间隔后,这些更改中有多少仍保留在用户的代码库中。这让我们能够了解用户何时需要手动调整智能体的输出,或者需要反复迭代让智能体修复问题,这表明智能体的初始响应质量较低。

其次,我们使用一个语言模型来读取用户对智能体初始输出的回复,从而在语义上判断用户是否满意。用户转而处理下一个功能,是智能体完成工作的强烈信号;而用户粘贴一段堆栈跟踪信息,则是智能体未能完成工作的可靠信号。

有时这些在线测试会告诉我们,某个看似有前景的想法应该搁置。在一次实验中,我们尝试用更昂贵的模型进行上下文摘要,结果发现它对智能体质量的影响微乎其微,根本不值得付出更高的成本。

追踪与修复性能退化

随着我们加入更多模型和功能,测试框架也像任何软件一样变得愈发复杂,潜在状态也更多。随之而来的是更多可能出现漏洞的环节,其中许多问题只有在规模化运行时才能被发现。

智能体的工具是漏洞最常出现的区域之一,而工具调用错误对 Cursor 中的会话可能造成极大损害。虽然智能体通常能自行纠正,但错误仍会保留在上下文中,浪费模型 token 并导致“上下文腐败”——即累积的错误会降低模型后续决策的质量。

有时,智能体在工具调用失败后可能被阻塞,或完全偏离正轨。尽管工具调用量和错误率等指标并不能直接衡量智能体是否表现良好,但它们可以作为指示器,指向更广泛的问题。

任何未知错误都代表测试框架中存在漏洞,我们会据此处理。但许多错误是“预期内的”,例如模型偶尔提出错误的编辑,或试图读取一个不存在的文件。我们按原因对这些预期错误进行分类。InvalidArguments 和 UnexpectedEnvironment 捕获模型在上下文窗口中的错误和矛盾,而 ProviderError 则捕获 GenerateImage 或 WebSearch 等工具出现的供应商故障。

我们还有其他几类分类,如 UserAborted 和 Timeout,它们共同涵盖了大多数预期错误。

我们根据这些指标定义告警,以捕获进入生产环境的重大性能退化。由于未知错误始终是漏洞,因此只要任何工具的未知错误率超过固定阈值,我们就会触发告警。但要判断预期错误究竟代表测试框架中的漏洞还是预期行为,则可能相当棘手。

例如,grep 搜索超时可能是由于工具本身的性能问题,也可能是代码库过于庞大,导致模型生成了低效的查询。为此,我们设置了异常检测告警,当预期错误显著超过基线时便会触发。我们会按工具和模型分别计算基线,因为不同模型调用工具时出错的频率可能不同。

我们还每周运行一次自动化流程,配备一项技能,让模型学会如何搜索我们的日志、发现新出现或近期激增的问题,并在待办事项中创建或更新工单以进行调查。我们大量依赖 Cloud Agents 来同时启动多个问题的修复,甚至可以直接从 Linear 触发它们。

这一流程是我们为智能体框架构建自动化“软件工厂”的一部分。在今年早些时候的一次集中冲刺中,我们将意外的工具调用错误降低了整整一个数量级。

针对不同模型定制框架

我们所有的框架抽象都是模型无关的,并且可以针对我们支持的每个模型进行深度定制。例如,OpenAI 的模型经过训练,使用基于补丁的格式编辑文件,而 Anthropic 的模型则经过字符串替换的训练。两种模型都可以使用对方的工具,但使用不熟悉的工具会消耗额外的推理 token,并产生更多错误。因此,在我们的框架中,我们会为每个模型配备其在训练期间使用的工具格式。

这种定制非常深入,包括针对不同提供商甚至不同模型版本的定制提示词。OpenAI 的模型在遵循指令方面往往更字面化、更精确,而 Claude 则更直观一些,对不精确指令的容忍度也更高。

当我们在新模型发布前获得早期访问权限时,我们会从最接近的现有模型框架开始,并进行迭代。我们运行离线评估来找出模型容易混淆的地方,让团队成员使用它并反馈问题,然后相应调整框架。我们这样反复迭代,直到得到一个我们认为可以放心发布的模型-框架组合。

这种调优过程很大程度上是为了根据新模型的优势来定制适配层,但有时我们也会遇到真正的模型怪癖,并可以通过适配层来缓解。例如,我们观察到某个模型出现了一种我们称之为“上下文焦虑”的现象:随着其上下文窗口被填满,它会开始拒绝工作,推脱说任务似乎太大了。我们通过调整提示词成功减少了这种行为。

支持在对话中途切换模型

设计适配层以支持用户在对话中途切换模型尤其棘手,因为不同模型有不同的行为、提示词和工具形态。

当用户切换模型时,Cursor 会自动切换到相应的适配层,并应用该模型定制的一套提示词和工具。然而,模型仍然需要将这些工具应用于由另一个模型产生的对话历史,而这部分历史数据分布与它训练时所接触的数据分布是不同的。

为了解决这个问题,我们添加了自定义指令,告知模型它正在对话中途接替另一个模型。这些指令还会引导它不要调用对话历史中出现但并非其自身工具集一部分的工具。

第二个挑战是,缓存是特定于提供商和模型的,因此切换模型意味着缓存未命中,导致首次交互更慢、成本更高。我们尝试通过在切换时对对话进行摘要来缓解这个问题,这为模型提供了一个干净的摘要,从而减少了缓存惩罚。但如果用户正深入处理一个复杂任务,摘要可能会丢失重要的细节。我们通常建议在单次对话期间坚持使用同一个模型,除非你有理由进行切换。

另一种规避对话中途模型切换挑战的方法是改用子智能体,它会从一个全新的上下文窗口开始。我们最近在适配层中增加了功能,允许用户直接请求使用特定模型来运行一个子智能体。

适配层与软件开发的未来

AI 辅助软件工程的未来将是多智能体协同。系统不会通过单一智能体运行每一个子任务,而是学会将任务分派给专门的智能体和子智能体:一个负责规划,另一个负责快速编辑,第三个负责调试,每个智能体都专注于自己最擅长的领域。

要让这套机制良好运转,本质上是一个编排层(harness)的挑战。系统需要知道该分派哪个智能体,如何根据该智能体的优势来构建任务,以及如何将结果整合成一个连贯的工作流程。这种协调编排的能力将存在于编排层中,而非任何单一智能体。这意味着,尽管编排层工程对于智能体的成功一直很重要,但未来它将变得更加关键。

我们在构建云端智能体过程中学到的东西

Josh Ma

更优秀的 AI 模型能够支撑更具雄心的任务

Luke Melas-Kyriazi

通过实时强化学习改进 Composer

Jacob, Ben, Nathan & Wanqi

来源:Cursor Blog· cursor.com