微信扫码
添加专属顾问
我要投稿
Clawdbot的本地记忆系统让AI真正实现个性化,彻底摆脱云端限制,打造完全属于你的智能助手。核心内容: 1. Clawdbot本地记忆系统的独特优势与工作原理 2. 上下文与记忆的关键区别及实现方式 3. 开源特性带来的透明可控与隐私保护
原文:How Clawdbot Remembers Everything
作者:Manthan Gupta
Clawdbot (译者记:由于Anthropic寄了律师函,已经被迫改名为Moltbot了)是由 Peter Steinberger 创建的开源个人 AI 助手(MIT 许可),在撰写本文时,它在 GitHub 上已获得超过 32,600 颗星(译者记:现在已经8.3万星了)。与运行在云端的 ChatGPT 或 Claude 不同,Clawdbot 在你的本地机器上运行,并与你已经使用的聊天平台集成,比如 Discord、WhatsApp、Telegram 等。
让 Clawdbot 与众不同的是它能够自主处理现实世界的任务:管理邮件、安排日历事件、办理航班值机,以及按计划运行后台任务。但真正吸引我的是它的持久记忆系统(persistent memory system),能够 24/7 保持上下文留存(context retention),记住对话并无限期地在过往交互基础上延展。
如果你读过我之前关于 ChatGPT 记忆 和 Claude 记忆 的文章,你会知道我对不同 AI 产品如何处理记忆非常着迷。Clawdbot 采用了截然不同的方法:不是基于云端、由公司控制的记忆,而是把一切都保存在本地,让用户完整拥有自己的上下文和技能。
让我们深入看看它如何运作。
在深入记忆之前,先看看模型在每次请求中看到什么:
AgentS.md、SOUL.md 等)
[2] 对话历史(Conversation History)(消息、工具调用、压缩摘要)
[3] 当前消息(Current Message)" data-show-line-number="false" style='box-sizing: border-box;margin: 0px;padding: 0.5em 1em 1em;border: 0px solid rgb(229, 229, 229);outline-color: oklab(0.144521 0.00000657141 0.00000288337 / 0.5);font-family: "Fira Code", Menlo, "Operator Mono", Consolas, Monaco, monospace;font-feature-settings: normal;font-variation-settings: normal;font-size: 12.96px;border-radius: 4px;display: -webkit-box;overflow-x: auto;text-indent: 0px;color: inherit;background: none;white-space: nowrap;'>[0] 系统提示词(System Prompt)(静态 + 条件指令)
[1] 项目上下文(Project Context)(引导文件: AGENTS.md、SOUL.md 等)
[2] 对话历史(Conversation History)(消息、工具调用、压缩摘要)
[3] 当前消息(Current Message)
系统提示词定义了代理的能力和可用工具。与记忆相关的部分是项目上下文,它包含了会被注入到每次请求中的、用户可编辑的 Markdown 文件:
这些文件与记忆文件一起存放在代理的工作区中,使整个代理配置透明且可编辑。
理解上下文(context)与记忆(memory)的区别,是理解 Clawdbot 的基础。
上下文是模型在一次请求中看到的全部内容:
Context = System Prompt + Conversation History + Tool Results + Attachments
上下文是:
记忆是存储在磁盘上的内容:
Memory = MEMORY.md + memory/*.md + Session Transcripts
记忆是:
代理通过两个专门工具访问记忆:
用途:在所有文件中查找相关记忆
{
"name": "memory_search",
"description": "Mandatory recall step: semantically search MEMORY.md + memory/*.md before answering questions about prior work, decisions, dates, people, preferences, or todos",
"parameters": {
"query": "What did we decide about the API?",
"maxResults": 6,
"minScore": 0.35
}
}
返回:
{
"results": [
{
"path": "memory/2026-01-20.md",
"startLine": 45,
"endLine": 52,
"score": 0.87,
"snippet": "## API Discussion\nDecided to use REST over GraphQL for simplicity...",
"source": "memory"
}
],
"provider": "openai",
"model": "text-embedding-3-small"
}
用途:在 memory_search 之后读取具体内容
{
"name": "memory_get",
"description": "Read specific lines from a memory file after memory_search",
"parameters": {
"path": "memory/2026-01-20.md",
"from": 45,
"lines": 15
}
}
返回:
{
"path": "memory/2026-01-20.md",
"text": "## API Discussion\n\nMet with the team to discuss API architecture.\n\n### Decision\nWe chose REST over GraphQL for the following reasons:\n1. Simpler to implement\n2. Better caching\n3. Team familiarity\n\n### Endpoints\n- GET /users\n- POST /auth/login\n- GET /projects/:id"
}
没有专用的 memory_write 工具。代理会使用标准的 write 和 edit 工具将内容写入记忆文件,就像处理任何文件一样。由于记忆本质上是 Markdown,你也可以手动编辑这些文件(它们会自动重新索引)。
写到哪里由 AGENTS.md 的提示驱动:
自动写入也会在预压缩刷新和会话结束时发生(后文会介绍)。
Clawdbot 的记忆系统建立在一个原则之上:"记忆就是代理工作区里的纯 Markdown"。
记忆位于代理的工作区(默认:~/clawd/):
~/clawd/
├── MEMORY.md - Layer 2: 长期整理的知识
└── memory/
├── 2026-01-26.md - Layer 1: 今天的笔记
├── 2026-01-25.md - 昨天的笔记
├── 2026-01-24.md - ...以此类推
└── ...
层 1:每日日志 (memory/YYYY-MM-DD.md)
这些是追加式的每日笔记,代理会在一天中持续写入。当代理想记住某些事,或被明确要求记住某些事时,它就会写在这里。
# 2026-01-26
## 10:30 AM - API 讨论
与用户讨论 REST vs GraphQL。决定:使用 REST 以简化实现。
关键端点:/users、/auth、/projects。
## 2:15 PM - 部署
将 v2.3.0 部署到生产环境。无问题。
## 4:00 PM - 用户偏好
用户提到比起 JavaScript 更喜欢 TypeScript。
层 2:长期记忆 (MEMORY.md)
这是整理过的、持久的知识。代理会在学到重要事件、观点、决策、意见和经验时写到这里。
# 长期记忆
## 用户偏好
- 比起 JavaScript 更喜欢 TypeScript
- 喜欢简洁的解释
- 正在开发 "Acme Dashboard" 项目
## 重要决策
- 2026-01-15:选择 PostgreSQL 作为数据库
- 2026-01-20:采用 REST 而非 GraphQL
- 2026-01-26:使用 Tailwind CSS 进行样式设计
## 关键联系人
- Alice (alice@acme.com) - 设计负责人
- Bob (bob@acme.com) - 后端工程师
AGENTS.md 文件(会自动加载)包含如下指令:
## 每次会话
在做任何其他事情之前:
1. 读取 SOUL.md - 这定义了你是谁
2. 读取 USER.md - 这定义了你在帮助谁
3. 读取 memory/YYYY-MM-DD.md(今天和昨天)以获取最近上下文
4. 如果在主会话(与人类的直接聊天)中,也要读取 MEMORY.md
不要请求许可,直接执行。
当你保存一份记忆文件时,背后会发生这些步骤:
┌─────────────────────────────────────────────────────────────┐
│ 1. 文件已保存 │
│ ~/clawd/memory/2026-01-26.md │
└─────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ 2. 文件监控器检测到变化 │
│ Chokidar 监控 MEMORY.md + memory/**/*.md │
│ 防抖 1.5 秒以批量处理快速写入 │
└─────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ 3. 分块(Chunking) │
│ 分割为约 400 token 的块,重叠 80 token │
│ │
│ ┌────────────────┐ │
│ │ 块 1 │ │
│ │ 行 1-15 │──────┐ │
│ └────────────────┘ │ │
│ ┌────────────────┐ │ (80 token 重叠) │
│ │ 块 2 │◄─────┘ │
│ │ 行 12-28 │──────┐ │
│ └────────────────┘ │ │
│ ┌────────────────┐ │ │
│ │ 块 3 │◄─────┘ │
│ │ 行 25-40 │ │
│ └────────────────┘ │
│ │
│ 为什么是 400/80?平衡语义连贯性与粒度。 │
│ 重叠确保跨越块边界的事实被两者捕获。两个值都可配置。 │
└─────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ 4. 嵌入(Embedding) │
│ 每个块 -> 嵌入提供商 -> 向量 │
│ │
│ "讨论了 REST vs GraphQL" -> │
│ OpenAI/Gemini/本地 -> │
│ [0.12, -0.34, 0.56, ...] (1536 维) │
└─────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ 5. 存储 │
│ ~/.clawdbot/memory/<agentId>.sqlite │
│ │
│ 表: │
│ - chunks (id, path, start_line, end_line, text, hash) │
│ - chunks_vec (id, embedding) -> sqlite-vec │
│ - chunks_fts (text) -> FTS5 全文 │
│ - embedding_cache (hash, vector) -> 避免重新嵌入 │
└─────────────────────────────────────────────────────────────┘
sqlite-vec 是一个 SQLite 扩展,允许在 SQLite 内直接进行向量相似度搜索,无需外部向量数据库。
FTS5 是 SQLite 内置的全文搜索引擎,为 BM25 关键词匹配提供支持。两者结合,使 Clawdbot 能在单一轻量数据库文件中运行混合搜索(语义 + 关键词)。
当你搜索记忆时,Clawdbot 会并行运行两种搜索策略。向量搜索(vector search)用于语义匹配,BM25 搜索用于关键词匹配。
结果会用加权评分组合:
finalScore = (0.7 * vectorScore) + (0.3 * textScore)
为什么是 70/30?语义相似度是记忆召回的主要信号,但 BM25 关键词匹配能捕捉向量可能错过的精确术语(名称、ID、日期)。低于 minScore 阈值(默认 0.35)的结果会被过滤。所有这些值都可配置。
这保证了你无论是搜索概念("那个数据库的事")还是具体细节("POSTGRES_URL")都能得到好结果。
Clawdbot 支持多代理(multi-agent),每个代理的记忆完全隔离:
~/.clawdbot/memory/ # 状态目录(索引)
├── main.sqlite # "main" 代理的向量索引
└── work.sqlite # "work" 代理的向量索引
~/clawd/ # "main" 代理工作区(源文件)
├── MEMORY.md
└── memory/
└── 2026-01-26.md
~/clawd-work/ # "work" 代理工作区(源文件)
├── MEMORY.md
└── memory/
└── 2026-01-26.md
这些 Markdown 文件(真实来源)位于各自工作区,而 SQLite 索引(派生数据)位于状态目录。记忆管理器以 agentId + workspaceDir 为键,因此不会自动跨代理搜索。
代理能读取彼此的记忆吗?
默认不行。每个代理只看到自己的工作区。不过,工作区是软沙箱(默认工作目录),不是硬边界。代理理论上可以用绝对路径访问另一个工作区,除非你启用严格沙箱。
这种隔离有助于区分上下文。例如,用于 WhatsApp 的"个人"代理和用于 Slack 的"工作"代理,各自有独立的记忆与人格。
每个 AI 模型都有上下文窗口上限。Claude 为 200K tokens,GPT-5.1 为 1M。长对话最终会触及这个上限。
发生这种情况时,Clawdbot 会使用压缩(compaction):把更早的对话总结为紧凑摘要,同时保留最近消息。
┌─────────────────────────────────────────────────────────────┐
│ 压缩前 │
│ 上下文:180,000 / 200,000 tokens │
│ │
│ [回合 1] 用户:"让我们构建一个 API" │
│ [回合 2] 代理:"当然!你需要哪些端点?" │
│ [回合 3] 用户:"用户和认证" │
│ [回合 4] 代理:*创建 500 行 schema* │
│ [回合 5] 用户:"添加限流" │
│ [回合 6] 代理:*修改代码* │
│ ...(100 个更多回合)... │
│ [回合 150] 用户:"状态如何?" │
│ │
│ ⚠️ 接近限制 │
└─────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ 触发压缩 │
│ │
│ 1. 将回合 1-140 总结为紧凑摘要 │
│ 2. 保持回合 141-150 完整(最近上下文) │
│ 3. 将摘要持久化到 JSONL 记录文件 │
└─────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ 压缩后 │
│ 上下文:45,000 / 200,000 tokens │
│ │
│ [摘要] "构建了带有 /users、/auth 端点的 REST API。 │
│ 实现了 JWT 认证、限流(100 次/分钟)、 │
│ PostgreSQL 数据库。部署到 staging v2.4.0。 │
│ 当前重点:生产部署准备。" │
│ │
│ [回合 141-150 保持原样] │
│ │
└─────────────────────────────────────────────────────────────┘
自动:接近上下文上限时触发
手动:使用 /compact 命令
`/compact`
关注决策与未决问题
与一些优化不同,压缩会持久化到磁盘。摘要写入会话的 JSONL transcript 文件,因此未来会话会从压缩后的历史开始。
基于 LLM 的压缩是有损的。重要信息可能被总结掉并丢失。为了解决这个问题,Clawdbot 使用预压缩记忆刷新。
┌─────────────────────────────────────────────────────────────┐
│ 上下文接近限制 │
│ │
│ ████████████████████████████░░░░░░░░ 75% 的上下文 │
│ ↑ │
│ 超过软阈值 │
│ (contextWindow - reserve - softThreshold)│
└─────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ 静默记忆刷新回合 │
│ │
│ 系统:"预压缩记忆刷新。现在存储持久记忆 │
│ (使用 memory/YYYY-MM-DD.md)。 │
│ 如果没有要存储的,回复 NO_REPLY。" │
│ │
│ 代理:审查对话中的关键信息 │
│ 将关键决策/事实写入记忆文件 │
│ -> NO_REPLY(用户什么都看不到) │
└─────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ 压缩安全进行 │
│ │
│ 重要信息现在已在磁盘上 │
│ 压缩可以继续而不会丢失知识 │
└─────────────────────────────────────────────────────────────┘
记忆刷新可以在 clawdbot.yaml 或 clawdbot.json 文件中配置。
agents:
defaults:
compaction:
reserveTokensFloor: 20000
memoryFlush:
enabled: true
softThresholdTokens: 4000
systemPrompt: "会话接近压缩。现在存储持久记忆。"
prompt: "将持久笔记写入 memory/YYYY-MM-DD.md;如果没有要存储的,回复 NO_REPLY。"
工具结果可能非常大。一次 exec 命令可能输出 50,000 个字符的日志。剪枝会修剪这些旧输出而不重写历史。这是有损过程,旧输出无法恢复。
┌─────────────────────────────────────────────────────────────┐
│ 剪枝前(内存中) │
│ │
│ 工具结果(exec):[50,000 字符的 npm install 输出] │
│ 工具结果(read):[大型配置文件,10,000 字符] │
│ 工具结果(exec):[构建日志,30,000 字符] │
│ 用户:"构建成功了吗?" │
└─────────────────────────────────────────────────────────────┘
│
▼(软修剪 + 硬清除)
┌─────────────────────────────────────────────────────────────┐
│ 剪枝后(发送到模型) │
│ │
│ 工具结果(exec):"npm WARN deprecated...[已截断] │
│ ...Successfully installed." │
│ 工具结果(read):"[旧工具结果内容已清除]" │
│ 工具结果(exec):[保留 - 太近未剪枝] │
│ 用户:"构建成功了吗?" │
└─────────────────────────────────────────────────────────────┘
磁盘上的 JSONL 文件:未改变(完整输出仍在)
Anthropic 会缓存提示词前缀最多 5 分钟,以降低重复调用的延迟和成本。在 TTL 窗口内发送相同提示词前缀时,缓存 token 的成本约低 90%。TTL 过期后,下一个请求需要重新缓存整个对话历史,成本回到完整的"缓存写入"价格。
问题在于:如果会话空闲超过 TTL,下一次请求就会失去缓存,需要以全价重新缓存完整对话历史。
缓存 TTL 剪枝通过检测缓存是否过期,并在下一次请求前裁剪旧工具结果,来降低重缓存成本:更小的提示词意味着更低成本。
agent:
contextPruning:
mode: "cache-ttl" # 仅在缓存过期后剪枝
ttl: "600" # 匹配你的 cacheControlTtl
keepLastAssistants: 3 # 保护最近的工具结果
softTrim:
maxChars: 4000
headChars: 1500
tailChars: 1500
hardClear:
enabled: true
placeholder: "[旧工具结果内容已清除]"
会话不会永远存在。它们会基于可配置规则重置,从而形成自然边界。默认行为是每天重置,但也有其他模式可选。
当你运行 /new 启动新会话时,会话记忆钩子可以自动保存上下文:
/new
│
▼
┌─────────────────────────────────────────────────────────────┐
│ 会话记忆钩子已触发 │
│ │
│ 1. 从结束的会话中提取最后 15 条消息 │
│ 2. 通过 LLM 生成描述性 slug │
│ 3. 保存到 ~/clawd/memory/2026-01-26-api-design.md │
└─────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ 新会话开始 │
│ │
│ 之前的上下文现在可以通过 memory_search 搜索 │
└─────────────────────────────────────────────────────────────┘
Clawdbot 的记忆系统之所以成功,是因为它遵循了几个关键原则:
记忆是纯 Markdown。你可以阅读、编辑、版本控制它。不需要不透明的数据库或专有格式。
不是把所有上下文都塞进去,而是搜索真正相关的内容。这让上下文更聚焦,成本更低。
重要信息存于磁盘文件,而不只是对话历史里。压缩也无法摧毁已保存的内容。
单纯向量搜索会遗漏精确匹配,单纯关键词搜索会错过语义。混合两者兼得。
53AI,企业落地大模型首选服务商
产品:场景落地咨询+大模型应用平台+行业解决方案
承诺:免费POC验证,效果达标后再合作。零风险落地应用大模型,已交付160+中大型企业
2026-01-29
看Claude Code如何用Rust重写千问语音模型
2026-01-29
Clawdbot进化速度已经离谱:突然开口说话,给自己捏脸,还能炒股砍价
2026-01-29
世界模型 LingBot-World,正式开源!
2026-01-29
ollama v0.15.2发布:新增Clawdbot集成指令,全面支持Ollama模型启动!
2026-01-29
Moltbot(原 Clawdbot)扫盲
2026-01-29
Clawdbot在国内没有用武之地
2026-01-29
Clawdbot 深度拆解: 7 个问题看懂它。
2026-01-28
ClawdBot 火爆全网,手把手教你如何部署,还能直接用钉钉操作!
2025-11-19
2025-12-22
2025-12-10
2025-11-17
2025-11-07
2026-01-12
2025-12-23
2026-01-06
2026-01-27
2025-11-06
2026-01-28
2026-01-26
2026-01-21
2026-01-21
2026-01-20
2026-01-16
2026-01-02
2025-12-24