内容
# 乌尔德 — 面向 AI 智能体的树状记忆
[](https://github.com/natureco-official/urdr/actions/workflows/ci.yml)
[](https://opensource.org/licenses/MIT)
[]()
[]()
> **"过去从未消逝。它甚至从未过去。"** — 威廉·福克纳
**乌尔德(Urðr)**(读音:*urth*)是一个开源的、面向 AI 编程智能体的树状结构记忆架构。命名源自北欧神话中掌管过去的诺恩女神,她居住在世界树尤格德拉西尔的根部。乌尔德为您的 AI 智能体提供了一个持久的、有组织的、快速检索的记忆系统,该系统在多个会话中保持一致。与向量数据库或不透明的记忆体不同,乌尔德的真实源头是一个普通的、可通过 Git 进行差异对比的 Markdown 树,由一个崩溃一致的事件日志支持 — 您可以清楚地看到智能体何时、如何以及为什么记住某些信息。
**证明,而非承诺:**
- **143 个自动化测试**,跨 Linux、macOS 和 Windows 平台的持续集成 — 实时更新的徽章。
- **0 个已知漏洞**(`npm audit`)。
- 每个原子写入都在每个实际崩溃点进行 **故障注入测试** — `before-fsync`、`before-rename`、`after-rename`、`before-directory-fsync` — 证明在写入过程中发生崩溃不会导致数据损坏或部分写入。
- **基准测试报告自身弱点**:89.7% 的一次调用召回率,降至 67% 的冲突/模糊键 — 已发布,而不是隐藏。
- [`ISSUES.md`](./ISSUES.md) 公开保存了两次独立的 AI 代码审计 — 包括修复前后的所有问题。
---
> 🤖 **您是正在阅读本文的 AI 智能体吗?** 请停止,立即阅读 **[AGENTS.md](./AGENTS.md)** — 其中包含您的直接指令。 onboarding完成后,请返回此处。(是的,本仓库旨在让您自行配置。)
---
## 为什么选择乌尔德?
当今的每个 AI 智能体都存在一个基本限制:**在多个会话之间没有持久的记忆**。大多数智能体每次启动时都是全新的,丢失了上下文、决策和已学到的经验。那些确实记住某些信息的智能体使用扁平文件,这些文件很快就会变得难以管理。
乌尔德通过 **树状记忆** 方法解决了这个问题 — 灵感来自人类如何将知识组织成类别,而不是扁平列表。
### 乌尔德的不同之处
| 特性 | 其他方法 | 乌尔德 |
|---------|-----------------|------|
| **结构** | 扁平文件、向量数据库或 SQL | 具有分支和叶节点的 4 根树 |
| **检索** | 全文件扫描或向量数据库/嵌入管道 | 优先考虑层次结构,然后是无依赖的混合备用(精确/正则表达式 + 三元组/拼写错误/土耳其后缀排名)— 无嵌入,无网络调用 |
| **真实源头** | 磁盘上的文件,仅此而已 | 追加只读、哈希链接的事件日志;Markdown 是生成的、仍然可以直接编辑的视图 |
| **一致性** | 通常在多个文件之间复制/复制 | 单个主要源 + 基于稳定 ID 的 `bkz:` 边,而不是自由文本 |
| **增长** | 无管理 — 变成一个杂乱的抽屉 | 有纪律的分支分割规则,以及当分支超出大小限制时的确定性自动分割建议 |
| **跨领域** | 临时处理 | 正式的跨领域协议 |
| **可审计性和删除** | 通常两者都没有,或者是裸露的不可逆删除 | 可选的每个叶节点的源信息;遗忘会从当前和未来的状态以及每个实时托管工件中删除叶节点,历史账本边界明确记录 |
| **维护** | 手动清理或没有 | 内存编译器提出具体的修复建议(分割、索引差异、引用修复)作为干燥运行计划,仅在明确批准后应用 |
| **智能体集成** | 特定于平台 | OpenCode、Claude Code、Codex CLI(MCP)、NatureCo、Hermes、OpenClaw |
---
## 架构概览
```
🌳 乌尔德记忆树
│
├── 🌱 根节点(4 个核心文件)
│ ├── root-0 → 索引(路由,所有根节点的映射)
│ ├── root-1 → 主题(人、项目、广泛的主题)
│ ├── root-2 → 技术(系统、安装、技术参考)
│ └── root-3 → 决策(ADR、约束、已学到的经验教训)
│
├── 🌿 分支(根节点内的 ## 头部)
│ └── 每个根节点通常有 5-9 个分支(一个实用的路由启发式)
│
└── 🍃 叶节点(特定的笔记、日期事件、事实)
└── 分支持有 30-50 个叶节点,然后分裂
```
### 4 步检索协议
```
1. 确定主题
2. 选择根节点(哪个领域?)
3. 选择分支(哪个 ## 头部?)
4. 读取叶节点(特定的笔记)
目标:<300 个标记符每次检索
```
---
## 快速入门
**3 个步骤,2 分钟。** 在下方选择您的智能体。
### 步骤 1:初始化记忆树
```bash
git clone https://github.com/natureco-official/urdr.git
cd urdr
# 创建 ~/my-memory 并包含 4 个根文件 + 个性
./scripts/init.sh --path ~/my-memory --lang zh
```
这会创建:
```
~/my-memory/
├── root-0-index.md # ← 路由映射
├── root-1-topics.md # ← 人、项目、主题
├── root-2-technical.md # ← 系统、API、配置
├── root-3-decisions.md # ← ADR、约束、经验教训
└── agent-personality.md # ← 智能体的个性
```
### 步骤 2:选择您的智能体 → 按照以下 3 行进行
| 智能体 | 操作 |
|-------|-------------|
| **OpenCode** | 将 `integrations/opencode/SKILL.md` 复制到您的 `.opencode/skills/` 目录 |
| **Claude Code** | 将 [`integrations/claude-code/CLAUDE.md`](integrations/claude-code/CLAUDE.md) 交给它并说“设置此内容” — 该文件会指导它安装 MCP 服务器、构建树、注册自身,并将 Claude Code 的内存索引指向乌尔德(使召回自动进行) |
| **OpenClaw** | 使用 `integrations/openclaw/README.md` 将索引公开为 `MEMORY.md`,并在 `memory/` 下保留域根节点 |
| **NatureCo CLI** | 将 `integrations/natureco/plugin.yaml` 复制到您的 NatureCo 配置中 |
| **Hermes** | 将 `integrations/hermes/skill.yaml` 复制到您的 Hermes 技能目录 |
| **Codex CLI** | `codex mcp add urdr -- npx -y urdr-mcp-server --root ~/my-memory` |
| **其他智能体?** | 在会话开始时加载 `root-0-index.md`,然后根据需要读取路由的域根节点。参见 `AGENTS.md` |
**找不到您的智能体?** 没关系。乌尔德只是 Markdown 文件。任何可以读取文件的智能体都可以使用它 — 告诉它在会话开始时加载 `root-0-index.md`,就完成了。
### 步骤 3:告诉您的智能体记住某些内容
```markdown
# 进入 root-1-topics.md → ## 项目
## 当前项目:我的应用程序
**04.07.2026 — 决定使用 SQLite 进行本地存储。**
- 替代方案:PostgreSQL(对于单用户来说过于复杂)
- 回滚可能:只需交换连接字符串
```
就是这样。您的智能体将在下一次会话中找到这个,理解上下文,并在此基础上继续。无需从零开始。
---
## 目录结构
```
urdr/
├── README.md # 本文
├── LICENSE # MIT
├── AGENTS.md # 面向使用乌尔德的 AI 智能体的指南
├── package.json # MCP 服务器包(唯一的真实 npm 依赖)
│
├── templates/ # 内存根节点模板(EN + TR)
│ ├── root-0-index.md
│ ├── root-1-topics.md
│ ├── root-2-technical.md
│ ├── root-3-decisions.md
│ ├── kök-0-indeks.md
│ ├── kök-1-konular.md
│ ├── kök-2-teknik.md
│ ├── kök-3-kararlar.md
│ └── agent-personality.md
│
├── protocols/ # 架构和协议文档
│ ├── architecture.md # 英文
│ ├── cross-cutting.md # 跨领域协议
│ ├── growth-rules.md # 何时和如何增长
│ └── hard-error-protocol.md # 错误恢复
│
├── integrations/ # 平台特定适配器
│ ├── opencode/SKILL.md
│ ├── claude-code/CLAUDE.md
│ ├── openclaw/README.md
│ ├── natureco/plugin.yaml
│ └── hermes/skill.yaml
│
├── scripts/ # 实用脚本(跨平台)
│ ├── init.sh # 初始化内存树(从一开始就诞生的事件日志)
│ ├── migrate.mjs # 事务性分支/根节点重构
│ ├── search.mjs # 混合分支感知搜索(Node,无 LLM)
│ ├── bench.mjs # 检索/保真度基准测试(Node,无 LLM)
│ ├── append.mjs # 并发安全的、事件日志感知的叶节点写入器
│ ├── lint.mjs # 内存健康审计(增长/引用/重复,CI 守护进程)
│ ├── compiler.mjs # 干燥运行修复计划(分割、索引差异、引用修复)
│ ├── forget.mjs # 永久叶节点墓碑 + 工件清理
│ ├── mcp-server.mjs # MCP 工具(在封闭的内存树根节点上)
│ ├── lib/ # 事件日志、事务、锁、解析器、遥测、自动分割
│ └── selftest.mjs # 演练每个工具(CI,3-OS 矩阵)
│
└── examples/ # 实际用例
└── basic-setup/
```
---
## 平台集成
| 平台 | 集成文件 | 状态 |
|----------|-----------------|--------|
| **OpenCode** | `integrations/opencode/SKILL.md` | ✅ 已准备好 |
| **Claude Code** | `integrations/claude-code/CLAUDE.md` | ✅ 已准备好 |
| **OpenClaw** | `integrations/openclaw/README.md` | ✅ 已准备好 |
| **NatureCo CLI** | `integrations/natureco/plugin.yaml` | ✅ 已准备好 |
| **Hermes** | `integrations/hermes/skill.yaml` | ✅ 已准备好 |
| **Codex CLI** | `scripts/mcp-server.mjs`(MCP,无需技能文件约定) | ✅ 已准备好 |
| **您的智能体?** | 只需读取 4 个 `root-*.md` 文件 → 参见 `AGENTS.md` | 🛠 任意 |
---
## MCP 服务器
直接使用 `npx` 运行已发布的包 — 无需单独的安装步骤。对于本地检出,首先运行 `npm ci`,然后使用存储库脚本。配置服务器时使用一个固定的文件系统根节点。工具调用的 `memoryDir` 值相对于此根节点;拒绝绝对路径、父目录遍历和解析到其外部的符号链接。
```bash
npx -y urdr-mcp-server --root ~/my-memory
# 或,从本地检出后使用 npm ci:
node scripts/mcp-server.mjs --root ~/my-memory
```
服务器公开了七个命名空间工具:`urdr_search`、`urdr_append`、`urdr_lint`、`urdr_compile_plan`、`urdr_apply_plan`、`urdr_forget_leaf` 和 `urdr_resume_forgetting`。编译计划是只读的;应用保留了已提交的树状态新鲜度检查,并且只接受通过全新受信任的干燥运行重现的操作。遗忘被标记和描述为一种后果严重的、用户触发的擦除操作,而恢复是一种已经提交的遗忘的幂等完成。
---
## 协议
乌尔德定义了三个核心协议,使记忆系统可靠:
### 1. 架构协议 (`protocols/architecture.md`)
基本的树状记忆结构:根节点、分支、叶节点和 4 步检索方法。
### 2. 跨领域协议 (`protocols/cross-cutting.md`)
处理自然属于多个根节点的信息。使用 **"单一主节点,多个 `bkz:`"** 规则以防止重复漂移。
### 3. 增长规则 (`protocols/growth-rules.md`)
有纪律的规则,用于何时添加分支、分割过大的分支或创建新根节点。防止“垃圾抽屉”问题。
---
## 检索安全网 (`scripts/search.mjs`)
4 步层次结构是 **主要** 路径 — 快速且廉价。但类别猜测有故障模式:如果智能体在错误的根节点中查找,存储的信息将被视为“未找到” — 对于用户来说,这与遗忘无法区分。
乌尔德提供了一个 **混合备用搜索**,在不影响架构优雅性的情况下弥补了这一缺陷:
```bash
# 当 4 步协议为空时,扫描所有内容(分支感知):
node scripts/search.mjs "sqltie karar" ~/my-memory
# → root-2-technical.md › ## APIs › **04.07.2026 — 选择 SQLite 进行本地存储**
# 在必须显式查询语法时,重写元字符自动检测:
node scripts/search.mjs "foo.bar" ~/my-memory --literal
node scripts/search.mjs "foo.*bar" ~/my-memory --regex
```
- **无 LLM,无嵌入,无网络调用** — 精确/正则表达式匹配,然后是基于三元组相似性的模糊排名,适用于轻微词干化的标记(带有土耳其语后缀剥离) — 捕捉拼写错误和不同词形变化,而纯粹的扫描则完全无法检测到。
- **ReDoS 安全** — 在单独的、可终止的子进程中运行正则表达式查询,并带有硬性截止时间;如果路径导致挂起,则会将其杀死并作为超时报告,而不是作为冻结。
- **跨平台** — 纯 Node.js。无需 `grep`/`rg`/`awk` 依赖(这些在原始 Windows 上不存在)。
- **分支感知** — 每个命中都报告 `file › ## branch › leaf`,因此智能体仍然获得结构化上下文。
- **遥测是可选且仅限聚合** — 默认情况下禁用,当关闭时在磁盘上完全无操作;启用时,仅记录层次结构/回退/未命中/超时计数器,绝不查询、结果或叶节点 ID。
- **可组合** — 以 `0` 退出表示命中,以 `1` 退出表示未命中(grep 惯例),或使用 `--json` 进行编程使用。
这大大减少了虚假的“未记住”结果:优先考虑层次结构,然后是混合的全树排名作为其下的安全网。
## 基准测试 (`scripts/bench.mjs`)
“无限内存”是一种说法,直到你测量它。`bench.mjs` 构建了一个合成树,其中包含可控的 **错误根节点** 叶节点(归档到一个根节点,但自然查询为另一个)和可控的 **冲突** 叶节点(近似重复内容,用拼写错误或不同的土耳其语后缀查询)— 衡量召回的诚实方式,因为如果每个键都是全局唯一的,则 100% 召回是无关紧要的,而与检索实际上有多好无关:
```bash
node scripts/bench.mjs --leaves 300 --ambiguity 0.3
```
```
🌳 乌尔德记忆基准测试
──────────────────────────────────────────────────────────────────
叶子:300 · 错误根节点:93(31.0%)· 冲突:94(31.3%)· 种子:42
生产者写入保真度 :100.0%(6/6 通过 appendLeaf + 事件日志)✓
稳定 ID 导入/预言保真度:100.0%(300/300)✓
召回率@1,层次结构感知,一次调用:89.7%
召回率@1,仅限全局:88.7%
召回率@1,辅助两次调用:89.7%
召回率@1,仅限唯一精确键:100.0%(206/206,一次调用)
召回率@1,冲突/模糊键:67.0%(63/94,一次调用)
辅助第二次调用救援:0 个叶子节点(0.0%)
平均一次调用延迟 :28.069 毫秒/查询(CPU,无 LLM/网络调用)
平均仅限全局延迟 :40.209 毫秒/查询(CPU,无 LLM/网络调用)
平均两次调用辅助延迟 :32.144 毫秒/查询(条件第二次调用)
平均一次调用结果大小 :~22 个标记
→ 一次调用召回率是生产 API/MCP 行为;辅助召回需要条件下的第二次调用。
```
写入保真度通过实际的 `appendLeaf()` 生产写入器衡量,而非原始文件写入。检索正确性根据 Rock 6A 稳定 ID 得分,而非文本匹配。macOS、Windows 和 Linux 上的结果相同(确定性种子)。使用它来证明架构在大量数据下有效 — 而不是在用户询问“为什么它不记得?”之前几个月后 — 到那时已经太晚了。
## 事件日志和事务 (`scripts/lib/event-log.mjs`, `scripts/lib/transaction.mjs`)
Markdown 文件是人类可读的表面;实际的真实源是 **追加只读、哈希链接的事件日志**(`.urdr/events.jsonl`)。每个叶节点都有一个稳定 ID(一个可往返的 `<!-- urdr:id:... -->` 注释),`bkz:` 引用解析为基于 ID 的边,而不是自由文本,并且多文件更改通过一个事务提交。直接编辑 Markdown 文件仍然完全受支持 — 一个协调步骤将它们与日志进行调和,如果在两个方向上更改同一个叶节点,则会标记一个真正的冲突(绝不自动合并)。
- **崩溃安全**。每次写入都经过 fsync 并原子重命名;在进程在发布过程中被终止后,事件感知的读取器立即看到正确的逻辑生成,而不是损坏状态或丢失的叶节点。下一个突变或显式协调/导入修复了部分物化的根 Markdown 文件;读取操作不会重写它们。
- **并发安全**。一个持久的租赁服务进程,在调用者的生命周期内重用,在其自己的计时器上续约每个锁,因此繁忙的写入器不会因虚假的“过时”窃取而失去锁。
- **可选的源信息**。任何叶节点都可以携带 `creator`、`timestamp`、`source`、`confidence`、`verification_state`、`verifier` 和 `validity_interval` 元数据 — 完全是增量的,不需要对现有叶节点进行迁移。
- **遗忘**。`scripts/forget.mjs` 在叶节点上创建一个墓碑,将其从当前和未来的状态中删除,并从每个实时托管的生成快照、恢复副本和已注册的导出中清除其字节。它不能在不破坏哈希链的情况下修改历史账本;此边界在 `protocols/architecture.md` 中记录,而不是隐藏的。
- **内存编译器 (`scripts/compiler.mjs`)**。将 lint 发现的问题转化为一个具体的干燥运行计划 — 确定性的分支分割建议(关键词/ Jaccard 聚类,无 ML)、索引差异和明确的引用修复 — 绑定到当前的事件日志头哈希。应用拒绝过时的计划和任何未经新鲜受信任的干燥运行重现的操作,然后以单个事务发布批准的操作。
```bash
node scripts/compiler.mjs ~/my-memory --out plan.json # 干燥运行,不会更改任何内容
node scripts/compiler.mjs ~/my-memory --apply plan.json # 应用已批准的计划
node scripts/forget.mjs ~/my-memory --id <稳定 ID> --reason "..."
```
## 并发安全写入 (`scripts/append.mjs`)
当多个写入者同时操作同一内存时,简单的“读取文件 → 重写文件”会导致数据丢失:两个写入者读取相同的版本,都进行追加,第二次写入会覆盖第一次。这是一个**真实**的场景 — 一个 NatureCo 网关运行 8 个消息通道(WhatsApp、Telegram、Signal、IRC、Mattermost、iMessage、SMS + 终端),所有通道都写入同一个共享树。
`append.mjs` 使得叶子节点的追加是原子化和序列化的:
```bash
node scripts/append.mjs ~/my-memory root-2-technical.md "APIs" "**04.07.2026 — 选择 SQLite — ok**"
```
- **租约锁,而不是简单的 advisory mkdir**。一个持久的租约服务进程,在调用者的生命周期内被重复使用,单独获取和续期每个锁 — 繁忙的写入者的阻塞事件循环不会导致假的“锁过期”抢占,而真正崩溃的写入者的锁仍然可以安全地被回收(令牌检查,因此前任所有者永远不能删除后继者的锁)。
- **写入通过事件日志**,而不是简单的文件重写 — 新的叶子节点获得一个稳定的 ID,并立即在提交状态下可见,无需单独的导入步骤。
- **仅追加** — 在正确的 `## 分支` 下插入(替换 `_No entries yet._`),永远不会覆盖兄弟叶子节点。
- **原子写入** — fsync + 临时文件 + 持久化重命名(平台特定:Linux/macOS 上的目录 fsync,Windows 上的 `MoveFileEx` 和 `MOVEFILE_WRITE_THROUGH`),因此永远不会观察到半写入的文件,写入过程中崩溃总是能干净地恢复。
在 Linux、macOS 和 Windows 上的 CI 中验证:6 个并发写入者 → 6 个叶子节点,无数据丢失,文件完整性完好。不同根文件的并发写入者现在通过一个事件日志序列化 — 单个权威哈希链的故意结果,而不是回归;保证正确性(无叶子节点丢失),而不是并行执行。
## 健康检查 (`scripts/lint.mjs`)
一个跨平台的命令审计检索失败的模式,当树增长时,并退出非零错误码(CI/预提交保护):
```bash
node scripts/lint.mjs ~/my-memory
```
1. **增长** — 根节点有 9+ 个分支,分支有 50+ 个叶子节点 → 分割信号
2. **索引膨胀** — 标志一个存储叶子节点而不是映射的 `root-0-index`(每次检索都会读取)
3. **bkz: 引用** — 损坏的引用(指向丢失的根节点)+ 过深的链条
4. **重复** — 树中近似相同的叶子节点 — “同一个事实在 5 个略有不同的地方”漂移
## 设计哲学
1. **结构优于内容** — 100 个有条理的笔记胜过 1000 个杂乱无章的笔记
2. **单一事实来源** — 每个事实只存在于一个地方;其他位置只引用它
3. **适龄分层** — 原始笔记随着时间推移成熟为分类知识
4. **检索速度优先** — 设计决策优先考虑查找信息的速度,而不是存储信息的数量
---
## 适用人群
- **AI 代理开发者**,他们需要跨会话的持久内存
- **团队**,他们使用 AI 编码助手,需要共享上下文
- **独立开发者**,他们希望 AI 记住决策和上下文
- **工具构建者**,他们创建需要结构化内存的智能系统
---
## 许可证
MIT — 使用、fork、适应。鼓励署名,但非必需。
---
## 词源
**Urðr**(古诺斯语:*Urðr*,英语:*Wyrd*)是北欧神话中三个诺恩女神之一,她们居住在世界树 Yggdrasil 的根部。Urðr 编织**过去** — 使她成为一个完美的命名,适用于一个存档决策、经验和上下文的内存系统。
她的姐妹们:
- **Verðandi** — 现在(正在形成)
- **Skuld** — 未来(将要发生)
他们一起从 Urðr 井中为 Yggdrasil 的根部浇水,使树保持活力。 🌳
---
## 更多来自 NatureCo
- [**Cupertino Terminal**](https://github.com/natureco-official/cupertino-terminal) — 一个适用于 Windows、macOS 和 Linux 的 macOS 级终端 — Rust 核心,无 Electron,带有端到端加密的 P2P 远程 shell
- [**NatureCo CLI**](https://github.com/natureco-official/natureco-cli) — 一个终端原生的 AI 助手:聊天、编码代理、自动化和 Telegram、Discord 和 Slack 上的机器人
- [**CodeDNA**](https://github.com/natureco-official/codedna) — 多少提交是由 AI 编写的,其作者是否真正理解它?
- [**NatureCo SDK**](https://github.com/natureco-official/natureco-sdk) — 用于 NatureCo API 的 JavaScript SDK — 构建 AI 聊天机器人并将其部署到任何地方
<sub> NatureCo 生态系统的一部分 — [natureco.me](https://natureco.me) · NatureCo ekosisteminin parçası</sub>
MCP 配置
以下是此 MCP Server 的配置信息,可直接复制到 Cursor 或其他 MCP 客户端中使用。
mcp.json
连接信息
猜你喜欢
暂无推荐服务器