SSD Nodes Learn 🎉 VPS $5.50/月起
指南 Matt Connor作者: Matt Connor

Compartment 离线加密智能体记忆安全吗?

了解 Compartment 4.6.0 的离线威胁模型:XChaCha20-Poly1305、Argon2id、本地嵌入和真正删除能保护什么,以及代理读取明文、托管模型和丢失口令后会发生什么。

Compartment 的不同之处

Compartment 是一个智能体记忆存储系统。它会在创建每条记录的机器上对记录进行加密,并且从不连接网络服务。有两点使它区别于其他智能体记忆系统。保管库是一个密封文件,只有您的口令短语可以将其打开;嵌入步骤在本地运行,因此记忆文本不会被发送到任何地方进行向量化。版本 4.6.0 于 10 August 2026 发布,许可证为 Apache-2.0,可从 PyPI 安装。

这是一项威胁模型声明,因此本指南将其作为声明来处理。静态数据加密和离线设计可以保护特定范围内的内容,但无法保护其他内容。第二天出现的问题就集中在这个差距上。

本指南依据项目自身的文档和发布说明编写,相关资料查阅于 11 August 2026。除命令行工具外,Compartment 还提供桌面应用程序、macOS 菜单栏项目和 Windows 通知区域图标;自动化容器无法驱动口令短语提示。以下内容应视为文档记录的行为,而不是本指南实际测量的行为。在将任何真实数据交给它之前,请先在备用机器上运行测试。

静态加密实际保护什么

该保险库使用 XChaCha20-Poly1305 进行加密。这是一种 AEAD(带关联数据的认证加密)算法。保存主密钥的密钥槽使用 Argon2id 进行封装。Argon2id 是一种密码哈希函数,设计目标是运行缓慢且需要大量内存。由此可知两点。窃取的磁盘、旧备份或支持工单中的文件副本,只是一串无意义的字节。文件打开时,即使只有一个比特发生翻转,也会认证失败。因此,数据损坏会表现为明确的错误,而不是返回错误结果。

嵌入向量也会加密,这一点比看起来更重要。嵌入向量不是哈希值。有关嵌入向量逆向的研究表明,仅凭向量本身就可以恢复原始文本中可读的片段。因此,将明文向量索引放在加密数据库旁边,几乎等同于让数据库处于开放状态。Compartment 不会将明文索引写入磁盘。

删除是真正的删除。每条记录都有自己的密钥,compartment forget --shred 会销毁该密钥。因此,遗留的密文无法被任何人解密,包括您自己。相比之下,从数据库文件中删除一行后,该行通常仍会在空闲页中保持可读,直到其他数据覆盖它。

离线运行是另一半保障。不会上传任何数据,因此没有供应商账户保存您的记忆,也没有可能泄露这些记忆的 API 密钥。

Compartment 无法防护的内容

保护范围止于保险库边界,而这个边界比看起来更近。

代理会读取明文。 Recall 会解密记忆,并将文本交给代理。如果该代理是托管模型,记忆会随下一条提示词发送给模型提供商,就像上下文窗口中的其他内容一样。静态加密可以保护文件,但无法保护检索过程。因此,避免将机密交给 AI 代理中的规则不会因为存储已加密而放宽:将密码保存为记忆,就等于安排系统自动将密码粘贴到提示词中。

运行中的机器上,已解锁的保险库就是开放的。 项目的安全说明明确指出了这一点。保险库解锁期间,主密钥和工作集都位于 RAM 中;Python 无法保证缓冲区已清除;swap 或休眠映像还可能将这些内存写入磁盘。以您的用户身份运行的恶意软件无需破解密码,因为它可以请求已经解锁的保险库。

调用方身份是声明式的。 可以按调用方限制命名空间,但调用方名称来自宿主进程。因此,虚报名称的宿主会获得它声称拥有的授权。命名空间权限用于组织资源,不是防御恶意本地程序的安全边界。

安全擦除无法覆盖副本。 forget --shred 会销毁当前文件中的密钥。在擦除前创建的备份仍然保存该记录,也仍可使用当天的口令短语打开。

弱口令短语会使其他措施失去意义。 Argon2id 会增加每次猜测的成本,但无法保护出现在词典中的口令短语。

从固定版本安装 Compartment

Compartment 需要 Python 3.11 或更高版本。该项目更新很快,截至 2026 年 8 月 10 日,PyPI 上已有 30 个版本。因此,安装时应固定版本,不要直接安装当天的最新版本。

python3 --version
pip install "compartment==4.6.0"
compartment --version
compartment init

compartment --version 应输出已固定的版本。如果 Shell 返回 compartment: command not found,说明安装目录不在 PATH 中。在大多数系统上,该目录是 ~/.local/binpipx install compartment==4.6.0uv tool install compartment==4.6.0 会自行管理路径,因此不会出现此问题。

compartment init 会要求输入两次密码短语,输入时不会回显任何内容。该密码短语是唯一的密钥。项目不会生成密码或恢复短语,这是有意设计的:软件不会持有任何您无法控制的凭据。

