小岛AIAI 航行日志

小岛 / 岛刊社 / 文章

Agent 长任务总会越跑越钝?把记忆搬出上下文窗口的 5 个办法

小岛AI

长任务卡住、重复搜索、忘掉前文,不一定是模型不够大。LangChain 新文给出卸载、可恢复摘要、按需技能、子 Agent 和自有记忆的分工;这篇把它整理成一次试点前能用的选择表。

Agent 工程

一个 Agent 已经查完五家竞品,读过几十篇网页,拉了几份大表,又改了两版报告。到了最后排版那一步,它开始重复搜索、忘记自己刚写过的判断,甚至把旧草稿又捡回来当新结论。

这种场面很像模型“变笨”了。很多团队的第一反应是换更大的上下文窗口,或者把所有聊天记录、工具结果和项目资料继续塞回下一轮请求。

但长任务真正危险的,往往不是它记得太少,而是它带着太多不该常驻的东西继续跑。

LangChain 昨天发了一篇讲 Deep Agents 上下文工程的文章,给出的处理方式很实在:大结果先离开活动窗口,旧过程压成可找回的摘要,专业说明按需加载,噪声工作交给独立子 Agent,跨会话的经验放进团队自己控制的文件里。不是清空记忆,是给记忆分仓。

先说证据边界:下面的机制、阈值和配图都来自 LangChain 官方文章,不是我的独立性能跑分。它很适合拿来设计试点,但不代表把这些组件装上,任何任务都会自动更快、更准。

先别把“上下文越大越安全”当默认答案

一个模型窗口再大,也不等于每一段历史都值得跟着下一轮模型调用继续计费。

长任务里最常见的垃圾,不是错误资料,而是已经完成的过程:那次几十页的网页抓取、工具返回的原始数据、被否掉的两版草稿、子任务里来回试探的搜索结果。它们对当下的排版、汇总或下一步决策大多没用,却会持续占用 token,还会让模型在相似但过时的线索里打转。

官方把这个现象叫作 context rot。名字听着有点重,实际很朴素:一个桌面放得下所有东西,不代表你还能快速找到眼前要用的那张纸。

Deep Agents 的思路,是把“现在要推理的材料”和“以后可能要追溯的材料”拆开。主 Agent 持有前者;后者不丢,但要有文件路径、摘要、检索入口或独立执行者负责保管。

LangChain 官方图:大工具结果先卸载,旧上下文接近阈值后压缩为摘要,活动窗口重新变轻。

LangChain 官方机制图。黑点表示大结果的卸载,蓝点表示接近阈值后进行摘要;原图保留英文标签。

这里最容易踩的坑,是把“压缩”理解成“删掉”。如果摘要后细节再也找不回来,Agent 只是从上下文溢出变成了记忆丢失,后面要核对一个数字或追问一个引用时,照样会翻车。

还有一个常见误判:任务慢、答非所问,不一定都是上下文的问题。模型本身慢、外部工具超时、权限被拒、检索源质量差,也会长得很像“记忆坏了”。因此第一轮别急着上五套中间件,先在任务记录里分开看:模型调用耗时、工具返回体积、重试次数、上下文用量和回放次数。你至少得知道,那个 Agent 是被一份 30MB 的导出压住了,还是被一个一直 500 的接口拖住了。

反过来,只有两三步的小任务也没必要整套搬运。一次查询、一次格式转换、一次明确的写入,透明的短链路更好维护。上下文工程从来不是给流程加机关,而是让信息只在需要的地方停留。

第一格:大结果应该卸载,不该截断

LangChain 文中给了一个清晰的默认信号:大型工具输入或输出超过 20,000 token 时,适合写进文件系统,让模型看到位置和短预览,需要时再搜索或读取。

这和“把结果砍到前 100 行”不是一回事。截断会让后半段从此消失;卸载把原件留在项目存储里,只是停止让它每一轮都坐在模型的主桌上。

你可以从最容易把窗口撑胖的地方下手:数据导出、长网页正文、测试日志、完整 diff、批量检索结果。把每类内容放到可追踪的位置,并留下来源、时间、任务 ID 和摘要。这样当报告最后一句需要回查时,Agent 有路可以回去,不必靠记忆猜。

对很多已经在用 RAG 的团队,这一步也值得单独做。检索回答的是“此刻该找哪段资料”;卸载处理的是“上一次工具调用塞进对话里的那坨原始输出,现在还要不要一直背着”。两者不是替代关系。

