1. OpenViking 简介
1.1 解决方案
| 问题 | OpenViking 的做法 |
|---|
| 上下文碎片化 | 用文件系统范式统一管理:记忆、资源、技能都映射到 viking:// 虚拟目录,像管理文件一样管理上下文 |
| Token 消耗大 | L0/L1/L2 分层:L0 摘要约 100 token 做检索,L1 概览约 2k token 做决策,L2 按需加载全文,显著节省成本 |
| 检索效果差 | 目录递归检索:先向量定位到高分区目录,再在目录内递归细化,结合语义与层级结构,提升准确率 |
| 检索不可观测 | 检索路径对应明确 URI,支持可视化检索轨迹,便于调试和优化 |
| 记忆难以迭代 | 自动会话管理:对话结束后自动压缩、归档,并用 LLM 抽取长期记忆写入 user/memories、agent/memories,越用越准 |
1.2 核心概念
Resource(用户添加的知识与文档)、Memory(用户/Agent 的记忆)、Skill(可调用的能力),统一用 Viking URI 组织
VikingFS 做 URI 抽象;底层 AGFS 存内容(L0/L1/L2 文件),Vector Index 存向量与元数据,二者分离便于扩展
支持 find()(单查询向量检索)和 search()(意图分析 → 分层检索 → Rerank);结果按 URI 返回,可区分 memories/resources/skills
2. OpenViking 部署
1
2
| mkdir -p openviking/data
chmod -R 777 openviking
|
1
| 825a3a0183950b1bfa6c21b7afd8357b103e49c0478ae0f651515d76969f8ac4
|
1
2
3
| export OPENAI_API_KEY=sk-xxx
export OPENAI_API_BASE=https://llmapi.xxx.com/v1
export ROOT_API_KEY="825a3a0183950b1bfa6c21b7afd8357b103e49c0478ae0f651515d76969f8ac4"
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
| cat > openviking/ov.conf <<EOF
{
"server": {
"host": "0.0.0.0",
"port": 1933,
"root_api_key": "$ROOT_API_KEY",
"cors_origins": ["*"]
},
"storage": {
"workspace": "/app/data",
"vectordb": {
"name": "context",
"backend": "local"
},
"agfs": {
"backend": "local",
"port": 1833,
"log_level": "warn"
}
},
"embedding": {
"max_concurrent": 10,
"dense": {
"provider": "openai",
"api_key": "$OPENAI_API_KEY",
"api_base": "$OPENAI_API_BASE",
"model": "text-embedding-v4",
"dimension": 1024,
"input": "text",
"batch_size": 32
}
},
"vlm": {
"provider": "openai",
"api_key": "$OPENAI_API_KEY",
"api_base": "$OPENAI_API_BASE",
"model": "qwen3.5-plus",
"temperature": 0.0,
"max_retries": 2,
"max_concurrent": 100
},
"log": {
"level": "INFO",
"output": "stdout"
}
}
EOF
|
embedding 配置用于向量化,vlm 配置用于摘要、L0/L1、记忆抽取,图像和内容理解。这里没有配置 rerank 模型。
1
2
3
4
5
6
7
| nerdctl run -d \
--name openviking \
--restart always \
-p 1933:1933 \
-v $(pwd)/openviking/data:/app/data \
-v $(pwd)/openviking/ov.conf:/app/ov.conf \
ghcr.io/volcengine/openviking:v0.2.9
|
1
| nerdctl rm -f openviking
|
1
| curl http://127.0.0.1:1933/health
|
返回 {"status":"ok","healthy":true,"version":"v0.2.9"} 即表示服务就绪。
3. OpenViking 用户管理
1
2
| export OPENVIKING_BASE_URL="http://10.10.10.10:1933"
export ROOT_API_KEY="825a3a0183950b1bfa6c21b7afd8357b103e49c0478ae0f651515d76969f8ac4"
|
1
2
| curl -fsS -H "X-API-Key: $ROOT_API_KEY" \
"${OPENVIKING_BASE_URL%/}/api/v1/admin/accounts"
|
1
| {"status":"ok","result":[{"account_id":"default","created_at":"2026-03-23T09:58:40.472608+00:00","user_count":0}],"error":null,"telemetry":null}
|
1
2
3
4
| curl -fsS -X POST "${OPENVIKING_BASE_URL%/}/api/v1/admin/accounts" \
-H "Content-Type: application/json" \
-H "X-API-Key: $ROOT_API_KEY" \
-d '{"account_id":"my-team","admin_user_id":"my-admin"}'
|
1
| {"status":"ok","result":{"account_id":"my-team","admin_user_id":"my-admin","user_key":"49331c3c1cafb6e5670f316d47aabfaae6c628b6ae72a0d05f35b7c93da763a2"},"error":null,"telemetry":null}
|
需要提供 account 下的 admin user key
1
2
3
4
5
| export ADMIN_USER_KEY="49331c3c1cafb6e5670f316d47aabfaae6c628b6ae72a0d05f35b7c93da763a2"
curl -fsS -X POST "${OPENVIKING_BASE_URL%/}/api/v1/admin/accounts/my-team/users" \
-H "Content-Type: application/json" \
-H "X-API-Key: $ADMIN_USER_KEY" \
-d '{"user_id":"my-user","role":"user"}'
|
1
| {"status":"ok","result":{"account_id":"my-team","user_id":"my-user","user_key":"ad133ab241f779f19e2efe0c69655bd97dd67ac3a26a58d36a4a30c346e4b53f"},"error":null,"telemetry":null}
|
1
2
| curl -fsS -H "X-API-Key: $ADMIN_USER_KEY" \
"${OPENVIKING_BASE_URL%/}/api/v1/admin/accounts/my-team/users"
|
1
| {"status":"ok","result":[{"user_id":"my-admin","role":"admin"},{"user_id":"my-user","role":"user"}],"error":null,"telemetry":null}
|
1
2
3
4
| curl -fsS -X PUT "${OPENVIKING_BASE_URL%/}/api/v1/admin/accounts/my-team/users/my-user/role" \
-H "Content-Type: application/json" \
-H "X-API-Key: $ROOT_API_KEY" \
-d '{"role":"admin"}'
|
1
| {"status":"ok","result":{"account_id":"my-team","user_id":"my-user","role":"admin"},"error":null,"telemetry":null}
|
- 重新生成用户 Key(旧 Key 立刻失效;用 Root 或 Admin User Key)
1
2
3
4
| curl -fsS -X POST "${OPENVIKING_BASE_URL%/}/api/v1/admin/accounts/my-team/users/my-user/key" \
-H "Content-Type: application/json" \
-H "X-API-Key: $ADMIN_USER_KEY" \
-d '{}'
|
1
| {"status":"ok","result":{"user_key":"97b790bed56e40d288d3c60ee09abb41d821fb039fb2a53f92fe4fbd629ea8cd"},"error":null,"telemetry":null}
|
1
2
| curl -fsS -X DELETE "${OPENVIKING_BASE_URL%/}/api/v1/admin/accounts/my-team/users/my-user" \
-H "X-API-Key: $ADMIN_USER_KEY"
|
1
2
| curl -fsS -X DELETE "${OPENVIKING_BASE_URL%/}/api/v1/admin/accounts/my-team" \
-H "X-API-Key: $ROOT_API_KEY"
|
4. OpenViking 功能使用
1
2
3
| export OPENVIKING_BASE_URL="http://10.10.10.10:1933"
export USER_ID="my-user"
export USER_KEY="97b790bed56e40d288d3c60ee09abb41d821fb039fb2a53f92fe4fbd629ea8cd"
|
1
2
3
4
| curl -fsS -X POST "$OPENVIKING_BASE_URL/api/v1/fs/mkdir" \
-H "Content-Type: application/json" \
-H "X-API-Key: $USER_KEY" \
-d '{"uri":"viking://resources/lifecycle-demo/"}'
|
1
| {"status":"ok","result":{"uri":"viking://resources/lifecycle-demo/"},"error":null,"telemetry":null}
|
1
2
3
4
5
| export FILE_PATH="/tmp/ov-lifecycle.md"
echo 'Hello OpenViking lifecycle' > $FILE_PATH
curl -fsS -X POST "$OPENVIKING_BASE_URL/api/v1/resources/temp_upload" \
-H "X-API-Key: $USER_KEY" \
-F "file=@$FILE_PATH"
|
1
| {"status":"ok","result":{"temp_path":"/app/data/temp/upload/upload_3c5f30d789b9439e91f16da9b22555cc.md"}}
|
1
2
3
4
5
6
7
8
9
10
| export TEMP_PATH="/app/data/temp/upload/upload_3c5f30d789b9439e91f16da9b22555cc.md"
curl -fsS -X POST "$OPENVIKING_BASE_URL/api/v1/resources" \
-H "Content-Type: application/json" \
-H "X-API-Key: $USER_KEY" \
-d "{
\"temp_path\": \"$TEMP_PATH\",
\"parent\": \"viking://resources/lifecycle-demo/\",
\"wait\": false,
\"reason\": \"curl lifecycle\"
}"
|
1
| {"status":"ok","result":{"status":"success","errors":[],"source_path":"/app/data/temp/upload/upload_3c5f30d789b9439e91f16da9b22555cc.md","meta":{},"root_uri":"viking://resources/lifecycle-demo/upload_3c5f30d789b9439e91f16da9b22555cc","temp_uri":"viking://resources/lifecycle-demo/upload_3c5f30d789b9439e91f16da9b22555cc"}}
|
1
2
3
4
5
| curl -fsS -G \
-H "X-API-Key: $USER_KEY" \
--data-urlencode "uri=viking://resources/lifecycle-demo/" \
--data-urlencode "recursive=true" \
"$OPENVIKING_BASE_URL/api/v1/fs/ls"
|
1
| {"status":"ok","result":[{"uri":"viking://resources/lifecycle-demo/upload_3c5f30d789b9439e91f16da9b22555cc","size":88,"isDir":true,"modTime":"09:02:48","rel_path":"upload_3c5f30d789b9439e91f16da9b22555cc","abstract":""},{"uri":"viking://resources/lifecycle-demo/upload_3c5f30d789b9439e91f16da9b22555cc/upload_3c5f30d789b9439e91f16da9b22555cc.md","size":27,"isDir":false,"modTime":"09:02:48","rel_path":"upload_3c5f30d789b9439e91f16da9b22555cc/upload_3c5f30d789b9439e91f16da9b22555cc.md","abstract":""}],"error":null,"telemetry":null}
|
1
2
3
4
5
| export FILE_URI="viking://resources/lifecycle-demo/upload_3c5f30d789b9439e91f16da9b22555cc/upload_3c5f30d789b9439e91f16da9b22555cc.md"
curl -fsS -G \
-H "X-API-Key: $USER_KEY" \
--data-urlencode "uri=$FILE_URI" \
"$OPENVIKING_BASE_URL/api/v1/content/read"
|
1
| {"status":"ok","result":"Hello OpenViking lifecycle\n","error":null,"telemetry":null}
|
1
2
3
4
5
| export FILE_URI="viking://resources/lifecycle-demo/upload_3c5f30d789b9439e91f16da9b22555cc/upload_3c5f30d789b9439e91f16da9b22555cc.md"
curl -fsS -G \
-H "X-API-Key: $USER_KEY" \
--data-urlencode "uri=$FILE_URI" \
"$OPENVIKING_BASE_URL/api/v1/fs/stat"
|
1
| {"status":"ok","result":{"isDir":false,"modTime":"2026-03-24T09:02:48.710880298Z","mode":420,"name":"upload_3c5f30d789b9439e91f16da9b22555cc.md","size":27},"error":null,"telemetry":null}
|
可以配置 reranker 模型。
1
2
3
4
5
6
7
8
| curl -fsS -X POST "$OPENVIKING_BASE_URL/api/v1/search/find" \
-H "Content-Type: application/json" \
-H "X-API-Key: $USER_KEY" \
-d '{
"query": "Hello",
"target_uri": "viking://resources/lifecycle-demo/",
"limit": 5
}'
|
响应会比较慢,会有模型调用。
1
| {"status":"ok","result":{"memories":[],"resources":[{"context_type":"resource","uri":"viking://resources/lifecycle-demo/upload_a67d1858a30f4c4d91df60e7a489448c/upload_a67d1858a30f4c4d91df60e7a489448c_1.md","level":2,"score":0.09988392326968897,"category":"","match_reason":"","relations":[],"abstract":"","overview":null}],"skills":[],"total":2}}
|
1
2
3
4
| curl -fsS -X POST "$OPENVIKING_BASE_URL/api/v1/search/grep" \
-H "Content-Type: application/json" \
-H "X-API-Key: $USER_KEY" \
-d '{"uri":"viking://resources/lifecycle-demo/","pattern":"Hello"}'
|
1
| {"status":"ok","result":{"matches":[{"line":24,"uri":"viking://resources/lifecycle-demo/upload_3c5f30d789b9439e91f16da9b22555cc/.overview.md","content":""},{"line":1,"uri":"viking://resources/lifecycle-demo/upload_3c5f30d789b9439e91f16da9b22555cc/upload_3c5f30d789b9439e91f16da9b22555cc.md","content":"Hello OpenViking lifecycle"},{"line":1,"uri":"viking://resources/lifecycle-demo/upload_d318b2c6f0494e88af77f9d1afbc18de/upload_d318b2c6f0494e88af77f9d1afbc18de.md","content":"Hello OpenViking lifecycle"}],"count":3},"error":null,"telemetry":null}
|
- search 语义、意图检索,可选带 session。
1
2
3
4
| curl -fsS -X POST "$OPENVIKING_BASE_URL/api/v1/sessions" \
-H "Content-Type: application/json" \
-H "X-API-Key: $USER_KEY" \
-d '{}'
|
1
| {"status":"ok","result":{"session_id":"d46e0160-1ebc-483d-971f-32d60bb1de9a","user":{"account_id":"my-team","user_id":"my-user","agent_id":"default"}},"error":null,"telemetry":null}
|
1
2
3
4
5
6
7
8
9
| export SESSION_ID="d46e0160-1ebc-483d-971f-32d60bb1de9a"
curl -fsS -X POST "$OPENVIKING_BASE_URL/api/v1/search/search" \
-H "Content-Type: application/json" \
-H "X-API-Key: $USER_KEY" \
-d '{
"query": "Hello",
"session_id": "$SESSION_ID",
"limit": 5
}'
|
也会有模型调用。
1
2
3
4
| curl -fsS -X DELETE \
-H "X-API-Key: $USER_KEY" \
--get "$OPENVIKING_BASE_URL/api/v1/fs" \
--data-urlencode "uri=$FILE_URI"
|
1
| {"status":"ok","result":{"uri":"viking://resources/lifecycle-demo/upload_3c5f30d789b9439e91f16da9b22555cc/upload_3c5f30d789b9439e91f16da9b22555cc.md"},"error":null,"telemetry":null}
|
1
2
3
| curl -fsS -X DELETE \
-H "X-API-Key: $USER_KEY" \
"$OPENVIKING_BASE_URL/api/v1/fs?uri=viking://resources/lifecycle-demo/&recursive=true"
|
1
| {"status":"ok","result":{"uri":"viking://resources/lifecycle-demo/"},"error":null,"telemetry":null}
|
1
2
3
4
| curl -fsS -G \
-H "X-API-Key: $USER_KEY" \
--data-urlencode "uri=viking://resources/" \
"$OPENVIKING_BASE_URL/api/v1/fs/ls"
|
1
| {"status":"ok","result":[],"error":null,"telemetry":null}
|
5. OpenClaw 集成 OpenViking
OpenClaw:建议 2026.3.11,高版本可能存在兼容性问题
1
| nerdctl exec -it openclaw bash
|
1
2
3
4
| openclaw config set agents.defaults.memorySearch.enabled false --json
openclaw config set memory.qmd.includeDefaultMemory false --json
openclaw config set hooks.internal.entries.session-memory.enabled false --json
openclaw config set agents.defaults.compaction.memoryFlush.enabled false --json
|
1
| npm install -g openclaw-openviking-setup-helper
|
选择 remote,填写 OpenViking 服务地址和 USER_KEY。
1
| openclaw config set plugins.slots.memory openviking
|
1
| openclaw gateway restart
|
1
| openclaw config get plugins.entries.openviking.config
|
1
2
3
4
5
6
7
8
| 🦞 OpenClaw 2026.3.11 (unknown) — I've survived more breaking changes than your last three relationships.
{
"mode": "remote",
"baseUrl": "http://10.10.10.10:1933",
"apiKey": "__OPENCLAW_REDACTED__",
"agentId": "openclaw-viking"
}
|
1
| node openclaw.mjs status |grep Memory
|
1
| │ Memory │ enabled (plugin openviking) │
|
尝试与 OpenClaw 对话,可以看到 OpenViking 创建相关记忆的日志。
1
| nerdctl logs openviking -f
|
1
| 2026-03-24 10:20:59,392 - openviking.session.memory_extractor - INFO - uri viking://user/my-user/memories/events/mem_372fc569-f140-4a31-a266-6a795bf49af0.md abstract: 正在学习参考 LVM 日常运维文章作为速查手册,将其作为运维工作的速查手册使用。文章内容涵盖物理卷(PV)、卷组(VG)、逻辑卷(LV)的管理命令,以及 RAID 逻辑卷配置、扩容缩容操作等实用内容。
|
6. 参考