在将其他组件连接到它之前,先检查安装结果。

compartment status

正常的保险库会报告已解锁。如果报告已锁定,请运行 compartment unlock 并输入密码短语。重启后保险库会再次锁定,因为保持其解锁状态的凭据依赖于每次启动时生成的密钥。在 macOS 上,compartment unlock --keychain 会将该凭据存储到系统钥匙串中,从而选择在重启后继续保持解锁状态。

数据实际存储在哪里

默认保险库位于 ~/.compartment/memory.vault。在任意命令中使用 --vault PATH 可指定其他位置,也可以设置 COMPARTMENT_VAULT 环境变量。

这个文件就是完整的数据存储。文件开头是包含格式版本和 Argon2id 密钥槽的标头,随后是密封载荷,最后是随着新记忆写入而追加的日志条目。每个日志条目都包含自身长度,以及该长度对应的 CRC(循环冗余校验)。因此,因崩溃导致写入中断时,程序会将其识别为截断条目,而不会将其当作数据读取。压缩过程会序列化保险库,写入临时文件并执行 fsync,然后将其重命名为目标文件,因此读取程序永远不会看到写入不完整的保险库。

实际好处是:备份脚本只需复制一个路径。缺点是:你不能对它运行 grep,也不能在文本编辑器中修复它。如果你希望获得可以使用 cat 读取并提交到 git 的记忆,Memmy 的本地纯文本记忆文件提供的是相反的取舍。两种方式都合理,具体取决于你担心的是笔记本被盗,还是工具损坏。

compartment uninstall 会删除软件,但保留保险库。只有确实要删除保险库时,才传入 --purge

接入智能体

一条命令即可接入受支持的客户端。

compartment integrate --list
compartment integrate claude

对于 Claude Code,该命令会先备份文件,然后写入 MCP(模型上下文协议)服务器条目和 PostToolUse 钩子到 ~/.claude/settings.json,在 ~/.claude/skills/ 下安装 /compartmentalize 技能,并向 ~/.claude/CLAUDE.md 添加一个受管理代码块,告知智能体 Compartment 优先于它原先使用的基于文件的记忆。确认两部分配置:

compartment hook status
compartment recent

如需手动注册服务器:

claude mcp add --scope user compartment -- \
    compartment --vault ~/.compartment/memory.vault --caller claude-code serve

其他支持 MCP 的主机也使用同一个服务器,但使用各自的调用方名称。

{ "mcpServers": { "compartment": {
    "command": "compartment",
    "args": ["--vault", "/path/to/memory.vault",
             "--caller", "your-agent-name", "serve"] } } }

为每个主机设置不同的 --caller 值。审计日志会记录此值,命名空间授权也以此值为依据写入,因此多个主机共用同一名称会使这两项功能都失效。

如果 Claude Code 已经将事实写入自己的记忆文件,compartment import-claude --dry-run 会先显示将要迁移的内容,不会立即执行迁移。请先阅读Claude Code 会在记忆文件中保留哪些内容,因为将一年的笔记导入新的存储库,会让记忆存储填满没人打算保留的内容。

本地 vault 的速度如何

以下数据是该项目为个人规模 vault 发布的指标。数据来自项目文档,不是本次运行的实测结果。

ChartCompartment published local latency, milliseconds
The data behind this chart
[
  {
    "label": "Store one memory, end to end",
    "latency_ms": 40
  },
  {
    "label": "Embed one memory, bundled model",
    "latency_ms": 25
  },
  {
    "label": "Hybrid search, median",
    "latency_ms": 11.6
  },
  {
    "label": "Vector search at 20k records, p95",
    "latency_ms": 0.68
  }
]

存储一条记忆的延迟为 40 ms;对两万条记录执行向量搜索时,95% 分位延迟为 0.68 ms。该项目主张将记忆保留在本地,依据的是一个简单的计算:托管记忆 API 的一次网络往返通常比这里执行完整混合搜索的 11.6 ms 中位延迟更高。

两个设计细节解释了这些搜索数据。在记录数低于两万时,Compartment 会将查询与每个向量进行比较,因此召回结果天然是精确的,而不是近似结果。超过该数量后,它会切换到 HNSW(分层可导航小世界)索引。这是一种近似索引,以少量召回率换取更高速度。vault 还会记录 embedding model 的 SHA-256 哈希,并拒绝使用不同的模型打开 vault。原因是来自两个不同模型的向量可以在不报错的情况下进行比较,但返回的分数没有意义。

备份,以及明年仍可打开的副本

锁定的保管库是一个可移植文件,因此移动它就是复制它。

compartment lock
scp ~/.compartment/memory.vault other-machine:
compartment --vault memory.vault unlock

先锁定它。代理仍在写入时进行复制,可能会捕获一条正在追加的日志记录。虽然 CRC 帧结构允许读取器跳过末尾的残片,但其中的内存内容已经丢失。compartment lock --sign 使用 Ed25519 清单封存文件,因此接收计算机无需持有密码短语,也能验证副本是否完整到达。

