# Long Term Memory

> 读取和维护 Agent 与用户跨聊天会话形成的长期记忆，使当前交互能够延续过去的重要经历、知识和上下文，而不是每次从零开始。用于记住、回忆、纠正或忘记过去的信息，以及当前交互与既往经历、讨论、决定、目标、偏好、约定、未完成事项或其他历史上下文明显相关的情况。

- Skill: `nutstore/long-term-memory` (Agent Skill)
- Install (CLI): `npx skillmds@latest add nutstore/long-term-memory`
- Raw SKILL.md: https://api.skillmd.com/api/skills/nutstore/long-term-memory/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: AI & ML
- Author: nutstore (https://skillmd.com/u/nutstore)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/nutstore/long-term-memory

---


# 长期记忆

长期记忆用于长期保存未来可能值得回忆的过去，使 Agent 跨聊天会话持续继承过去的经历、背景、决定与未完成事项，而不是每次从零开始。

判断一件事是否值得记住：

> 如果未来某个交互不知道这件事，是否会丢失有意义的上下文——导致重复提问、重复决定、误解用户，或无法延续之前的进展？

不要因为一件事曾经出现过就记住它，也不要求它必须永久稳定才值得记住。值得记住的内容既可以是持续有效的知识，也可以是一次重要经历、某项决定、事情的发展过程，或尚未结束的上下文。

## 存储布局

长期记忆存放在两个地方：

```
.agents/nutstore-sync/memory/
├── archive/                     # 权威记忆：每日一个 Markdown 文件
│   └── <YYYY>/<YYYY-MM-DD>.md
└── catalog/                     # 检索目录：每年一个 TSV，可重建
    └── <YYYY>.tsv
```

在 bash 文件系统中务必使用以下完整路径，不要构造其他变体：

- `/.agents/nutstore-sync/memory/archive/<YYYY>/<YYYY-MM-DD>.md`
- `/.agents/nutstore-sync/memory/catalog/<YYYY>.tsv`

向用户提及记忆文件时，使用知识库相对路径 `.agents/nutstore-sync/memory/...`，不要带开头的 `/`。

## 权威性

- **每日记忆文件是唯一权威数据源**。文件名 `<YYYY-MM-DD>.md` 就是日期，也是稳定 ID；文件完整路径完全由日期唯一推导，一旦写入就永不重命名、永不移动、永不因任何分类而重组。
- **`catalog/` 是派生检索目录**。它只把每日文件 frontmatter 中的 `date` 与 `index` 原样集中复制。目录可删除、可重建，但绝不反向写回每日记忆文件。
- 记忆文件都是普通 Markdown，用户可以随时阅读、修改或删除。

## 文件格式

每日一个 Markdown 文件：

```markdown
---
date: <YYYY-MM-DD>
index: '检索摘要：覆盖当天记录的所有主题与关键内容'
---

## <YYYY-MM-DD>

- <一条记忆条目>
- <另一条记忆条目>
```

### index 的硬性约束

- 只能占一行，必须用单引号或双引号包裹；
- 禁止包含制表符或换行（否则会破坏 `catalog/<YYYY>.tsv` 的列结构）；
- 只写正文中真实存在的信息，不虚构；
- 不得为了简短而漏掉当天任何一个独立主题；
- 不复制整篇正文；
- 避免「进行了讨论」「确定了方案」「记录了问题」这类没有区分度的套话。

### index 应该写什么

`index` 是给未来未知查询做全文匹配的检索摘要，不是标签列表。合格摘要应当包含：

- 人名、项目名、对象名、专有名词；
- 关键决定及其对象，关键数字、日期、状态；
- 遗留的问题、待办事项；
- 用户使用过的、以后的查询可能重新出现的具体说法。

未来查询未必使用总结出来的规范术语，大多使用具体名称或关键短语，因此摘要要保留这些可检索文本。

## 写入与冻结规则

- **当天文件**：正文只允许追加；`index` 可随新条目反复重新生成（覆盖旧的 `index`），但绝不删除或改写已有正文。
- **历史文件**：本地日期跨日后，正文与 `index` 一同冻结；之后普通维护不得修改历史文件。
- 历史文件就是最终储存地，不需要再次搬移归档。真正随时间变化的是检索入口（catalog），不是文件位置。
- 「纠正」和「忘记」是用户的专门请求，不受冻结规则限制（见「修正与遗忘」）。

## 年度检索目录（catalog）

`catalog/<YYYY>.tsv` 每年一个纯文本文件，一行对应一个记忆日：

```text
<YYYY-MM-DD><TAB><index>
```

- 一行中的 `index` 必须与该日文件 frontmatter 的 `index` 完全一致，**不做二次总结**。
- 生成时机：某个自然日结束、该日文件被冻结后，把该日的 `date + index` 追加进对应年份的 TSV。
- 若跨日时没有运行，下次使用记忆功能时补做；先读取已存在的日期行，只补缺失的行，避免重复。

## 检索流程

检索始终由近及远、按顺序展开：

1. **当前会话上下文**：先使用会话已经带上的内容。
2. **最近 30 天（插件注入）**：插件把最近窗口内每天的文件位置与 `index` 直接带进上下文；若检索目标落在窗口内，直接读取当天文件。
3. **全部历史目录**：从用户描述中提取 1–3 个区分度最高的名称、对象或关键短语（专有名称、具体对象、关键动作、数字/日期），扫描年度目录：

```bash
grep -HniE '检索词a|检索词b|检索词c' /.agents/nutstore-sync/memory/catalog/*.tsv
```

候选行过多时，再做交集过滤：

```bash
grep -HniE '检索词a|检索词b' /.agents/nutstore-sync/memory/catalog/*.tsv | grep -iE '检索词c|检索词d'
```

4. **读取原文**：由命中行日期推导路径，读取当日完整记忆：

```bash
grep -n '' /.agents/nutstore-sync/memory/archive/<YYYY>/<YYYY-MM-DD>.md
```

需要更多背景时才读整个文件，不要无谓地把全部档案读入上下文。

## 未命中时的降级

`catalog` 不保证能命中所有自然语言提问（用户措辞可能不同）。未命中时按序降级：

1. 扫描全部归档文件的原始 frontmatter `index` 行：

```bash
grep -RnE '^index:.*(检索词a|检索词b)' /.agents/nutstore-sync/memory/archive
```

2. 仍未命中，才扫描正文——全库扫描是最后的恢复路径，低频、昂贵，不是日常检索手段：

```bash
grep -RniE '检索词a|检索词b|检索词c' /.agents/nutstore-sync/memory/archive
```

一旦上层找到正确文件，立即把对应日期行补齐/重建到 `catalog/<YYYY>.tsv`，让下次命中走正常索引路径。

## 重建 catalog

以下情况必须重建受影响年份的 TSV：

- 目录文件丢失或缺失日期行；
- 用户改动、删除或移动了历史记忆文件；
- 目录行的内容与文件 `index` 不一致；
- 检索结果指向不存在的文件；
- 执行过「修正与遗忘」之后。

重建只从日文件复制而来，不需要理解正文：

1. `find /.agents/nutstore-sync/memory/archive/<YYYY> -name '*.md'`，列出该年份全部文件；
2. 逐个读取 frontmatter，取 `date:` 与 `index:` 两行；
3. 拼成 `<date><TAB><index>`，重写 `catalog/<YYYY>.tsv`。

## 修正与遗忘

- **纠正**：尽量在历史文件外修正——在今天文件中追加一条更正记忆，用今天 `index` 记下被纠正的主题与新的正确信息；召回时更新近的更正优先。
- **忘记**：用户明确要求删除或遗忘目标记忆时，才允许删除或编辑对应历史内容；之后必须重建受影响年份的目录。

## 约束

- 只用 bash 工具集（find、grep、read/append、mv、mkdir）操作普通文本；不引入数据库、embedding、向量检索、搜索服务、知识图谱——这些都不是这个环境里的需求。
- 永远用日期文本或标题定位，不用行号（行号会漂移）。
- 记忆文件一旦写入就永不移动、永不重写；需要更正时按「修正与遗忘」处理。
- catalog 永远可重建，archive 永远不可覆盖。

综上：索引必须来自真实文件，检索链只能由近向远，降级路径不能成为常规路径。

