很多开发者发现,AI 编程 Agent 的消耗并不完全取决于任务难度。一个看似简单的改动,如果让 Agent 反复读取项目说明、重复查看同一批文件、接收过大的命令输出,或者在几个无效步骤之间来回循环,Token 很快就会被消耗掉。Spotify 工程团队公开的 Portal 案例提供了一个值得参考的切入点:降低成本的重点,不是单纯更换模型,而是让每一轮调用都携带更少、更准确、能直接推动任务前进的上下文。
AI 编程 Agent 每次请求模型时,通常会组合多类信息:系统指令、当前任务、对话历史、项目规则、代码片段、工具调用记录,以及命令执行后的结果。上下文越长,输入端需要处理的内容越多;如果这些内容在多轮调用中反复出现,消耗就会持续累积。
问题在于,Agent 并不会因为“看过一次”就永远不需要再次处理。只要一轮调用重新携带了相同的项目文档、历史对话或工具返回结果,它们就可能再次进入模型的输入。长会话因此容易形成一种隐性浪费:每一轮新增的信息并不多,但旧信息不断被重复计算。
这也是为什么“支持更长上下文”不能直接等同于“可以把所有内容都塞进去”。上下文中如果混杂了过期方案、重复日志和无关文件,真正有用的线索反而更难被识别。优化的目标不是让 Agent 知道更多,而是让它在当前步骤知道刚好够用的信息。
项目说明、开发约定和目录规则对 Agent 很重要,但把所有内容长期放在每次请求的固定上下文中,未必是好办法。
常见问题包括:
更合理的做法是把规则分成“始终需要知道”和“执行特定任务时才需要知道”两类。代码风格、测试要求、提交规范等高频规则可以保持简洁;某个模块的特殊约束,则应尽量在进入该模块时再提供。
不要把文档写成面面俱到的团队手册,然后期待 Agent 每次都能准确提取重点。对 Agent 来说,短而明确的规则通常比长而完整的背景说明更容易执行。
工具调用本身未必昂贵,真正容易造成浪费的是工具返回的内容。比如一次搜索返回大量文件,一条命令输出完整日志,一次测试执行附带许多与当前错误无关的内容。Agent 接收到这些结果后,可能还会在下一轮继续携带它们。
工具结果最好服务于一个明确判断,而不是追求“把所有信息都返回”。如果当前任务只是确认某个函数是否被调用,就不必把整个项目或完整日志交给 Agent;如果只需要定位失败原因,也不必保留大量已经确认无关的成功输出。
可以优先采用这些处理方式:
这里的关键不是盲目裁剪,而是保留能够支持下一步决策的信息。过度压缩也会导致 Agent 缺少判断依据,随后通过更多调用补齐信息,反而增加总消耗。
Agent 的成本还会被“没有推进任务”的调用放大。例如,它先后多次检查同一个目录,重复确认已经知道的环境状态,或者在修改失败后不断尝试相似方案,却没有重新分析失败原因。
判断一轮调用是否有效,可以问三个问题:
如果三个问题的答案都是否,这一轮很可能只是上下文噪声。尤其是在自动循环中,工具调用失败、结果为空或格式异常,都可能让 Agent 重试同一动作。此时需要设置清晰的停止条件,或者让 Agent 在重复失败后先总结现状,再决定是否继续。
长会话不一定更高效。随着任务推进,早期的假设、临时方案和已经解决的问题仍然留在历史中,新的调用可能继续携带它们。
例如,Agent 最初认为问题出在配置文件,后来已经确认根因是接口返回异常,但早期判断仍然存在于对话里。此后它可能同时参考新旧两套结论,产生更多解释和试错。
当任务发生明显阶段变化时,适合主动整理上下文:
如果工具或工作流支持缓存,应优先缓存稳定且重复使用的上下文,而不是缓存频繁变化的内容。稳定的项目规则、固定的接口说明适合复用;实时状态、当前日志和临时任务描述则应保持最新。缓存的价值在于减少重复处理,但缓存过期或失效后仍需要重新核验,不能把它当成事实永久存档。
Spotify 工程团队公开的 Portal 案例,值得借鉴的地方并不是某个特定产品设置,而是把 Agent 工作过程看成一条需要优化的上下文流水线:哪些信息进入模型、哪些信息留在工具侧、哪些结果应该被压缩,以及什么时候应该结束当前循环。
这套思路可以拆成四个动作。
稳定内容适合重复使用,但应避免把所有内容都放入固定上下文。项目级规则、常用接口约定和明确的工作边界,可以作为相对稳定的基础信息;当前文件内容、测试输出和运行状态则属于动态信息。
设计时要特别留意“看起来稳定、实际上经常变化”的内容。比如自动生成的状态、带时间信息的提示和不断更新的任务记录,如果每次都发生变化,可能会削弱缓存复用效果。只有真正稳定的部分,才适合成为共享上下文。
裁剪不是简单截断字符,而是按照任务目标筛选信息。一次修改函数的任务,通常需要目标文件、相关调用关系和约束说明,不一定需要整个仓库的所有文档。
可以按照这个顺序缩小范围:
如果 Agent 经常因为缺少信息而反复搜索,说明裁剪过度;如果它拿到大量内容却仍然无法定位问题,说明筛选方式可能不够聚焦。好的裁剪应当减少无效调用,而不是只让单次输入看起来更短。
并非所有中间结果都需要一直放在对话历史里。工具可以在外部保留较大的日志、扫描结果或临时文件,模型只接收摘要、索引和访问线索。
这里的“离载”可以理解为:把适合机器保存的原始材料留在工具侧,把适合模型判断的结论带回上下文。比如保留错误位置、结果状态、关键片段和文件路径,而不是完整输出全部内容。
需要注意的是,离载后的摘要必须可追溯。只给出“执行失败”这种过于笼统的结果,会迫使 Agent 再次调用工具获取细节。摘要至少要让 Agent 知道失败发生在哪里、可能影响什么,以及下一步可以采取什么动作。
降低消耗不能只看总 Token 数,还要看这些 Token 是否推动了任务进展。可以为一次任务保留简单的调用记录,关注:
复盘的目的不是追求每次任务都使用最少调用,而是找出重复出现的浪费模式。如果一个任务偶尔多调用几轮是为了确认风险,这可能是合理成本;如果每次简单修改都重复扫描相同目录,就应该优先改造工作流。
在调整 AI 编程 Agent 之前,可以先按以下顺序检查:
上下文优化最容易走偏的地方,是把“少传内容”当成唯一目标。过度裁剪会让 Agent 缺少必要背景,过度压缩会隐藏错误细节,过早开启新会话又可能丢失已经确认的关键信息。
更稳妥的判断标准是:在保证结果质量的前提下,让每一轮调用都承担清晰的任务。固定内容尽量复用,变化内容及时更新;工具结果只返回有助于决策的部分;长会话定期清理;遇到循环则复盘调用条件,而不是继续堆叠历史。
当团队开始记录“哪些上下文被重复读取”“哪些工具结果从未被使用”“哪些调用没有改变决策”,Token 优化就不再是凭感觉删提示词,而会变成一项可以持续改进的工程工作。
Δ
Ctrl+D