OpenViking ov_dream 技能实战:为 OpenClaw Agent 打造手动同步与召回记忆的轻量 CLI
【免费下载链接】OpenVikingSelf-evolving Context Database for AI Agents. Unify Agent Memory, Knowledge RAG and Skills.项目地址: https://gitcode.com/GitHub_Trending/op/OpenViking
导读
ov_dream是 OpenViking 为 OpenClaw Agent 提供的一枚"技能(Skill)",它绕开插件(plugin)槽位,用最轻量的方式打通两条核心链路:手动同步(ov dream)——把 OpenClaw 最近记录的聊天会话转录同步进 OpenViking;手动召回(ov recall <query>)——以自然语言查询直接命中 OpenViking 用户空间下的记忆。读完本文,你将掌握这枚技能的完整使用规则、底层 CLI 的调用链与认证模型、OV Lite 无插件安装方式,以及如何用 cron 把同步变成定期执行的自动化任务。
本文以 SKILL.md 为骨架,结合其背后的 dream.py、测试用例 与 OpenViking 服务端路由实现展开讲解。
一、技能定位:何时使用ov_dream
ov_dream的使用前提非常明确:当用户在消息开头输入了精确前缀ov dream或ov recall时,这条消息不应被当作普通对话处理,而是显式的操作员命令。该技能在 SKILL.md 中被声明为:
Use when the user explicitly types
ov dreamorov recall <query>and the request should be routed to the OpenViking sync/recall CLI instead of handled as normal chat.
也就是说,这是一条路由规则(routing rule)而非闲聊场景。它的设计目标是不占用 OpenClaw 的contextEngine插件槽位——第一版刻意保持纯手动(manual-only),不做自动注入,不取代 OpenViking 的 context-engine 插件,从而让用户在已有插件体系之外多一个随时可用的运维入口。
二、命令总览
| 命令 | 语义 | 底层动作 |
|---|---|---|
ov dream | 手动同步 | 读取 OpenClaw 的sessions.json,把符合聊天条件的会话转录同步到 OpenViking,有新消息时逐个 commit 会话 |
ov recall <query> | 手动召回 | 在默认用户根 URIviking://user/default下搜索 OpenViking 记忆 |
两条命令的底层都收敛到同一个脚本 dream.py:
# 同步 python3 scripts/dream.py dream # 召回 python3 scripts/dream.py recall "<query>"CLI 入口main()甚至内置了对ov dream/ov recall xxx短语的归一化处理(_normalize_ov_command),意味着既可以直接以ov dream这种完整短语触发,也可以拆成子命令参数传入。
三、ov dream:手动同步的完整执行流
3.1 触发与执行
当用户消息恰好等于ov dream时触发。执行流程只有两步:运行上面的同步命令,然后向用户返回同步摘要(sync summary)。
3.2 会话来源:只信任 OpenClaw 会话索引
同步命令读取 OpenClaw 的会话元数据,路径固定为~/.openclaw/agents/main/sessions/sessions.json(存在时)。代码中的关键决策在get_active_sessions():
# Only trust OpenClaw's session index; raw jsonl fallback can accidentally sync cron/subagent transcripts. return _get_indexed_chat_sessions(sessions_root)这里有一个非常重要的工程决策:绝不回退到扫描最新 raw jsonl 文件。原因在注释里写得很清楚——盲扫原始转录文件可能误把 cron/subagent 等非聊天转录一并同步。对应测试test_get_active_sessions_does_not_fallback_to_raw_jsonl专门断言:即使存在更新的未索引 jsonl,只要不在sessions.json索引中,get_active_sessions()返回空列表。
3.3 会话过滤规则:聊天 vs 非聊天
is_chat_session_key()是过滤的核心函数:
blocked = (":cron:", ":heartbeat", ":subagent:", ":acp:", ":hook:") return bool(key) and not any(part in key for part in blocked)即会同步形如agent:main:main、:direct:、:channel:、:group:、:room:的聊天类会话键;禁止同步包含:cron:、:heartbeat、:subagent:、:acp:、:hook:的非聊天会话。测试 test_dream_cli.py 中的test_is_chat_session_key_filters_non_chat_openclaw_sessions给出了完整的正反例矩阵,例如agent:main:telegram:direct:123与agent:main:discord:channel:456会被保留,而agent:main:cron:daily、agent:main:heartbeat、agent:main:subagent:child会被剔除。
3.4 消息解析:扁平化文本块
同步的对象是会话转录中的message行。parse_messages()对每个会话文件(默认{session_id}.jsonl)逐行解析:
- 只接受
type == "message"的行; - 只保留
role为user或assistant的消息; - 内容为空的消息直接跳过;
- 通过
_message_text()把 OpenClaw 的消息体扁平化为纯文本——内容可能是 block 列表,也可能是裸字符串(简单消息场景)。这里对裸字符串有专门兼容处理,因为真实转录中简单消息存的是字符串,若按列表迭代会逐个字符拆开并触发AttributeError,导致整个 run 中断。
3.5 独立游标:增量同步的断点续传
每个源会话在~/.openclaw/memory/ov_dream_sync.json中维护相互独立的同步游标last_synced_timestamp。sync_session()只会上传timestamp > last_synced_timestamp的新增消息,按时间戳排序后逐条add_session_message,只要有新消息就触发commit_session(wait=True)并推进游标。同步状态文件同时记录last_status、last_synced_count、last_sync_at、committed、session_key、session_file等元信息,方便事后审计。
测试test_sync_active_session_syncs_chat_sessions_with_independent_cursors验证了多会话并行游标:main与direct两个聊天会话各有一条游标,而cron会话既不被同步也不会出现在状态文件中。
四、ov recall <query>:手动召回的执行流
4.1 硬路由规则
当用户消息以ov recall开头时,本技能有强制路由规则:
- 不要用通用推理回答;
- 不要复述"召回会做什么";
- 不要询问"是否要执行召回";
- 立即执行本地召回命令。
4.2 执行流程
- 提取
ov recall之后的所有文本作为召回查询; - 执行
python3 scripts/dream.py recall "<query>"; - 把命中的相关记忆行返回给用户;
- 若无命中,返回
No memories found.。
4.3 规则细节
ov recall ...是手动召回请求,不是普通对话轮次;ov recall之后的命令文本即精确查询串;- 召回命令必须在技能目录下运行,保证
scripts/dream.py能正确解析; - 不自动把召回结果注入 prompt 上下文(与第一版 manual-only 定位一致);
- 不触发
ov dream,除非用户另行要求同步; - 查询为空时,向用户索要召回查询,而不是自行猜测。
_print_recall_results()的输出格式为uri|score|summary三列:uri是记忆条目的viking://地址,score是相关性得分,summary取abstract或overview摘要字段,非常适合在终端里直接阅读或二次解析。
五、底层实现:OpenVikingClient 与认证模型
dream.py的所有网络调用都封装在OpenVikingClient中,理解它也就理解了整个同步/召回链路的协议面。
5.1 默认端点与目标 URI
DEFAULT_BASE_URL = "http://127.0.0.1:1933" DEFAULT_TARGET_URI = "viking://user/default" LEGACY_TARGET_URI = "viking://user/memories" # 兼容旧配置的 uid-less 拼写 HOME_MEMORIES_TARGET_URI = "viking://~/memories" # 调用者自身用户空间的 home 别名 SERVERLESS_BASE_URL = "https://api.vikingdb.cn-beijing.volces.com/openviking"本地部署时默认指向本机127.0.0.1:1933;Serverless 模式则指向火山引擎的托管端点。
5.2 三种认证模式
auth_mode支持auto/local/serverless三选一(_resolve_auth_mode校验),默认auto:
auto(默认):检测 base URL——只要包含api.vikingdb或以/openviking结尾,自动切换为serverless,否则视为local;local:使用X-OpenViking-Account/X-OpenViking-User请求头(分别取环境变量OPENVIKING_ACCOUNT、OPENVIKING_USER,默认均为default),API Key 通过X-API-Key头传递;serverless:使用Authorization: Bearer <OPENVIKING_API_KEY>,不发送X-API-Key、X-OpenViking-User等本地请求头(测试test_serverless_headers_use_bearer_auth逐项断言)。
5.3 目标 URI 解析
_resolve_target_uri()把三类写法统一解析为显式 uid 的viking://user/<user_space>形式:
viking://user/default(含尾斜杠)→viking://user/default;- 旧拼写
viking://user/memories与 home 别名viking://~/memories→viking://user/<user_space>/memories/。
测试test_recall_expands_default_user_root_to_explicit_user_space完整覆盖了这组映射。
5.4 三个核心 API 调用
| 方法 | HTTP 调用 | 说明 |
|---|---|---|
add_session_message | POST /api/v1/sessions/{session_id}/messages | 写入单条消息。Serverless 模式发送{"role": ..., "parts": [{"type": "text", "text": ...}]}格式,本地模式发送{"role": ..., "content": ...} |
commit_session | POST /api/v1/sessions/{session_id}/commit | 提交会话。Serverless 模式附带{"telemetry": false}且不带?wait=true;本地模式默认?wait=true |
recall | POST /api/v1/search/find | 语义检索,请求体含query、limit(默认 5)、target_uri |
测试test_serverless_sync_reuses_source_session_id_and_uses_parts_payload验证了同步时直接复用 OpenClaw 的session_id作为 OpenViking 会话 ID,并断言了 Serverless 模式的 parts 载荷与telemetry: false提交体。
5.5 服务端对应实现
这些调用并非凭空捏造,在 OpenViking 服务端有对应路由:
- search.py 中的
POST /api/v1/search/find被注释为 "Semantic search without session context",接收FindRequest(含query、limit、node_limit、target_uri、score_threshold、filter、tags等字段),经 URI 校验、过滤器合并后调用检索服务并返回记忆结果; - sessions.py 中的
POST /{session_id}/commit执行"归档(Phase 1)+ 后台记忆抽取(Phase 2)"两阶段提交,并返回task_id供轮询进度。
六、OV Lite 安装与 Serverless 配置
OV_LITE_INSTALL.md 提供了不安装 OpenVikingcontextEngine插件、不占用插件槽位的 OV Lite 安装路径。
6.1 环境变量(前置条件)
执行同步或召回前必须配置:
OPENVIKING_API_KEY:OpenViking serverless API Key。
注意:不要在日志、shell 历史或回复中打印 API Key。
6.2 安装或更新
将技能文件从当前仓库的 examples/skills/ov_dream 目录安装到 OpenClaw 的 skills 目录:
mkdir -p ~/.openclaw/skills/ov_dream/scripts # 复制 SKILL.md 与 scripts/dream.py 到上述目录 # 并补齐两个 __init__.py 使 Python 包可导入 touch ~/.openclaw/skills/ov_dream/__init__.py touch ~/.openclaw/skills/ov_dream/scripts/__init__.py下载/复制过程中任一文件失败,应停下并核对来源。
6.3 校验文件完整性
用以下关键特征验证拿到的dream.py是对应版本:
grep -q 'SERVERLESS_BASE_URL' ~/.openclaw/skills/ov_dream/scripts/dream.py grep -q 'OPENVIKING_AUTH_MODE' ~/.openclaw/skills/ov_dream/scripts/dream.py grep -q 'viking://user/default' ~/.openclaw/skills/ov_dream/scripts/dream.py grep -q 'is_chat_session_key' ~/.openclaw/skills/ov_dream/scripts/dream.py grep -q 'raw jsonl fallback can accidentally sync cron/subagent transcripts' ~/.openclaw/skills/ov_dream/scripts/dream.py grep -q 'client.add_session_message(session.session_id' ~/.openclaw/skills/ov_dream/scripts/dream.py任一检查失败,说明dream.py不是预期的 OV Lite 版本。
6.4 配置 Serverless 认证
创建~/.openclaw/ov_dream.env(若已存在则保留真实OPENVIKING_API_KEY,只补充缺失的非敏感默认值):
cat > ~/.openclaw/ov_dream.env <<'EOF' OPENVIKING_BASE_URL=https://api.vikingdb.cn-beijing.volces.com/openviking OPENVIKING_API_KEY=<replace with OpenViking serverless API key> OPENVIKING_AUTH_MODE=serverless EOF chmod 600 ~/.openclaw/ov_dream.env6.5 验证同步与召回
cd ~/.openclaw/skills/ov_dream set -a . ~/.openclaw/ov_dream.env set +a python3 scripts/dream.py dream python3 scripts/dream.py recall "最近我在聊什么"其中OPENVIKING_AUTH_MODE=serverless会让 CLI 自动使用 Bearer 认证与 serverless 会话消息格式(对应 5.2、5.4 节描述的_resolve_auth_mode与add_session_message分支)。
6.6 用 cron 定时同步
要周期性沉淀记忆,可添加 OpenClaw cronjob 每 5 分钟同步一次(若ov-dream-sync已存在则更新而非重复创建):
openclaw cron add ov-dream-sync \ --schedule "*/5 * * * *" \ --command 'cd ~/.openclaw/skills/ov_dream && set -a && . ~/.openclaw/ov_dream.env && set +a && python3 scripts/dream.py dream'七、CLI 参数速查
dream.py是标准argparseCLI(见_build_parser),可用参数如下:
| 参数 | 默认值 | 说明 |
|---|---|---|
--base-url | 环境变量OPENVIKING_BASE_URL,否则http://127.0.0.1:1933 | OpenViking 服务地址 |
--api-key | 环境变量OPENVIKING_API_KEY | API Key,可省略 |
--auth-mode | 环境变量OPENVIKING_AUTH_MODE,否则auto | auto/local/serverless |
--openclaw-root | ~/.openclaw | OpenClaw 数据根目录 |
--state-root | ~/.openclaw/memory | 同步游标状态文件目录 |
recall <query> | — | 召回查询子命令 |
recall --limit N | 5 | 召回条数上限 |
八、行为边界与注意事项
综合 SKILL.md 的 Notes 与 OV_LITE_INSTALL.md 的行为说明,使用时请牢记以下边界:
- 纯手动:第一版不自动注入召回结果到 prompt,也不自动触发同步;
- 不取代插件:它不替代 OpenViking context-engine 插件,两者是互补关系;
- 磁盘快照语义:基于磁盘的同步针对"最近记录的聊天转录",不是精确的"正在运行的会话"检测器——例如新消息刚写入但尚未出现在索引中的窗口期,可能不会被捕获;
- 会话来源单一:只读取
sessions.json索引,不回退扫描 raw jsonl; - 非聊天会话隔离:包含
:cron:、:heartbeat:、:subagent:、:acp:、:hook:的会话键一律不同步; - Serverless 约定:同步时直接复用 OpenClaw 的
session_id写入 OpenViking serverless,并关闭遥测提交(telemetry: false)。
九、测试保障
技能随仓库携带了完整测试 test_dream_cli.py,覆盖了本文讲述的大部分关键行为:ov recall短语归一化、默认用户根 URI 展开、recall 请求体构造、serverless Bearer 认证头、serverless 同步载荷与会话 ID 复用、索引优先且不回退 jsonl、非聊天键过滤、多会话独立游标同步等。这意味着你可以在仓库内直接运行测试验证这套 CLI 的语义,也便于在修改后做回归保障。
一句话总结:ov_dream是 OpenViking 提供给 OpenClaw 用户的"记忆运维控制台"——ov dream让对话记忆按需落库,ov recall让记忆按语义随时可查,两者叠加 cron 调度,即可在不引入插件的前提下,为 Agent 构建一条可持续生长的记忆管道。
【免费下载链接】OpenVikingSelf-evolving Context Database for AI Agents. Unify Agent Memory, Knowledge RAG and Skills.项目地址: https://gitcode.com/GitHub_Trending/op/OpenViking
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考