前面三篇走下来,Agent 已经会转循环、会喊工具、会在失败之后换个做法。它看上去越来越像个有记性的东西:记得你上次交代过什么,记得任务的目标,记得刚才那一步为什么失败。

但准确的说法是:它什么都没记住。

无状态的真相

模型本身是无状态的。这一轮生成和上一轮生成之间,它内部不留任何东西——每次开口之前,它能看到的只有这一次被递到面前的内容。

那你为什么觉得它记得你?因为外面的程序把之前的对话原样又递了一遍。所谓记忆,全都是外面替它保存、替它搬运的结果。

模型不会记住你,它只是每次开口前,把你和它说过的话重新读一遍。

能读的内容有上限,这是硬约束。这个上限就是上下文窗口,可以理解成它面前那张桌子的面积:凡是能影响它这次回答的东西,都得先摊在这张桌上——你的问题、工具说明书、工具返回的结果、之前的对话,还有它自己写下的思考。

越摞越高 · 摊满桌面

桌子摊满了会怎样

任务短的时候什么事都没有。轮数一多,麻烦就来了:对话越来越长,桌上越来越挤,直到放不下。

常见的三种应付方式:

截断最省事,代价也最直接:最早的内容里往往压着最要紧的东西——任务的目标、你给过的约束、双方约定好的做法。长任务里 Agent 忽然“忘了你要它干什么”,通常就是这个原因:不是它走神,是那一段被挤出去了。

这三种做法并不互斥,成熟的系统通常一起上:平时靠压缩,遇到特别长的历史才截断,真出了岔子就明确报错,把“丢什么”交给用的人来定。

短期记忆的第一种解法:压缩

压缩的做法是让模型给前面的一段对话写摘要:读一遍,留下要点,丢掉原话,用摘要替换原文。

这笔账很好算:地方省下来一大块,细节也跟着没了。所以整理的时候要有取舍意识。什么必须留——任务的最终目标、已经拍板的决定、还没做完的待办、不能违反的约束;什么可以丢——寒暄、试错的过程、中途作废的那段分析。

压缩不是无损的:丢掉的是过程细节,留下的是结论和约束。

摘要按固定栏目写会更好用。与其让模型自由发挥,不如要求它分四栏输出:任务目标、已定事项、待办、限制条件。栏目固定下来,下一轮不管是人来读还是模型来读,都不容易看漏。

工程上常见的做法是分两层:最近几轮对话保留原文,一个字不动,因为模型需要那些细节才能把话说得顺;更早的部分压成摘要。这样既省地方,也不会把眼前的对话搅浑。

长期记忆:搬到外面的柜子里

压缩只能救急。真正重要的东西,不该指望模型“当前读到的这一堆字”,而该放到模型外面去——写进文件、数据库或者专门的记忆库。

分工可以这样理解:短期记忆是面前这张桌子,长期记忆是身后那个档案柜。模型依旧什么都不记得,但每次开工之前,外面的程序会先去柜子里取出这次用得上的几份,摆到桌上。

往里放什么,决定了这套记忆值不值钱。经验上,真正值得写下来的是四类东西:

长期记忆的本质不是“模型记得”,而是“外面替它记着,用的时候再递给它”。

还有一件容易做错的事:什么时候写进去。写入时机该由外面的程序把握——任务收尾时、用户明确说了新偏好时——而不是让模型在对话里随口宣布“我记住了”。模型说记住,多半只是生成了一句听起来像记住的话。

存进去,还要取得回来

柜子越大,越考验取的能力。柜子再满,取不回来就等于没存。

取的方式大致两类:

取回来的数量要有克制。全部塞回桌上,等于没做压缩;检索的意义不在于把所有相关的都找出来,而在于挑出这次真正用得上的那一小把。

分寸还要再往下走一层:取回来的东西太多,不但占地方,还会把模型带偏——一堆沾边的旧事堆在桌上,反而盖住了真正相关的那一条。

从柜子里 · 挑回一把

记忆的三种风险

新旧信息打架的时候也得有规矩:以更新的为准,并且给每条记忆带上时间和来源——否则你永远说不清哪一条该信。

还有一个容易忽略的成本:记忆会让每一轮都变得更重。桌上多摆几份档案,模型处理起来就更慢、更贵。所以“多记一点总没坏处”是个错觉——好的记忆系统不是记得最多,是取得最准。

四篇走完,路还长

四步之后 · 路还长

回头看这四篇:从“模型只会说”出发,给它接上工具,用循环把工具串成连续的行动,再配一套会取舍的记性。

走的是一条从会聊天到能干活的路,而每一步的技术内核其实是同一句:模型只说,外面在做。

再往后还有许多值得单独聊的题目——多个 Agent 之间怎么分工,工具的权限和沙箱怎么设,一个 Agent 到底行不行该怎么观察和评测。等讲到这里,我们再往下拆。