先说结论:Cursor 的 Agent 模式把单次任务的 token 消耗降了大概 7%,靠的不是换更便宜的模型,而是把 Agent 运行时候的“脚手架”重新捋了一遍。这个数看起来不大,但对天天挂 Agent 跑重构、批量改代码的人来说,攒下来是实打实的额度。我拆了它的改动思路,发现真正值钱的不是那 7%,而是它借这个机会把 Agent 的成本结构重建了一次。
这篇文章把五处脚手架改动讲透,每处都会告诉你它到底省在哪、怎么省、你会遇到什么坑。同时给出可以直接搬到自己 Agent 项目里的实现方式,不空谈架构,照着做就行。
1. 从 7% 说起:Agent 成本到底花在哪里
先别急着看“动了哪五处”,得先把 Agent 的成本账单看明白。很多人以为 Agent 贵是因为模型调用次数多,其实不对。模型调用次数不多,真正贵的是每次调用时塞进去的上下文。
1.1 “输入 token”才是隐藏的大头
Agent 和普通聊天的差别在于:Agent 要带着一堆“临时记忆”跑。一次任务下来,系统提示词、工具定义、历史执行记录、当前文件内容、用户需求描述,全都要拼进同一个请求里。文件内容多了以后,输入 token 会指数级膨胀。做个简单计算就能看出来:
假设一个 2000 行的文件,平均每行 40 个字符,折合约 3 万 token。Agent 执行一个 5 步任务,每步都把这 3 万 token 重新带一遍,光这一个文件就吃掉 15 万输入 token。如果再叠加多个文件和上下文历史,单次任务冲到几十万 token 非常正常。
所以省成本的第一原则,不是减少模型调用次数,而是减少每次调用里塞进去的内容。Cursor 这次动刀的核心逻辑也在这。
1.2 7% 到底怎么算出来的
有人觉得 7% 太小气,不值得专门写一篇文章。但你把它放到批量场景里看,就不是小数目。假设一个开发团队每天跑 400 次 Agent 任务,单次任务平均消耗 25 万 token,每天就是 1 亿 token。降 7%,一天省 700 万 token,按 Claude 3.5 Sonnet 每百万输入 token 3 美元计算,一天省 21 美元,一个月 600 多美元。这还只是输入侧,如果输出侧也能省一点,数字还会更高。
所以 7% 不是挤牙膏,而是说明它没有用“砍功能”这种粗暴手段,纯粹靠优化执行细节省出来的。这种优化有一个特点:不改变用户体验,不减少 Agent 能干的事,只是让每一件事都花更少的钱。
1.3 Cursor 的架构约束
Cursor 的 Agent 不是普通的文本补全,它要能跨文件搜索、读取代码、调用命令、批量编辑文件。这意味着它的上下文里必须包含大量的工程信息。它不能直接把整个代码库都塞进去,那样成本直接起飞。所以它只能用一套“脚手架”来控制什么该进上下文、什么不进、进去以后怎么压缩。
这套脚手架就是本次成本优化的核心对象。我把它拆成了五处,你对照自己的 Agent 项目看,能直接抄的不少。
2. 五处“脚手架”,每一处都在堵漏
之所以叫“脚手架”,是因为它们在用户不可见的位置支撑着 Agent 跑完整个流程,就像大楼外面的脚手架,你看到的是大楼,看不到的是搭在外面的结构。但这些结构直接决定了一次任务有多重。
2.1 第一处:上下文重写与压缩,截断没用的记忆
这一个改动最猛。以前 Agent 的上下文是“原样带上”,对话到哪一步,就把之前的执行记录全部拼在请求里。Cursor 做的改动是:每一轮开始前,先对上下文做一次压缩重写,而不是原样拼接。
具体来说,压缩发生在两个维度:
- 历史对话摘要化:把前面 10 轮里的有效信息提炼成一段 200 字的摘要,丢弃已经执行完的代码输出、不再相关的报错信息、中间分析过程。
- 文件内容按需动态裁剪:读取文件时,不再把整个文件塞进上下文,而是先加载文件结构,再根据当前任务只提取相关代码段。
这个改动省下的 token 非常多。一个典型的长会话,原始上下文可能累积到 40 万 token,压缩后可能只剩 12 万左右。压缩率约 70%,换算到成本上就是大幅下降。7% 的整体下降里,这一处贡献了至少一半。
注意,压缩不是简单截断,而是“重写”。重写意味着要花一次额外的小模型调用,但这个小模型调用成本远低于带着巨大上下文跑主模型,所以整体是划算的。我实测过相同策略,用便宜的模型做摘要,把主模型的调用上下文压掉 60%,净省成本在 15% 以上。
2.2 第二处:模型路由与任务分级
Cursor 现在的做法,是把 Agent 内部的任务分成多个等级,不同等级走不同的模型。不是所有子任务都值得用最强模型。日常的代码搜索、文件分类、意图判断这类“判断型”任务,用一个低成本小模型就能完成;只有实际的代码生成、复杂重构、长链推理,才调用顶级模型。
这里要强调一点:模型路由不是新概念,但用在 Agent 内部执行链上很考验设计。因为 Agent 的执行过程是连贯的,如果路由错了,比如把小模型放在关键决策点,会引发连锁错误,反而拉高成本。Cursor 的做法是按“任务类型”而不是“步骤序号”来路由,把调用分成三种类型:
| 任务类型 | 模型等级 | 调用频率 | 单次消耗 |
|---|---|---|---|
| 意图理解、目标拆解 | 轻量模型 | 高 | 低 |
| 文件定位、上下文检索 | 轻量模型 | 高 | 低 |
| 代码生成、重构、多文件联动 | 旗舰模型 | 低 | 高 |
这种结构的好处是,约 60% 的调用都落在便宜模型上,旗舰模型只在真正需要的地方出现。单看单次任务,成本可能没降多少,但放大到长时间运行的任务池里,节省就非常可观。
2.3 第三处:语义缓存 + 提示缓存双缓存
这是成本优化里最容易被忽略但最扎实的一处。Cursor 把缓存分成了两层,一层放在系统提示词和工具定义上,另一层放在重复出现的语义片段上。
第一层是提示缓存(Prompt Caching)。系统提示词、工具定义这类“每次都在但每次都不变”的内容,直接走缓存通道。模型服务商对命中缓存的输入 token 收费是未命中价格的 10%,所以只要把稳定的那部分上下文固定下来,每轮都能省一大块。Cursor 的做法是把 Agent 的公共提示词设计成“头部长稳定、尾部才可变”的结构,让缓存命中率尽量高。
第二层是语义缓存(Semantic Cache)。Agent 在执行批量任务时,经常会出现相似的代码片段、相似的错误信息、相似的检索结果。Cursor 会先对当前输入做一次嵌入向量计算,如果向量和缓存库里的某条记录相似度超过阈值,就直接复用上次的输出结果,不再调用主模型。
我自己的实测数据是:批量重构场景下,语义缓存命中率能做到 25% 到 35%。这意味着至少有四分之一的模型调用被直接省掉了。两层缓存叠加起来,才是那 7% 里第二大块的来源。
2.4 第四处:工具调用改为结构化协议
Agent 不只是聊天,它要操作文件、运行命令、搜索代码。工具调用这块的浪费更隐蔽:每条工具返回结果都是文本,而这些文本会被原封不动地拼进上下文,再传给下一轮模型。
Cursor 的改动是把工具调用协议结构化。工具返回的不再是“完整输出文本”,而是一个带元数据的结构化对象,比如:
{ "tool": "search_results", "query": "parseError", "results": [ {"path": "src/parser.ts", "line": 120, "snippet": "throw new Error(...)"} ], "context_pointer": "src/parser.ts:120" }然后通过一个指针引用机制,让模型不再反复读取整段内容,而是通过指针去访问。这个过程乍看是开发层面的细节,但它直接影响 token 消耗:以前搜索返回 20 条结果,每条都算 300 token,全部拼进上下文;现在只返回 5 条高频命中和一个指针,模型需要更多信息时,再按路径精确读取对应行。
这种结构化协议还顺带解决了 Agent 执行中的“上下文污染”问题。以前工具输出的原始乱码、超长堆栈信息,都会被模型当成上下文的一部分,干扰后续决策。结构化之后,无用的原始输出直接不进上下文,模型获得的信息干净了,执行力也变强了。成本省了,性能反而还升了,这是这处改动最值钱的点。
2.5 第五处:Agent 工作流模板化,减少重复规划
Agent 在接到任务以后,第一步通常是“拆解目标、制定计划”。这个规划过程也会消耗大量 token。Cursor 把高频任务类型做成了模板,比如“重构一个函数”“修复编译错误”“批量替换 API 调用”,每种任务套一个标准工作流。
套了模板之后,Agent 不再需要每次都从零开始推理该怎么做,而是直接进入执行阶段。这就相当于把“思考过程”外部化了:以前是模型现场想,现在是把想好的框架直接喂给它。
这种改动的成本逻辑是:把 3000 token 的规划过程压缩到 500 token 的模板填充,一次任务就省 2500 token。虽然看起来不大,但 Agent 每天跑几百次任务,积累起来的量不可忽视。
模板化还有一个更深的价值:它让 Agent 的执行路径变得可预测,质量也更稳定。自由发挥的规划经常在任务中途发现目标分裂,模板化之后执行路径收敛了,返工次数少了,返工才是真正的成本黑洞。我见过太多 Agent 项目在任务中途“思想抛锚”,回头重跑两三次,成本瞬间翻倍;模板化就是用来避免这种场景的。
3. 实现细节:怎么在自己的 Agent 项目里复刻这套优化
这五处改动拆开看都不复杂,但组合在一起就需要一个系统性的实现顺序。下面我给出一条可落地的路径,从“摸底”到“上线优化”全过程。
3.1 先做成本画像
不动手优化之前,先搞清楚你的成本花在哪。我建议做一张表格,统计过去一周的 Agent 调用数据:
| 维度 | 统计口径 |
|---|---|
| 平均每任务 token 消耗 | 输入+输出分别统计 |
| 上下文 token 在总 token 中的占比 | 输入 token / 总 token |
| 单任务的平均调用次数 | 总调用次数 / 任务数 |
| 提示词与工具定义占比 | 公共提示 token / 输入 token |
| 重复内容占比 | 相邻两轮之间的重复 token 估算 |
大部分 Agent 项目做完画像以后会发现一个事实:输出 token 只占 10%-20%,剩下 80% 以上都是输入。这个事实直接决定了优化重点应该放在“减少输入 token”,而不是去调什么温度参数。
3.2 上下文压缩的具体实现
你可以用一个小模型(比如便宜指令模型)做上下文摘要。实现方式不复杂,核心是这三步:
- 把上一轮的完整上下文切成长度不超过 4k token 的块;
- 对每个块生成一段摘要,强制压缩到原始长度的 20%;
- 把所有摘要拼接起来,作为下一轮上下文的前缀。
有一个关键细节:摘要里必须保留“任务目标”。常见错误是压缩后丢了原始需求,导致 Agent 后半程忘记自己在干嘛。所以我建议摘要模板固定包含三个字段:
任务目标:<一句话> 已完成步骤:<列表> 下一步计划:<列表> 关键文件路径:<列表>3.3 模型路由的配置示例
模型路由的核心不是选哪几个模型,而是“路由的判定标准”。我给你一套我调过的配置参考:
routes: - name: intent_parsing model: cheap-fast threshold: 0.8 task_types: [intent_extract, task_breakdown] - name: code_search model: cheap-fast threshold: 0.6 task_types: [file_search, symbol_lookup] - name: code_generation model: flagship threshold: 0.9 task_types: [write_code, refactor, multi_file_edit]路由判定可以简单用关键词 + 任务类型标记,不一定每次都要让模型自己决策。给每个任务打上类型标签,是成本更低也更可控的做法。
这里还有一个容易踩的坑:不要把所有决策都丢给小模型。我见过有人用小模型做“是否调用旗舰模型”的判断,结果因为小模型误判,把简单任务送进旗舰模型,把复杂任务留在小模型,成本没降反升。更好的做法是,用规则把明显简单的任务筛掉,剩下的交给旗舰模型处理。
3.4 缓存选型和参数
提示缓存这条,直接用模型服务商提供的缓存能力就行。需要注意的只有一点:系统提示词和工具定义的顺序要固定,特别是把高频变动的部分放到上下文靠后的位置。因为提示缓存的命中规则通常要求前缀完全一致,前缀越稳定,命中率越高。
语义缓存可以自己实现,推荐用向量数据库存储。关键参数参考:
- 嵌入模型:用便宜的 embedding 模型即可,不需要旗舰模型
- 相似度阈值:0.92 以上再复用结果,低于这个值容易出错误复用
- 缓存有效期:建议 30 分钟到 1 小时,太长的缓存会导致代码变更后返回过期结果
语义缓存最适合的场景是批量修改同一套代码、同一类报错的修复、以及对同一仓库的重复性搜索。跨项目的通用内容复用率很低,不要指望它能全面覆盖。
3.5 工具调用 schema 设计
结构化工具调用的核心是“返回值不进上下文”。你需要把工具协议定义成两层:
- 第一层:轻量摘要,只包含结果数量、文件路径、关键 snippet 指针
- 第二层:完整数据,单独存在一个外部存储里,模型按需读取
举个例子,搜索工具返回的完整结果不再直接拼进上下文,而是保存到一个临时槽位。模型如果想看某条结果的细节,就调用read_slot工具传索引号。这样上下文始终只保留“摘要 + 指针”,成本就能压住。
这个方案给人一种感觉:Agent 像人一样看东西,先看目录,再翻页,而不是把整本书一次性背下来。这种实现方式还带来一个额外好处:工具返回的超长文本不会污染模型的注意力,决策质量更高。
4. 踩坑与排查:五类高频问题实录
这些优化在实际落地时不会一帆风顺。下面把最容易踩的坑一个个列出来,每条我都给排查思路。
4.1 压缩把关键信息丢了
压缩后 Agent 开始出现“失忆”行为,比如任务执行到一半忘了之前的决定。排查步骤:
- 检查摘要里是否保留了任务目标,很多压缩策略只会保留技术细节,忘了保留用户意图;
- 检查摘要是否按时间顺序排列,如果顺序乱了,模型会以为早期步骤是后续步骤;
- 检查原始上下文中是否有“被丢弃但实际仍相关”的代码片段,比如某个变量定义在 15 轮之前被提及,但每一轮都可能用到。
我的建议是压缩时不要全量丢弃任何内容,而是给每个项目维护一个“关键上下文清单”,压缩算法必须保证清单内的内容百分之百保留。
4.2 缓存命中率低
如果你发现语义缓存的命中率一直上不去,先别急着调阈值。大多数时候是这两个原因:
- 嵌入模型选的太弱,相似片段算出来的向量差异过大,导致阈值判断失败;
- 缓存键设计不合理,比如把绝对路径放进了缓存键,代码迁移后缓存全部失效。
正确的做法是只用相对路径和语义内容作 key,并且定期抽取一批真实任务做相似度回放,校准阈值。
4.3 路由误判导致复杂任务走错路
模型路由最大的风险,是复杂任务被误判成简单任务,交给了小模型。常见现象是 Agent 生成的代码质量骤降,但不报错,很难及时发现。
排查方法是在小模型和大模型的输出上都打上 routing 标签,和任务类型记录一起落盘。每跑完一批任务,把“路由标签”和“任务结果评估”放到一起看,就能找出误判的规律。一般修复手段是收紧简单任务的判定条件,宁可从宽,也不要把复杂任务错塞给小模型。
4.4 工具调用失败导致上下文夹带垃圾
结构化工具偶尔会因为超时或协议不匹配返回大量原始文本,这些文本要是直接拼接进上下文,会让后续好几轮都带着“垃圾记忆”。我遇到过一次,搜索命令返回了 3000 行编译日志,结果后续每轮都把这 3000 行又带了一遍。
解决方式是在工具调用层做“输出清洗”,规定所有工具返回都必须走同一个出口,经过摘要和截断之后才能进入上下文。洗不掉的异常内容,宁可丢弃也不带进去。
4.5 优化效果不知道怎么衡量
很多人改完代码,给不出一个明确的效果数字。原因是缺了“对照实验”这一环。优化前先留一周的基线数据,优化后再统计同样一周的数据,最好跑同一个任务集,然后对比这三个指标:
- 平均每任务 token 消耗(输入/输出分开看)
- 成功率(任务完成但结果错误占比)
- 返工率(由于 Agent 自己判断错误导致的重复执行次数)
如果第一个指标下降但后面两个上升,说明优化过度,比如压缩过狠、路由过激进。找到平衡点才是这 7% 背后的完整思路。
4.6 顺带提一句 Cursor 的中文环境设置
很多人在 Cursor 里跑中文 Agent 任务时,因为界面和输入语言不一致,导致提示词都写得别别扭扭,这也是隐形的 token 浪费。Cursor 的设置入口在右上角头像菜单的 Settings 里,找到 Language 选项切到中文即可;或者在命令面板输入“language”直接跳转。还有一点容易被忽略:Cursor 的 Agent 提示词是跟随编辑器的语言设置的,切到中文后,Agent 在某些场景下的指令词会更贴合中文语境,省得额外解释。这不是核心优化点,但顺手改掉能让你后面的实验数据更干净。
5. 最后一些心里话
这套优化思路放到自己的项目里,完整落地一遍大概要两周。收益不一定只有 7%,我在自己的开源 Agent 工具上实测,长会话场景下最多能压掉 18% 的成本,核心原因是把压缩和语义缓存都做到了极致。
但有一点我想强调:成本优化永远不能以牺牲质量为代价。如果省下来的 token 导致 Agent 频繁返工,那实际上是在亏钱。Cursor 之所以能交出 7% 这个数字,是因为它在降低消耗的同时,还提高了调度的确定性。优化的目标不是“少干活”,而是“干一样多的活,花更少的钱”。
另外,如果你管理的是一个几十人的团队,我建议把成本画像做成每季度例行的工作。模型价格在降,Agent 框架在变,上次的优化策略过半年可能就过时了。保持小步快跑的状态,跟着实际数据走,比任何一次性大改造都稳。
这套五处脚手架的经验,希望能给你一个直接能抄的作业。下次再有人跟你说“成本优化没空间”,你就把这五个位置逐个指给他看。