OpenViking 项目实践:把 Agent 上下文做成可导航的虚拟文件系统
一句话定位:OpenViking 是火山引擎开源的 Agent Context Database,用文件系统范式统一管理 memory、resources 和 skills,让 Agent 通过目录、摘要、概览和递归检索按需获取上下文。
官网 :openviking.ai
类型 :Agent Context Database / 上下文文件系统 / Agentic RAG 基础设施
语言 :Python 为主,另含 Rust CLI、C++ 扩展等
协议 :主项目以 GitHub 仓库显示为 AGPLv3;CLI 和 examples 为 Apache 2.0,落地前应复核具体目录协议。
适合读者:正在做长程 Agent、上下文工程、项目资料检索、技能库、用户记忆和多源上下文治理的开发者。
项目导读
OpenViking 的核心判断是:Agent 的上下文不应该继续散落在向量库、代码、文档、用户画像和技能模块里,而应该统一组织成一个可导航、可分层、可观察的虚拟文件系统。它把 memory、resources、skills 映射到 viking:// 路径下,让 Agent 先定位目录,再逐层读取摘要、概览和细节。
如果把 Agent Memory 分成几条路线,OpenViking 更接近"上下文数据库"路线。它不只是记住用户偏好,也不只是做向量检索,而是把上下文管理升级成一套文件系统式的基础设施。
1. 核心结论
- OpenViking 的关键词不是"记忆 API",而是 Context Database:统一管理 memory、resources、skills。
- 它用
viking://虚拟文件系统解决上下文碎片化,让 Agent 像浏览目录一样访问上下文。 - 它用 L0 / L1 / L2 三层加载降低 token 成本:先看摘要,再看概览,最后按需读全文。
- 它的检索不是普通一次性 top-k,而是目录递归检索:先定位高相关目录,再在目录内部细搜和下钻。
- 它提供检索轨迹可视化,方便调试"为什么召回这段内容"。
- 它支持会话自迭代:会话结束后从用户反馈、工具结果、资源引用里抽取长期记忆,更新到用户和 Agent 目录。
2. 它要解决什么问题
传统 RAG 把资料切成 chunk 后丢进向量库,适合做普通文档问答,但对 Agent 长程任务会暴露几个问题。
第一是 上下文碎片化。
Agent 需要的上下文不只有文档,还包括:
- 用户长期偏好;
- 项目 README、API 文档、代码仓库;
- 工具调用经验;
- Agent 自己的技能和 instructions;
- 历史任务结果;
- 会话中产生的新记忆。
如果这些上下文散落在不同文件、向量库、规则文档和模块里,Agent 很难形成全局视图。
第二是 上下文成本膨胀。
长程任务每一步都会产生新材料。简单截断会丢信息,简单总结会丢证据,直接塞全文又会让 token 成本爆炸。
第三是 检索黑盒化。
普通向量检索返回几个相似 chunk,但很难解释:
- 为什么是这几个 chunk?
- 它们属于哪个目录或资源?
- 是否漏掉了同目录下更关键的文件?
- 如果召回错了,应该调 embedding、chunk,还是资料组织方式?
OpenViking 的解决思路是:不把上下文当一堆扁平文本,而是做成一个有路径、有层级、有轨迹的上下文文件系统。
3. 总体架构:上下文文件系统
OpenViking 把上下文统一映射到 viking:// 协议下。可以把它理解成 Agent 的虚拟资料盘:
text
viking://
├── resources/ # 项目文档、代码仓库、网页、知识库
├── user/ # 用户偏好、习惯、长期记忆
└── agent/ # Agent 技能、instructions、任务经验
这种组织方式有两个好处。
第一,Agent 不再只面对"相似文本块",而是面对"路径和目录"。它可以先判断自己要找的是用户偏好、项目资源还是技能经验。
第二,开发者可以观察上下文结构。错误召回不再只是"向量不准",还可能是目录组织、摘要层、概览层或资源导入出了问题。
4. L0 / L1 / L2:分层加载上下文
OpenViking 写入资源时,会把内容加工成三个层级:
| 层级 | 作用 | 适合什么时候读 |
|---|---|---|
| L0 Abstract | 一句话摘要,约百 token 级别 | 快速判断目录或文件是否相关 |
| L1 Overview | 概览,说明核心信息和使用场景 | Agent 规划、决定是否继续下钻 |
| L2 Details | 原始细节或完整内容 | 真正需要证据、代码、文档细节时 |
这和普通 RAG 的区别很大。
普通 RAG 常见做法是:query 进来,直接召回若干 chunk。
OpenViking 的做法更像:先看目录摘要,再看目录概览,必要时再打开原文。这会让上下文加载更像人类查资料,而不是盲目塞相似片段。
#mermaid-svg-KdKzaQV35hsXRQ1X{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-KdKzaQV35hsXRQ1X .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-KdKzaQV35hsXRQ1X .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-KdKzaQV35hsXRQ1X .error-icon{fill:#552222;}#mermaid-svg-KdKzaQV35hsXRQ1X .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-KdKzaQV35hsXRQ1X .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-KdKzaQV35hsXRQ1X .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-KdKzaQV35hsXRQ1X .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-KdKzaQV35hsXRQ1X .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-KdKzaQV35hsXRQ1X .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-KdKzaQV35hsXRQ1X .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-KdKzaQV35hsXRQ1X .marker{fill:#333333;stroke:#333333;}#mermaid-svg-KdKzaQV35hsXRQ1X .marker.cross{stroke:#333333;}#mermaid-svg-KdKzaQV35hsXRQ1X svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-KdKzaQV35hsXRQ1X p{margin:0;}#mermaid-svg-KdKzaQV35hsXRQ1X .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-KdKzaQV35hsXRQ1X .cluster-label text{fill:#333;}#mermaid-svg-KdKzaQV35hsXRQ1X .cluster-label span{color:#333;}#mermaid-svg-KdKzaQV35hsXRQ1X .cluster-label span p{background-color:transparent;}#mermaid-svg-KdKzaQV35hsXRQ1X .label text,#mermaid-svg-KdKzaQV35hsXRQ1X span{fill:#333;color:#333;}#mermaid-svg-KdKzaQV35hsXRQ1X .node rect,#mermaid-svg-KdKzaQV35hsXRQ1X .node circle,#mermaid-svg-KdKzaQV35hsXRQ1X .node ellipse,#mermaid-svg-KdKzaQV35hsXRQ1X .node polygon,#mermaid-svg-KdKzaQV35hsXRQ1X .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-KdKzaQV35hsXRQ1X .rough-node .label text,#mermaid-svg-KdKzaQV35hsXRQ1X .node .label text,#mermaid-svg-KdKzaQV35hsXRQ1X .image-shape .label,#mermaid-svg-KdKzaQV35hsXRQ1X .icon-shape .label{text-anchor:middle;}#mermaid-svg-KdKzaQV35hsXRQ1X .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-KdKzaQV35hsXRQ1X .rough-node .label,#mermaid-svg-KdKzaQV35hsXRQ1X .node .label,#mermaid-svg-KdKzaQV35hsXRQ1X .image-shape .label,#mermaid-svg-KdKzaQV35hsXRQ1X .icon-shape .label{text-align:center;}#mermaid-svg-KdKzaQV35hsXRQ1X .node.clickable{cursor:pointer;}#mermaid-svg-KdKzaQV35hsXRQ1X .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-KdKzaQV35hsXRQ1X .arrowheadPath{fill:#333333;}#mermaid-svg-KdKzaQV35hsXRQ1X .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-KdKzaQV35hsXRQ1X .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-KdKzaQV35hsXRQ1X .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-KdKzaQV35hsXRQ1X .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-KdKzaQV35hsXRQ1X .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-KdKzaQV35hsXRQ1X .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-KdKzaQV35hsXRQ1X .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-KdKzaQV35hsXRQ1X .cluster text{fill:#333;}#mermaid-svg-KdKzaQV35hsXRQ1X .cluster span{color:#333;}#mermaid-svg-KdKzaQV35hsXRQ1X div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-KdKzaQV35hsXRQ1X .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-KdKzaQV35hsXRQ1X rect.text{fill:none;stroke-width:0;}#mermaid-svg-KdKzaQV35hsXRQ1X .icon-shape,#mermaid-svg-KdKzaQV35hsXRQ1X .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-KdKzaQV35hsXRQ1X .icon-shape p,#mermaid-svg-KdKzaQV35hsXRQ1X .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-KdKzaQV35hsXRQ1X .icon-shape .label rect,#mermaid-svg-KdKzaQV35hsXRQ1X .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-KdKzaQV35hsXRQ1X .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-KdKzaQV35hsXRQ1X .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-KdKzaQV35hsXRQ1X :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 用户问题 / Agent 意图
L0 摘要:快速判断相关性
L1 概览:理解结构和用途
L2 细节:按需读取原文
注入 Agent 上下文
5. 目录递归检索:先定位,再下钻
OpenViking 的检索不是简单的一次性 top-k。它强调 Directory Recursive Retrieval,可以拆成五步:
- 意图分析:理解当前 query 可能需要哪些条件。
- 初始定位:通过语义检索找到高相关目录或片段。
- 目录内细搜:在高相关目录里继续二次检索。
- 递归下钻:如果目录下面还有子目录,继续向下探索。
- 结果聚合:把最相关的上下文组合返回给 Agent。
这解决了普通向量检索的一个痛点:一个 chunk 相似,不代表它所在的上下文完整。OpenViking 会把"这段内容在哪个目录下、同目录还有什么、是否需要继续下钻"纳入检索过程。
6. 会话自迭代:不只存用户记忆,也存 Agent 经验
OpenViking 还有一个重要能力:session management,也就是会话自迭代。
一次会话结束后,系统可以分析:
- 用户反馈;
- 工具调用结果;
- 资源引用;
- 任务执行经验;
- 出错与修复路径。
然后把值得沉淀的内容更新到 user 和 agent 相关目录。
官方文档提到的记忆类别包括 profile、preferences、entities、events、cases、patterns。可以理解为:
- 用户画像;
- 用户偏好;
- 关键实体;
- 重要事件;
- 案例经验;
- 行为或任务模式。
这让 OpenViking 不只是资料库,还能让 Agent 在长期使用中沉淀"怎么给这个用户做事""这个项目有哪些坑""哪些工具调用经验可以复用"。
7. 可观察检索轨迹
OpenViking 很强调 visualized retrieval trajectory。这个点在工程里很重要。
普通 RAG 失败时,开发者往往只能看到"召回了这几段 chunk",很难判断错因。OpenViking 保留目录浏览和文件定位轨迹,能让开发者看到:
- 检索从哪个目录开始;
- 哪些目录被判定相关;
- 是否进入了错误子目录;
- 最终为什么返回这段上下文;
- 应该优化资源组织、摘要层,还是检索策略。
这让上下文调试从黑盒向量检索,变成可观察的路径分析。
8. 和 Mem0、TencentDB-Agent-Memory、agentmemory 的区别
| 维度 | OpenViking | Mem0 | TencentDB-Agent-Memory | agentmemory |
|---|---|---|---|---|
| 核心定位 | 上下文数据库 / 虚拟文件系统 | 通用记忆 API | 分层记忆组织管线 | 外部记忆基础设施 |
| 管理对象 | memory、resources、skills | 对话抽取后的记忆事实 | 短期任务 + 长期用户记忆 | 会话、工具调用、文件访问、错误上下文 |
| 结构方式 | viking:// 目录树 |
事实文本 + metadata + index | Mermaid / JSONL / Markdown / L0-L3 | memory server + 混合索引 |
| 检索方式 | 目录递归检索 + 语义检索 | 向量/混合/图检索 | BM25 + vector + RRF,挂在层级结构里 | BM25 + vector + graph |
| 优势 | 统一资源、记忆、技能,检索可观察 | 接入简单,通用 memory layer | 分层明确,证据可回溯 | 自动捕获和跨 Agent 共享 |
| 风险 | 系统较重,早期项目,协议和部署需评估 | 记忆治理要补 | 生态偏 OpenClaw / Hermes | 需要本地服务和治理配置 |
一句话区分:
OpenViking 管的是"上下文目录"。
Mem0 管的是"长期事实记忆"。
TencentDB-Agent-Memory 管的是"分层记忆结构"。
agentmemory 管的是"跨 Agent 捕获、治理和检索"。
9. 实验数据怎么读
OpenViking README 和文档中给出了基于 LoCoMo10 的 OpenClaw 插件效果数据。
代表性结果:
| 方案 | 任务完成率 | 输入 token |
|---|---|---|
| OpenClaw 原生 memory-core | 35.65% | 24,611,530 |
| OpenClaw + LanceDB | 44.55% | 51,574,530 |
| OpenClaw + OpenViking | 52.08% | 4,264,396 |
| OpenClaw + OpenViking + 原生 memory-core | 51.23% | 2,099,622 |
这个结果说明两个趋势:
第一,OpenViking 不只是降低 token,还提升了任务完成率。
第二,普通向量库接入后可能反而带来更高 token 成本,因为召回的是较粗粒度内容;OpenViking 通过 L0 / L1 / L2 分层加载和目录递归检索,把上下文压得更小。
但也要注意:这是特定 Agent、特定 benchmark、特定版本上的结果。生产选型不能只看这个数字,仍要用自己的任务集评估。
10. 工程入口
OpenViking 提供几类入口:
- Python package:适合直接嵌入应用或实验;
- HTTP server:适合作为独立上下文数据库;
- Rust CLI:适合用命令管理资源和检索;
- MCP server:适合接 Claude Desktop 等 MCP 客户端;
- OpenClaw / OpenCode / Claude Code 插件示例:适合 Agent 框架集成。
它需要两类模型能力:
- Embedding model:负责向量化和语义检索;
- VLM / LLM model:负责内容理解、摘要和语义处理。
支持 Volcengine、OpenAI、LiteLLM 及多种 OpenAI-compatible 或本地模型路径。
11. 适合的场景
- Agent 需要长期使用项目文档、代码仓库、网页和知识库;
- 一个 Agent 系统里同时有用户记忆、资源、技能、任务经验;
- 需要按目录和路径组织上下文,而不是只靠向量 chunk;
- 希望降低长程任务里的 token 成本;
- 希望观察检索轨迹,调试召回为什么对或错;
- 已经在使用 OpenClaw、Claude Desktop MCP、OpenCode 或类似 Agent 框架。
12. 不适合的场景
- 只需要保存几条用户偏好;
- 只做简单企业知识库问答;
- 不想维护额外上下文服务、模型配置和资源处理流程;
- 强依赖成熟稳定商业 SLA;
- 对 AGPLv3 主项目协议不方便接受,且无法隔离使用范围;
- 只需要一个轻量 memory API,而不是上下文数据库。
13. 实践建议
1. 先把资料目录设计好
OpenViking 的收益来自目录结构。如果资源、用户记忆、技能经验都随意放,最后还是会退化成"换皮向量库"。
建议先区分:
- resources:项目文档、代码、网页;
- user:用户偏好、长期画像;
- agent:技能、instructions、任务经验;
- session:一次任务的临时上下文和沉淀结果。
2. 不要把所有内容都升成长期记忆
会话自迭代很有用,但也容易把临时噪声沉淀成长期经验。建议对用户偏好、项目规则、工具经验设置不同保存策略。
3. 检索轨迹要进入调试流程
OpenViking 的优势之一是可观察。上线前应记录失败案例,看是目录定位错、L0 摘要错、L1 概览不够,还是 L2 原文缺失。
4. 协议和部署要提前评估
GitHub 仓库显示主项目为 AGPLv3,CLI 和 examples 为 Apache 2.0。生产使用前要确认你的部署方式、改造方式和开源合规要求。
5. 和轻量记忆服务组合使用
OpenViking 适合管理大上下文和资源目录;简单用户偏好可以仍由 Mem0、agentmemory 或应用自己的 profile store 管理。不要强行让一个系统包办所有记忆。
14. 资源链接
- GitHub:volcengine/OpenViking
- 官网:OpenViking
- 文档:OpenViking Documentation
- Red Hat 部署解读:Deploy OpenViking on OpenShift AI
一句话收尾:OpenViking 的重点不是让 Agent "多记几条偏好",而是把 Agent 需要的记忆、资源和技能整理成一个可分层加载、可递归检索、可观察路径的上下文文件系统。