
先说问题
agent 的记忆有个根本矛盾:
- 记得太少:每次都从零开始,你上周说的规范它当没听见
- 记得太多:每次都把整本手册塞进提示词,token 哗哗流,而且真正相关的信息被淹在噪音里
大部分方案选后者,因为实现简单——往系统提示里拼一段就完事了。但你每轮都在付费,而且是为一堆这一轮根本用不上的内容付费。
dsh-lite-memory 的设计目标只有一句:
全库不常驻:没有命中的轮次不追加记忆内容,命中时最多三条卡片,正文按需读。
三个数字:零常驻、最多三条、正文按需。
三级触发:什么时候它会写
这是整个插件最该先搞懂的部分。
| 级别 | 场景 | 行为 |
|---|---|---|
| L0 | 你明确要求「记住这个」 | 立即写盘,回一条确认行 |
| L1 | 它发现有跨会话价值的经验 | 一行灰字 memory · suggested "X" + 一个「保留」按钮;标题加一句话,看得懂才点,不点就永远不写,48 小时内不重复 |
| L2 | 常识、一次性参数、凭据的值 | 永不写入 |
L1 这个设计很克制。它不是「自动帮你记」,而是「问你一句要不要记」。而且:
- 标题里带一句话说明,你看得懂才点
- 不点就永远不写
- 同一个建议 48 小时内不重复骚扰
自动记忆最烦的地方是它记了一堆你以为它没记的东西,然后在你不知情的时候影响回答。这里把决定权留给你了。
L2 那条也值得说:凭据的值永不写入。不是「加密存储」,是不写。这个边界划得对。
写入前先蒸馏
这条规则直接决定了记忆质量:
标题是结论,正文只留原则、判断规则和触发条件,不把具体尺寸、字号、层级、颜色或一次性数字记进来;需要这些值时按记忆里的指针查当前代码或文档。
举个具体的:好记忆是「所有按钮的圆角走 --dsw-radius 变量,别写死像素」,坏记忆是「按钮圆角 8px」。
前者十年后还对,后者明天改了就变成误导。记忆存的是判断规则,不是某一时刻的快照。
配套的硬限制:单条正文超过 4096 字节直接拒绝,摘要超长自动截到 60 字。拒绝而不是截断,这个选择有意思——它逼你先把细节删干净再存。
同名怎么处理
记忆系统最容易烂掉的地方是「同一个东西记了五条,说法还不一样」。
它的处理规则:
- 同层里标题完全一致 → 更新原条目(不并存两条同名)
- 前置条件不同(用
when区分)→ 各存一条,但更新的是同一条 - 换过说法、标题变了 → 旧标题记成别名,以后也认得
- 像但不同名 → 先回「相近:X」,你说要更新就用那个标题重存;确实是另一条,才用
resolution="distinct"另存,且必须换个能区分的标题
最后那条「必须换个能区分的标题」是关键。它不让你偷懒存两条几乎一样的记忆。
读取:不猜
读取时如果标题只记得一半(到逗号或括号为止):
- 唯一一条前缀对得上 → 直接读
- 对得上两条 → 把候选标题列出来,不猜
同一名前缀的归档副本不算第二条候选,活条目优先。这种细节说明作者真的用过自己的东西。
每轮留在回复末尾的那几行
每次回复末尾,「已编辑 N 个文件」下面会多几行:
本轮参考 N 条
本轮更新 N 条
点开是记忆名,再点一条就地展开当前正文。名字和正文都取当前值——改过名显示新名字,归档的标「已归档」,删掉的显示「已删除」。
有个约束很有意思:这些行只属于产生它的那一轮。每轮按那轮自己的工具结果重建,重进会话还能看见,别的轮不会混进来。没读过也没写过,整段不出现。
这解决了「我到底这一轮用了哪些记忆」的可见性问题。否则记忆就是个黑箱,你永远不知道它这次是被哪条记忆带偏的。
为什么它「轻」
技术上的答案很干脆:
- 0 依赖
- 存储层无定时器、无监听、无网络
- 只有同步单文件写
- 写入用一把有超时的锁(500ms),别的进程正在写就明确报「忙」,不抢别人的锁
搜索最多返回 4 条、400 字。全文只在 memory_read 里出现,永不进上下文。
上限:
| 项 | 值 |
|---|---|
| 单条正文 | 4096 字节 |
| 整库正文 | 1 MB |
| 每层条目 | 1000 条(200 条起提示) |
| 标题 / 摘要 | 各 60 字 |
| 90 天未用 | 只留标题与版本 |
到硬上限时不拒绝新记忆:把同层最久没被读的一条移进归档(用户固定过的规则不动),保存结果里写明是哪条,正文与完整记录都留着,可人工取回。文件从不删除。
「用户明确说别记」也进归档。这条挺狠,也合理——你不让记的东西,连正文都不该留在活跃库里。
两层:项目和全局
默认只在这个项目生效。你明确说「以后所有项目都这样」,才进全局层。
检索时两层一起查,每条前面标归属([global] 或项目目录名如 [DSH])。
一个项目一个目录,项目之间互相看不见。这个隔离是硬隔离,不是「逻辑上分开」——客户端拼不了路径,也写不了别的项目的笔记。
面板能一键关掉
关掉项目记忆之后,这个项目不再使用任何记忆(包括全局层):自动注入、检索、读取、引用、保存全停,服务端也拒绝记忆工具和面板修改动作。
两个细节:
- 关闭只改权限,不删数据。候选、试用、生效、证据、整理额度都保留,计数照常显示
- 记忆工具与面板管理动作都在服务端拒绝,改前端绕不过
第二条是安全边界的正事。很多「开关」只在前端生效,改个 DOM 就绕过去了。这里明确说了服务端拒绝。
工具清单
memory_save · memory_suggest · memory_search · memory_read · memory_forget
五个。不多不少:存、建议、搜、读、忘。
「忘」是一个独立工具,而不是「存一个空值」。这个设计上的区别很重要——忘是有语义的操作,它该被记下来。
装
插件管理器里搜 dsh-lite-memory 直接装;或者 npm pack 后用 Plugin Manager 安装生成的 .tgz。
一句话
记忆的价值不在「存了多少」,而在「该出现的时候出现,不该出现的时候一个字都不占」。 大部分记忆插件解决的是「能不能记住」,这个插件解决的是「记住的代价」。
*参考:GitHub regrevia/dsh-lite-memory(MIT,4 stars),0.18.83,2026-11-04 更新。*
相关阅读
- 大肥鱼的记忆是怎么做的?三层记忆系统拆解 —— 记忆系统的完整设计
- DSH 插件怎么选?大肥鱼必装的 8 个插件 —— 插件怎么选
- DSH 崩溃自救:把崩溃日志变成拦截规则 —— 崩溃防护