第 3 章:记忆与上下文
让 Agent 有记忆、有个性、能管理上下文窗口。
这一章一次解决 3 个问题
如果你觉得这一章信息量突然变大,这是正常的。因为它不是只补一个点,而是同时补齐了 3 个在上一章已经暴露出来的缺口:
- 对话重启后会失忆
- system prompt 太薄,Bot 没有稳定个性
- 历史消息会不断增长,最终撑爆上下文窗口
所以读这一章时,最好始终问自己:当前这一段代码是在解决“记不住”、 “不像自己”,还是“放不下”这三个问题里的哪一个?
三个问题
上一章的 Agent 有三个硬伤:
- 没有持久记忆——重启后什么都不记得
- 没有个性——system prompt 就一句话
- 上下文会爆——对话越长,messages 越大,最终超出 LLM 窗口
nanobot 用三个机制解决这些问题:Session 持久化、Context Builder、Memory / Dream 整合。
第一步:Session 持久化
对应 nanobot/session/manager.py。核心思路:每个对话存为一个 JSONL 文件,每行一条消息。
现在重启后对话历史不会丢了。nanobot 的实现还支持 metadata 行、legacy 路径迁移等,但核心就是 JSONL 持久化。
第二步:Context Builder——组装 System Prompt
这是 nanobot 最精巧的设计之一(nanobot/agent/context.py)。System Prompt 不是写死的,而是动态组装的:
为什么不把 system prompt 写死?
因为用户要能定制 Bot 的行为。通过 SOUL.md 改性格、AGENTS.md 改规则、USER.md 告诉 Bot 你是谁——全部是 Markdown 文件,改完下次对话自动生效。
build_messages 每次调用都重新读取这些文件,所以用户编辑后不需要重启。
第三步:持久化记忆
对应 nanobot/agent/memory.py。当前实现是分层设计:
| 层 | 文件 | 特点 |
|---|---|---|
| 长期记忆 | memory/MEMORY.md |
每次对话都注入 system prompt,存放重要事实 |
| 历史摘要归档 | memory/history.jsonl |
追加式 JSONL,可 grep / jq 搜索,存放被压缩后的旧对话 |
| Dream 状态 | memory/.cursor / memory/.dream_cursor |
记录摘要写入位置和 Dream 已处理位置 |
| 记忆版本 | memory/.git/ |
Dream 修改长期文件后的轻量版本历史 |
记忆整合(Memory Consolidation)
当对话太长时,nanobot 会先由 Consolidator 把旧消息交给 LLM 总结,并把摘要追加到 memory/history.jsonl。随后 Dream 会定期读取这些新摘要,分析哪些内容应该沉淀为长期事实,再用文件工具谨慎编辑 SOUL.md、USER.md 和 MEMORY.md。
教学版为了让机制更容易看懂,把这两步压缩成一个 consolidate_memory():旧消息 → 摘要 → history.jsonl,再把最重要的结论写入 MEMORY.md。真实 nanobot 的 token-driven consolidation 更克制:它主要推进内部游标,保留原始 session 文件,并只让未整合部分继续参与上下文构建。
这个机制确保了:
- 上下文窗口不会撑爆
- 重要信息不会丢失
- MEMORY.md 里的事实每次对话都可用
简化版实现:
nanobot 的实现更精巧:Consolidator 负责在上下文压力过大时把旧消息压缩进 history.jsonl;Dream 则作为后台记忆整理器,分两阶段分析历史摘要并编辑长期记忆文件。Dream 的修改还会进入轻量 Git 历史,用户可以用 /dream-log 和 /dream-restore 查看或恢复。
先别把这三个概念混在一起
| 概念 | 它解决什么 | 它存什么 |
|---|---|---|
Session |
当前会话历史别丢 | 原始对话消息 |
Context Builder |
每轮发给模型什么上下文 | system prompt + 历史 + 运行时信息 |
Memory |
长对话里重要事实别丢 | 提炼后的长期事实和摘要 |
很多初学者会把“重启后还记得”和“长期记忆已经整合”混成一件事。实际上这是两层不同机制。
本章你真正学到的抽象
这一章真正引入了 3 个长期有效的设计点:
Session Persistence:把对话状态从内存搬到磁盘Context Builder:把静态配置、动态记忆、运行时信息拼成统一上下文Memory / Dream Consolidation:用摘要归档和长期记忆对抗上下文窗口上限
从这里开始,Agent 不再只是“会调用工具的聊天循环”,而是一个有稳定人格、跨轮状态和上下文预算意识的系统。
最小验证步骤
建议按顺序做下面 4 个验证:
- 跑一次程序并完成几轮对话,确认会生成
sessions/和memory/相关文件 - 重启程序,再问一个延续上一轮的问题,确认至少 session 历史仍然存在
- 修改
SOUL.md或AGENTS.md,确认下一次对话的风格或流程发生变化 - 构造一段较长对话,手动触发或观察记忆整合后
memory/history.jsonl和MEMORY.md的变化;真实 nanobot 还可以用/dream-log查看 Dream 修改了什么
常见失败点
- 重启后“没有记忆”:先区分是 session 历史没保存,还是长期记忆没写入,这是两套机制
- 改了
SOUL.md没效果:通常是 build_messages 没有重新读取文件,或 system prompt 没重新构建 - 记忆整合输出不稳定:让模型直接返回 JSON 很脆弱,真实 nanobot 把“压缩旧消息”和“整理长期记忆”拆成 Consolidator + Dream 两层来降低风险
- 上下文仍然爆掉:说明你只有“保存历史”,没有真正限制传给模型的历史窗口
完整代码
在看完整代码前,先记住本章新增的职责切分:
SessionManager:负责把会话历史保存和读回来ContextBuilder:负责把静态文件、记忆和运行时信息拼成完整上下文MemoryStore/consolidate_memory():负责把旧消息折叠成摘要归档和长期记忆
带着这 3 个问题去看代码,会比直接从头扫到尾轻松很多。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 | |
试一试
编辑 ~/.mini-agent/workspace/SOUL.md 改成任何你想要的风格,下次对话自动生效。
关键对比
| 概念 | 我们的代码 | nanobot 的代码 |
|---|---|---|
| Session 持久化 | JSONL 简单序列化 | JSONL + metadata 行 + 缓存 + legacy 迁移 |
| Context Builder | 拼接 Bootstrap 文件 + Memory | 同上 + Skills 摘要 + Runtime Context + 最近历史摘要 |
| 记忆整合 | 简化版 JSON 解析 | Consolidator 写入 history.jsonl + Dream 整理 SOUL.md / USER.md / MEMORY.md |
| Bootstrap 文件 | 4 个 Markdown | 同样 4 个,但有模板同步机制 |
还缺什么?
Agent 现在有记忆、有个性,但它只能在终端里用。如果想让它在 Telegram / Discord 上工作呢?
下一章:消息总线——解耦 Agent 和 I/O。