你家 Agent 记忆越做越大,越用越难用?
你肯定见过这种情况:
- 做了 RAG + 向量库,记忆“召回”很多,答案却开始发飘
- 越聊越长,上下文里堆满旧规则、过期偏好、临时吐槽
- 你的检索命中率看起来不错,实际是“脏命中”——命中的是过时经验
- token 消耗飞起,每天多烧几十块,心态爆炸
问题不在“记不住”。
问题在不会忘。
我最近翻到一个开源项目(Enso),思路挺硬:遗忘不是靠感觉,是可以被工程化的。它更像在给 Agent 加一个“纪律层”。
项目:github.com/amazinglvxw/enso-…
下面我把它的核心设计拆开讲,顺便给你一套可以直接抄走的实现套路。
这套方案到底解决什么?
把目标说人话:
让 Agent 记住“能让它少犯错的东西”,忘掉“只会占位置的东西”。
落地到日常体验就是:
- 你不用人工整理“记忆库”
- Agent 自己从失败里长记性
- 过期经验自动变淡、自动删除
- 真正重要的规则会从“具体案例”升格成“抽象原则”
这比“无限上下文”更现实。无限只是账单更无限。
核心设计 1:错误驱动的学习闭环(而且是全自动)
Enso 的闭环很像你带新人:
- 先让他干活
- 干砸了就复盘
- 写成一两条“教训”贴墙上
- 一段时间不再犯,就把那张纸撕了
它把这套流程写进系统里:
流程长这样
- tool call 失败自动捕获(比如 API 401、参数校验失败、文件路径不存在)
- 用轻量 LLM 把失败蒸馏成 1~3 条教训(短、硬、可执行)
- 下次 Agent 启动时,把这些教训 注入上下文(等于开机自检)
- 30 天没触发:标记为观察
- 37 天仍没触发:删除
- 删了以后又犯?允许恢复(别把系统做死)
整个过程零人工干预。你只负责看效果。
教训应该长什么样?(模板给你)
把“教训”写成能直接约束行动的句子:
- ✅ 好:
调用 Stripe 退款接口前,先检查 payment_intent 是否为 succeeded,否则直接终止并记录原因。 - ✅ 好:
读取本地文件路径时,统一用绝对路径;遇到相对路径先 resolve。 - ❌ 差:
要更谨慎。 - ❌ 差:
注意不要报错。
教训越短越狠越好。别写作文。
核心设计 2:DIKW 分层蒸馏,让经验自己“升级”
Enso 不是把所有记忆一股脑塞进同一个桶,而是按 DIKW 做分层。
你可以理解成:
- Info:具体教训/事实碎片(带分类、命中次数、溯源 hash)
- Knowledge:抽象规则(从多个 Info 合并而来)
为什么要这么分?
因为“教训”天然有保质期。
- 很多失败是一次性的环境问题(临时 token 过期、某个服务抖了)
- 也有一些失败会反复出现(参数校验、权限、路径、格式)
DIKW 分层的价值就是:
- 短期噪音留在 Info 层,方便淘汰
- 反复命中的 Info 自动合并成 Knowledge,变成长期资产
一个合并的例子
Info(多条):
上传图片到 S3 前必须校验 content-type,否则 CDN 侧会拒绝。S3 putObject 时如果没带正确的 ContentType,前端预览会 403。
合并成 Knowledge:
任何对象存储上传都必须显式设置 ContentType;缺失则视为错误并阻断。
你会发现:Knowledge 才是你真正想长期保留的东西。
核心设计 3:三维质量控制,让记忆库不发臭
记忆系统最怕的不是“小”,而是“烂”。
Enso 用了三把刀控质量:
1)语义去重(不用向量库也能做)
- 用 TF-IDF 做相似度
- 相似度阈值:
> 0.7判重
好处很实在:
- 避免同一条教训换个说法刷屏
- 让“命中次数”更可信(不会被重复条目稀释)
2)LRU 淘汰(硬上限)
- 超过 50 条:踢掉最旧的
这个简单粗暴,但很管用。
你不设上限,记忆就会像浏览器标签页一样越开越多,直到你不敢关。
3)stale 衰减(三段式过期删除)
- 新鲜:正常使用
- 变陈:进入观察
- 过期:删除
对“从没再触发的教训”,别恋爱脑。
核心设计 4:代码强制 > prompt 约束(这点特别值得抄)
很多人给 Agent 写一堆 prompt 规矩:不许干这个、不许干那个。
现实是:
- 对话拉到 5 万 token 以后,prompt 里那些规矩注意力权重会掉到你怀疑人生
- Agent 会“合理化”绕过规则(它真能编出一套自洽的借口)
Enso 的做法更像 SELinux:用代码做强制策略。
它用 hook 脚本在违规时直接 exit 2 阻断。
效果是:
- 不是“请你不要”,而是“你做不到”
- Agent 想绕也绕不过
你可以怎么抄(示例思路)
你可以在这些地方加“硬闸门”:
- 文件系统:限制只能读写某个目录
- 网络:只允许访问白名单域名
- 工具调用:参数缺失直接阻断
- 成本:单次调用超过预算直接停
伪代码(示意):
def tool_call_guard(tool_name, args):
if tool_name == "curl" and not is_whitelisted(args.url):
raise SystemExit(2)
if tool_name == "write_file" and not args.path.startswith(ALLOWED_DIR):
raise SystemExit(2)
return True
别把安全和纪律寄托在 prompt 上。真不稳。
最接地气的部分:零外部依赖
Enso 有个我很喜欢的点:
- TF-IDF 手写几十行 Python
- 分类器用关键词硬编码
- 不依赖 scikit-learn
- 不上向量库
结果就是:
- 一条命令装完
- 有
bash + python3的环境都能跑
这对做 Demo、做内网部署、做边缘环境特别香。
你要的是“能跑起来”,不是“依赖装一天”。
你想把“主动遗忘”接进自己的 Agent,可以照这个路线做
我给你一套可执行的接入清单,不管你用的是 OpenAI / Claude / 自建模型,都能套。
Step A:把失败事件变成标准化日志
你需要统一记录这些字段:
timestamptool_nameinput_argserror_type(超时/权限/校验/不存在…)error_messagetrace_id或source_hash(方便溯源)
关键点:别只存一段字符串。后面蒸馏会很难。
Step B:做一个“教训蒸馏器”
触发条件:工具调用失败,或输出被判定为严重错误。
蒸馏输出格式建议固定:
{
"category": "filesystem|network|auth|format|validation|rate_limit|unknown",
"lessons": [
"...",
"..."
]
}
要求:每条 lesson 能直接指导动作,控制在一行。
Step C:写入 Info 层(带计数与溯源)
Info 记录建议字段:
textcategoryhit_countcreated_atlast_hit_atsource_hash
命中一次就 hit_count += 1,更新 last_hit_at。
Step D:做合并策略(Info → Knowledge)
当你发现同类 Info 相似度高(TF-IDF 或简单关键词相似),触发合并:
- 生成更抽象的 Knowledge
- Knowledge 也要有
hit_count - 合并后可保留原 Info 作为溯源,或做摘要引用
Step E:做遗忘策略(三段式 + 上限)
建议直接抄这套组合:
- 去重阈值:
0.7 - 容量上限:
50(你可以按场景调) - 观察期:
30 天 - 删除期:
37 天 - 支持恢复:删除后如果再次触发同类错误,把它拉回来
参数不是圣经。
你跑一周看数据,明显不对再改。
Step F:注入到上下文的位置要讲究
别把 50 条教训全塞 prompt。
推荐做法:
- 每次启动注入:Top-N Knowledge + 最近命中的 Info
- N 建议 5~12 条,太多就是噪音
- 按工具分类注入:用到什么工具才注入相关教训
你的目标是让 Agent“开局不犯低级错”,不是背题库。
避坑清单(踩中一个就会变难用)
- 教训写太长:长文本会稀释注意力,还会把上下文撑爆。
- 没有溯源 hash:你会找不到“这条教训从哪来的”,也没法调试。
- 只靠 prompt 管纪律:越聊越长就失效,Agent 还会耍滑头。
- 不设上限:记忆一定会膨胀到不可控。
- 删除不可恢复:会把系统变成“一次误删,永久失忆”。
- 去重只做 exact match:同义表达会把记忆库刷成垃圾场。
适合什么人用?
这套“主动遗忘 + 纪律层”特别适合:
- 你的 Agent 有大量工具调用(爬虫、脚本、数据库、工单系统、内部 API)
- 你希望它越用越稳,少半夜把你叫起来修 bug 😅
- 你对向量库依赖过敏,想要轻量、可控、可迁移
如果你做的是纯聊天陪伴,工具很少,这套的收益会小一些。
你可以怎么用 Enso(现实建议)
别把它当“开箱即用的记忆系统”。它更像一个设计样板。
值得 fork 的原因:
- 把“遗忘”做成工程闭环,而不是一句口号
- DIKW 分层让记忆质量随时间变好
- 代码强制策略这条路,很少人认真做
代码质量中等,想接 OpenClaw、Hermes Agent 这类框架,需要自己适配一下。
适配不难,核心是把它的闭环思路嵌到你的事件流里:失败 → 蒸馏 → 注入 → 衰减。
给你一个行动建议
你今天就能做一件小事:
- 在你的 Agent 里加一个“tool call 失败捕获器”
- 失败时蒸馏成 1 条教训
- 下次启动时注入
跑 3 天你就会明显感觉到:低级错少了,token 也省了,心态更稳。
记忆系统不该只会囤货。
该忘的就忘,才像个真干活的 Agent。