第二格:摘要可以触发,但必须能回放

官方默认在上下文用量达到模型窗口的 85% 时摘要较早的消息,保留最近消息原文。原始对话会写入类似 /conversation_history/{session_id}.md 的位置,后续如果任务需要早前的细节,可以再读回来。

这套设计里最值得拿走的,不是 85% 这个数字。不同模型、不同工具输出密度、不同任务都可能需要改阈值。真正该固定下来的是三件事:什么时候压缩、压缩后保留什么、原件怎么找回。

如果你给 Agent 做一项跨天研究、代码迁移或资料归档任务,可以先用下面这份小合同试跑一轮:

触发:活动上下文达到团队设定的预算线
摘要:保留目标、已完成动作、待验证事实、未解决问题、来源索引
原件:把被压缩的对话与大结果写入可搜索的项目存储
回放:需要引用、数字、命令或失败原因时,先读原件,再写结论
验收:随机抽三条摘要结论,能否在原件中定位到对应证据

最后一行很关键。没有回放抽查的摘要,只是把错误写得更短。好家伙,token 是省下来了,排障证据也一起省没了。

第三格:技能不该常驻,重活也别污染主线程

文章里有个很适合做工程判断的区分。

像季度业务回顾模板、财务口径、某个客户的交付规范,这类知识不是每一步都需要。更合适的做法,是让 Agent 先看到技能名称和一句说明,只有任务真的涉及它时,才加载完整操作手册。LangChain 把这种方式叫作渐进式披露:菜单先在,整本菜谱用到再翻。

这和把团队所有 SOP 丢进系统提示词比起来,朴素得多,也省得多。常驻说明越多,模型每次回答一个小问题都得从一堆无关规定旁边挤过去。

另一类问题则不该靠技能解决,而该隔离。比如让 Agent 为五个竞品各做一轮资料搜集,原始搜索页、失败请求、重复线索必然很多。官方建议让子 Agent 在自己的上下文里处理这些噪声,最后只返回主 Agent 真正需要的三条结论或一个结构化结果。

LangChain 官方图:子 Agent 在独立上下文中完成高噪声研究,主 Agent 只接收需要的结论。

LangChain 官方示意图。子 Agent 的价值不只是并行,更是让原始搜索和中间试错不挤进主任务的活动窗口。

这里要留一个工程上的刹车:子 Agent 返回得短,不等于返回得可靠。主任务仍要知道结论来自哪个子任务、用过哪些来源、失败了没有、是否需要重新打开原始材料。把它当成“压缩后的供应商”,而不是神秘的答案黑箱。

第四格:长期记忆要归项目,不要归模型

LangChain 把长期记忆放进普通 Markdown 文件,运行时读取,学到的新偏好再写回。它的好处很直接:模型或供应商换了,项目的约定、写作格式、数据口径和已知边界还在自己的存储里。

但“什么都写进长期记忆”同样会出事故。长期文件一旦塞入临时结论、个人数据、过期规则和未经验证的猜测,下一次任务就会把旧偏见稳定地带回来。

我会把记忆分成三种:

  • 必须长期有效的约定:输出格式、权限边界、事实来源标准。
  • 可以过期的项目知识:带更新时间、负责人和失效条件。
  • 只属于这次运行的过程:留在任务账本或原始记录里,不升级为长期记忆。

这样做不浪漫,但很有用。Agent 不是越会“记住”越好;它得知道哪些东西应该在下次继续生效,哪些只能作为本次的历史证据。

真要开始试,先回答一个选择题

很多框架把卸载、摘要、技能、子 Agent 和记忆都打包成能力清单,看起来像五个都要。

其实第一轮只要问一句:眼前的问题,是信息太大、历史太长、知识不常用、子任务太吵,还是跨会话约定需要保留?

大文件和大工具结果,先卸载;长过程需要连续推进,用可回放摘要;偶尔才用的流程,按需加载技能;搜索或批量分析很吵,拆给子 Agent;真正跨会话的稳定偏好,才进入长期记忆。

这五件事不是某个框架的专属配方。它们是在提醒我们:给 Agent 做长任务,别只盯模型能装多少 token,也要给信息设计离场、归档和回来的路线。

你们团队的长任务现在最常见的症状是什么:工具输出太大、历史太长,还是子 Agent 报回来的结论已经没法追溯?

小岛 AI