先搞清楚三者的关系
LLM 是大脑,pi-mono 是身体,OpenViking 是海马体。
LLM 负责推理和决策,但天生无记忆——每次对话都是失忆状态。pi-mono 是 AI Agent 框架,给 LLM 装上工具调用、任务执行等能力,让它能真正干活。OpenViking 专门解决记忆问题,负责跨 session 的持久化存储与语义检索。三者组合,才构成一个"用过就记住、下次还认识你"的完整 Agent。
核心设计:工具优先,记忆为辅
这句话背后有一个值得注意的设计取舍。
主流做法是 RAG——每次对话开始前,系统自动检索历史记忆塞进上下文,LLM 被动接收。听起来省事,但问题很明显:LLM 不知道这些记忆从哪来、是否可信、当前场景是否真用得上。记忆变成噪音,上下文窗口被无效信息占满,反而干扰推理。
pi-mono 的选择刚好相反——记忆以工具形式存在,召回这个动作本身交给 LLM 来决策。Agent 在推理过程中自己判断:"我现在需要回忆什么吗?这件事值得记下来吗?"记忆从被动注入变成主动行为,和搜索网页、执行代码在逻辑上完全对等。
这样做的好处是:召回有明确意图,保存有明确判断,记忆的质量和相关性都更高。代价是 Agent 需要足够"聪明"才能知道什么时候该用记忆工具——但这正是现代 LLM 擅长的事。这个设计很实用,把复杂的记忆管理问题转化成了 LLM 本身就擅长的工具调用问题。
架构分两层
主动工具(Agent 自行决策调用):
recall_memory→ 语义搜索历史记忆save_memory→ 显式保存关键信息explore_memory→ 浏览记忆文件系统add_knowledge→ 索引本地文件/目录
被动钩子(透明自动执行,LLM 无感知):
before_agent_start→ 建立 OpenViking sessionsession_compact/shutdown→ 增量同步消息 + 触发记忆提取
底层是跑在 localhost:1933 的独立 Python 进程,通过 HTTP API 通信。
三层存储,各司其职
- 消息自动同步:钩子在 compact/shutdown 时静默追加对话内容
- 记忆提取:OpenViking 内部 LLM pipeline 在 commit 时自动抽取 preferences / entities / cases
- 主动召回/保存:Agent 自己调用工具决定存取
实际效果
Session 1:用户说"我喜欢用 anyhow 做 Rust 错误处理" → Agent 调用 save_memory 保存 → 关闭 pi-mono,OpenViking 自动提取写入 viking://user/memories/preferences/
Session 2(全新进程,零上下文):用户说"帮我写个 Rust 工具" → Agent 调用 recall_memory("Rust preferences") → 搜到上次的偏好,自动用 anyhow,不过度抽象
跨 session 的偏好记忆真正生效了,不需要用户重复说明。
容错设计:记忆是增强,不是依赖
这一点容易被忽略但非常关键——OpenViking 挂了,pi-mono 照跑:
health()检测失败 → 静默跳过,不注入系统提示- 工具调用失败 → 返回描述性文本,不抛异常
- 所有钩子 → try/catch 吞错误,主流程不受影响
记忆层的故障不会拖垮整个 Agent,这才是生产级的设计思路。
对于想给自己的 Agent 加上长期记忆的开发者来说,这套方案的核心启发在于:与其让系统自动往上下文里塞历史信息,不如把记忆做成工具,让 LLM 自己决定何时存、何时取。项目代码在 GitHub 的 pi-mono 仓库 feat/pi-viking-memory 分支下,感兴趣可以直接看实现。