由于文件已经封存,普通云存储可以安全存放它。这正是静态加密直接发挥作用的地方:备份目标永远看不到任何内存内容。

需要注意两点。安全擦除不会影响备份,因此今天执行加密擦除的记录,在上周的副本中仍可被持有上周密码短语的人读取。compartment export --plaintext 会将整个保管库以未加密形式写出,这适合迁移到其他系统,但不应将生成的文件留在 ~/Downloads 中。

保留少量副本,并标注日期。没有人清理时,内存存储就会变成负担;过期的代理记忆为何会悄然污染检索 说明了这一点。

密钥处理、轮换和第二因素

compartment rekey
compartment 2fa enable
compartment 2fa status

rekey 会在当前文件的 keyslot 中重新封装主密钥,从而更改密码短语。旧副本仍使用旧密码短语,因为其中的字节在更改前就已封存,之后不会回溯修改这些字节。请同时轮换这些副本,或接受已废弃的密码短语仍可打开某些内容这一事实。

2fa enable 会添加一个 keyfile,作为第二因素与密码短语共同参与密钥派生,因此打开保险库需要同时提供两者。这也会使可能丢失的凭据数量翻倍。请将 keyfile 保存在不存放保险库的机器上。

对于脚本和 CI(持续集成),密码短语可以通过 COMPARTMENT_PASSPHRASE 环境变量传入,unlock --passphrase-stdin 则从管道中读取。优先使用管道。其他由同一用户运行的进程可以读取环境变量,而且环境变量通常会出现在作业日志中。

审计历史采用哈希链,compartment audit verify 会遍历该链并报告第一个断开的链接。每次恢复后都应运行它,因为文件被静默截断时,通常会在此时暴露出来。

丢失密码短语后会发生什么

什么也不会发生,这正是设计目标。没有重置功能、恢复短语,也没有可供写入的地址,因为除了您的记忆和可选的密钥文件外,密钥没有任何副本存在。保管库仍然只是一个由看似随机的字节组成的文件。

因此,恢复计划不是针对保管库的计划,而是针对密码短语的计划。在运行 compartment init 的当天,将密码短语记录到密码管理器中。然后进行测试:锁定保管库,仅使用您记录的内容将其解锁;确认可以解锁后,再让代理开始填充密码。

隔离环境还是内存服务器

Compartment 从设计上就是单机应用。共享数据意味着复制已锁定的文件,或执行导出和导入;它不支持并发写入。因此,笔记本电脑和工作站同时指向同一个文件时,会互相覆盖修改内容。

如果多台机器需要同时访问同一份内存,这就是服务器要解决的问题。在 VPS 上自托管 Mem0 内存服务器可以解决这一问题:提供一个端点,供多个客户端使用,并让内存在笔记本电脑之外持续保存。但必须明确它的代价。该服务器运行的进程可以读取它存储的数据,因此您的威胁模型现在还包括 VPS,以及所有能够访问其 API 的人员。

应根据您实际担心的数据损失来选择。如果您担心笔记本电脑被盗,或供应商读取您的笔记,那么加密本地存储库更适合。如果您担心代理在切换机器后立即忘记所有内容,那么应选择服务器。

FAQ

Compartment 的加密实际保护什么?

它保护文件本身。保险库使用 XChaCha20-Poly1305 封装,密钥槽使用 Argon2id 派生并封装,嵌入向量也会加密。因此,即使磁盘被盗或旧备份泄露,得到的也只是无法读取的字节。它不保护正在运行的计算机上已解锁的保险库,因为保险库打开期间主密钥会驻留在 RAM 中;它也不限制代理在记忆以明文形式返回后如何使用该记忆。

如果 Compartment 处于离线状态,我的记忆对模型提供商是私密的吗?

只有在记忆被召回之前是私密的。记忆的存储和搜索都不需要网络,嵌入模型也在本地运行,因此写入时不会有任何内容离开计算机。在读取时,代理会收到明文;如果代理使用的是托管模型,该记忆就会进入提示词,并像上下文窗口中的其他内容一样传输给提供商。不要将凭据存储为记忆。

如果我丢失了 Compartment 口令,会发生什么?

保险库将无法恢复,这是有意设计的。Compartment 不生成种子或恢复短语,也不持有任何不由您持有的凭据,因此没有可重置的内容。请将口令存入密码管理器,将任何 2FA 密钥文件保存在存储保险库的计算机之外,并在保险库存入任何重要内容前确认您可以解锁副本。

两台计算机可以共享一个 Compartment 保险库吗?

不能同时共享。已锁定的保险库是一个可移植的单文件,文档规定的操作流程是先锁定它,再复制文件,然后在另一台计算机上使用 --vault 解锁。它不支持并发访问,因此两台计算机同时写入同一个文件会导致记忆丢失。需要并发访问时,请运行记忆服务器。

#agent-memory#compartment#encryption#offline#privacy