首页
/ DeerFlow 接入 OpenViking 长期记忆后端:认证边界、配置全解与失败语义

DeerFlow 接入 OpenViking 长期记忆后端:认证边界、配置全解与失败语义

2026-09-04 13:03:22作者:薛曦旖Francesca

本文以 docs/OPENVIKING.md 为主体,完整讲解 DeerFlow 的 OpenViking 长期记忆后端:如何用 USER API Key 配置 manager_class: openviking、如何启动并验证 OpenViking 服务、线程到 Session 的确定性映射规则,以及读取/写入失败策略、哈希游标与优雅关闭的底层实现。读完后你可以独立完成该后端的部署配置,并从源码层面理解其身份隔离与数据一致性边界。

OpenViking 后端定位与当前范围

DeerFlow 支持把远程 OpenViking 服务器作为可选的长期记忆后端,默认后端仍是 DeerMem。该后端不自行实现 OpenViking 的 HTTP 协议,而是直接使用官方维护的 langchain-openviking 适配包(仓库中以 langchain-openviking==0.1.0 锁定,声明在 harness 包依赖 中,通过常规 uv sync 流程安装)。

首个官方适配器集成刻意保留 DeerFlow 现有的自动记忆行为

  • 记忆通过 DeerFlow 既有的固定记忆查询(fixed memory query)召回;
  • 已完成的轮次由现有 memory middleware 捕获;
  • 即将被压缩(compaction)的消息由现有 summarization hook 捕获;
  • 每条被接受的捕获都提交到该线程稳定的 OpenViking Session;
  • 消息转换、工具调用与结果处理、100 条消息分批、部分写入进度记录、提交重试和 SDK 传输全部由官方适配器负责;
  • 一个由 recorder 拥有的 SDK 客户端与检索共享,并通过 DeerFlow 既有的 memory 关闭契约统一关闭。

明确的范围边界(这些不是缺陷,而是有意为之):

  • 仅支持 memory.mode: middleware。在 OpenVikingMemoryManager.from_config 中,mode != "middleware" 会直接抛出 ValueError,并提示需要模型主动调用记忆工具时应走 OpenViking MCP;
  • 不实现 DeerMem 的 fact CRUD、导入/导出,也不提供 Settings 中的记忆文档视图;
  • OpenViking MCP 工具是另一个独立的集成面,不由该后端启用(见 extensions_config.example.json 中默认 enabled: falseopenviking MCP 条目)。

认证边界:一个 USER Key 绑定一个 DeerFlow 用户

api_key 模式是唯一支持的服务器配置

当前版本面向「一个 DeerFlow 用户 + 一个普通 OpenViking USER API Key」的部署形态。OpenViking 从该凭据推导 account 和 user;DeerFlow 不配置 trusted account/user 请求头,正常记忆流量也不应持有 root key。

支持的服务端配置是 OpenViking 的 api_key 模式:DeerFlow 显式提供 URL 与 API Key,在记忆操作中覆盖任何环境里的 actor peer,且不继承 ovcli.conf 中的任意 HTTP 头。源码中这一点有明确对应:OpenVikingMemoryManager 构造 recorder 时传入 extra_headers={},注释写明该显式映射会禁用 SDK 的 ovcli.conf 头回退;每次操作再用 use_actor_peer 作用域覆盖环境身份。

启用该后端前的清理清单:

  1. 从 DeerFlow 仓库根 .env 和服务环境中移除遗留的 OPENVIKING_ACCOUNTOPENVIKING_USER
  2. ~/.openviking/ovcli.conf 移除 accountuser 默认值。

这些设置属于 trusted 模式,不在本适配器的支持范围内。

配置校验在启动期就会拦截遗留字段:OpenVikingConfig.from_backend_config 检测到 auth_modeaccount 字段会直接抛错("trusted mode is no longer supported"),自定义 HTTP 客户端字段(如 connect_timeout_secondsmax_retries 等)同样被拒。

owner_user_id:防止一个 Key 被多个用户共享

owner_user_id 把配置好的 Key 绑定到一个 DeerFlow 身份:DeerFlow 认证关闭时用 default;启用认证的单用户部署填该用户的 DeerFlow ID。请求属于其他 DeerFlow 用户时,会在联系 OpenViking 之前被拒绝,避免一个 USER Key 在用户之间静默共享记忆。

源码中的强制点在 _resolve_scope

resolved_user = str(user_id or "default")
if resolved_user != self._config.owner_user_id:
    raise MemoryManagerError(
        f"OpenViking USER API key is bound to DeerFlow owner_user_id "
        f"{self._config.owner_user_id!r}, but this request belongs to "
        f"{resolved_user!r}. Refusing to share one credential across users."
    )

多用户的凭据供给与存储被有意排除在第一个适配器之外。

旧 trusted 模式配置不会自动迁移

现有 trusted 模式配置不会被自动迁移。需要把 OpenViking 服务器配置为 api_key 模式,用 owner_user_id + USER Key 替换 auth_modeaccount 和 root key,并移除上述遗留环境身份设置。由于凭据绑定的 user/Session 映射与旧的 trusted-user 映射不同,先前捕获的 trusted 模式数据会留在其旧的 OpenViking 命名空间中,不会被静默重分配。

配置 DeerFlow

第一步:写入 .env 与 config.yaml

在 OpenViking 中创建或选择用户,把其 USER API Key 写入 DeerFlow 仓库根 .env

OPENVIKING_API_KEY=replace-with-an-openviking-user-api-key

config.yaml 中选择后端:

memory:
  enabled: true
  injection_enabled: true
  shutdown_flush_timeout_seconds: 30
  manager_class: openviking
  mode: middleware
  backend_config:
    base_url: http://127.0.0.1:1933
    owner_user_id: default
    api_key_env: OPENVIKING_API_KEY
    startup_policy: fail_fast
    failure_policy:
      read: fail_open
      write: log_and_drop
    retrieval:
      top_k: 8
      score_threshold: 0.25
      max_injection_chars: 12000
      content_mode: overview
      injection_query: >-
        user profile preferences important entities events ongoing goals
        constraints and prior decisions

同一份示例也内嵌在 config.example.yaml 的 memory 配置注释区(manager_class: openviking 时替换默认 DeerMem 的 backend_config 块)。

backend_config 完整参数表(源码校验值)

下表由 OpenVikingConfig 的默认值与 _validate() 取值范围整理,可复制到实际配置中使用:

参数 默认值 取值范围 / 说明
base_url http://127.0.0.1:1933 必须是绝对 http(s) URL;纯 HTTP 仅允许 127.0.0.1 / localhost / openviking,其他主机必须 HTTPS 或显式 allow_insecure_http: true
owner_user_id 必填,无默认 绑定 Key 的 DeerFlow 用户 ID;认证关闭时用 default;空值启动失败
api_key_env OPENVIKING_API_KEY 存放 USER Key 的环境变量名;Key 缺失时启动失败(fail_fast 语义)
default_peer_id deerflow 默认 agent 的 OpenViking peer ID;必须匹配 ^[a-z0-9][a-z0-9_-]{0,63}$,且不得以保留前缀 df-agent- 开头
timeout_seconds 30.0 必须为 > 0 的有限数值
storage_path 空(用 DeerFlow base_dir) 本地哈希游标根目录前缀
startup_policy fail_fast fail_fastwarn;控制启动期健康检查失败是否直接抛错
failure_policy.read fail_open fail_open(记日志并返回无注入记忆)或 raise(向调用方传播)
failure_policy.write log_and_drop log_and_drop(记日志,不使已生成的回答失败)或 raise
allow_insecure_http false 受信内网下才置 true
max_seen_message_ids 512 有界哈希游标容量,范围 16–10000
retrieval.top_k 8 1–100
retrieval.score_threshold 无阈值(null 0–1 的有限数值
retrieval.max_injection_chars 12000 256–100000
retrieval.content_mode overview auto / abstract / overview / read
retrieval.injection_query 与上文示例相同 固定记忆查询,不得为空

此外,任何未识别的 backend_config 顶层字段、retrieval.*failure_policy.* 字段都会触发启动期报错(config.py#L98-L106),可以防止拼写错误被静默忽略。

宿主安装 vs Docker 部署的地址差异

  • 宿主安装 OpenViking、Docker 运行 DeerFlow:base_url 设为 http://host.docker.internal:1933,并配 allow_insecure_http: true
  • 使用仓库自带的可选 Compose overlay 时,走容器网络内部地址 http://openviking:1933(该主机名在纯 HTTP 白名单内,无需 allow_insecure_http)。

启动服务

本地进程:先起 OpenViking 并验证

openviking-server doctor
openviking-server
curl http://127.0.0.1:1933/health

随后正常启动 DeerFlow:

make doctor
make dev

DeerFlow 位于 http://localhost:2026,OpenViking Studio 位于 http://localhost:1933/studio(可在 Studio 中人工检查记忆捕获与 Session 归档)。

Docker:可选 Compose overlay

docker compose \
  -f docker/docker-compose.yaml \
  -f docker/docker-compose.openviking.yaml \
  up -d openviking

docker exec -it deer-flow-openviking openviking-server init

docker compose \
  -f docker/docker-compose.yaml \
  -f docker/docker-compose.openviking.yaml \
  up -d --build

overlay 文件 的关键点:镜像默认 ${OPENVIKING_IMAGE:-ghcr.io/volcengine/openviking:latest},以 --without-bot 启动,端口映射 ${OPENVIKING_PORT:-1933}:1933,数据卷 openviking-data 挂到容器内 /app/.openviking;健康检查通过 /health 探测,且 gateway 服务 depends_on: openviking: condition: service_healthy——即 OpenViking 不就绪时 gateway 不会被拉起。

启动后把 OpenViking 配置为 API-key 模式,通过其身份管理流程获取 USER Key;只有这个 USER Key 应写入 DeerFlow 的 OPENVIKING_API_KEY 变量。

身份与会话映射:线程 → Session → Peer

一个 DeerFlow 线程确定性地映射为一个 OpenViking Session

Session ID 由 session.py 中的 _session_id 派生:对 deerflow-openviking-adapter-v1 命名空间 + owner_user_id + peer_id + thread_id 做 SHA-256,取前 48 个十六进制字符,加 df_ 前缀。commit 在该 Session 内部创建 archive,而不创建新 Session——因此用户稍后回来时线程保持同一身份。

Peer:用户内部的作用域分离

  • 默认 DeerFlow agent 使用 default_peer_id(默认 deerflow);
  • 具名 agent 使用小写 OpenViking peer ID(agent 名 strip + lower);
  • 不是合法 peer ID、与默认值冲突、或进入保留的 df-agent- 命名空间的名字,会映射到抗碰撞 ID:_canonical_peer_id 对其 SHA-256 摘要取前 32 位拼上 df-agent- 前缀,保证与合法名互不别名;
  • USER Key 身份始终是安全边界;peer 只在该用户内部隔离记忆作用域。

检索时,_memory_target_uris 同时查询 viking://user/memories(用户全局)与 viking://user/peers/{peer_id}/memories(当前 peer)。在 get_context 中,如果请求带 thread_id,检索器切换为 search 模式并绑定该线程的 Session;否则为 find 模式做跨 Session 检索。

重试、游标与失败语义

读写失败策略的落点

  • read: fail_open:检索失败记日志并返回空字符串(无注入记忆);read: raise 向 DeerFlow 调用方传播异常。对应 get_context / search 的异常分支:捕获异常后按策略 raiselogger.warning 降级。
  • write: log_and_drop:捕获失败记日志,但不使已生成的回答失败;write: raise 则抛出 MemoryManagerError。见 _handle_write_error
  • 启动期健康检查由 startup_policy 控制:fail_fast 下不健康直接抛错,warn 下降级运行(warm)。

只存哈希的本地捕获游标

DeerFlow 只在 {storage_path}/openviking/sessions/ 下维护一个有界的本地捕获游标,其中只有哈希与计数器,从不存消息文本。游标的作用:

  • 防止把完整的 LangGraph transcript 快照重复提交(每次捕获前用 _matching_prefix_count 比对已提交前缀,或基于 submitted_prefix_count + 前缀摘要处理压缩后的情况);
  • 记录部分批次中已确认的进度,在追加更多消息前先重试失败的 commit(见下文);
  • 不可读的游标按失败关闭处理:重放未知前缀可能复制私有对话历史,_load_cursor 对读不到/解析失败的游标直接抛 MemoryManagerError,拒绝不安全重放。

游标写入采用「临时文件 + os.replace」的原子替换(_save_cursor),避免半写状态。

消息签名的计算见 _message_signature:对 id / role / content / tool_calls / tool_call_id / tool_name / tool_status 做规范化 JSON 后 SHA-256,因此工具调用与结果的变化也会被感知。

部分写入与提交重试

捕获路径 _capture_locked 的流程:

  1. 若游标标记 commit_pending,先调用 recorder.flush(session_id) 重试上次未完成的提交;重试失败则按写策略处理并保留游标
  2. 计算已提交前缀,只提交增量 pending 消息;
  3. 捕获官方适配器抛出的 OpenVikingPartialWriteError:按 input_messages_consumed 把已确认前缀写入游标(commit_pending 一并记录),下次捕获时先重试 commit;
  4. 其他异常不推进游标;
  5. 全部成功后推进游标并清空 commit_pending

整个写入在每 Session 一把 RLock_session_lock)下串行,避免并发捕获互相覆盖游标。

优雅关闭

shutdown_flush(timeout)openviking_manager.py#L288-L301):置关闭标志停止新工作,在 shutdown_flush_timeout_seconds 预算内等待已接受的操作排空,然后关闭 recorder 拥有的 SDK 客户端。它不引入新的 DeerFlow 生命周期或后台 worker,完全复用既有 memory 关闭契约。

明确的局限:不承诺 at-least-once

对于「丢失一次记忆更新不可接受」的部署,仍然需要引入持久化 outbox。该初始集成不声称 at-least-once 投递——write: log_and_drop 下的写入丢失是有意的可恢复性取舍,而非静默承诺。

适用前提与验证路径

按上述步骤完成配置后,DeerFlow 会在每轮对话后把可捕获消息增量提交到该线程的 OpenViking Session,并在下一轮按固定查询把记忆注入系统提示;整个链路的身份隔离由 USER Key + owner_user_id 双重约束,任何跨用户访问都会在触达 OpenViking 之前被拒绝。

登录后查看全文
热门项目推荐
相关项目推荐

项目优选

收起
kernelkernel
deepin linux kernel
C
33
18
ops-transformerops-transformer
本项目是CANN提供的transformer类大模型算子库,实现网络在NPU上加速计算。
C++
1.12 K
2.72 K
kernelkernel
openEuler内核是openEuler操作系统的核心,既是系统性能与稳定性的基石,也是连接处理器、设备与服务的桥梁。
C
528
588
ops-nnops-nn
本项目是CANN提供的神经网络类计算算子库,实现网络在NPU上加速计算。
C++
906
1.83 K
pytorchpytorch
作为 Ascend for PyTorch 社区的核心组件,TorchNPU 是昇腾专为 PyTorch 打造的深度学习适配插件,使 PyTorch 框架能够直接调用昇腾 NPU,为开发者提供昇腾 AI 处理器的超强算力。
Python
854
1.34 K
docsdocs
暂无描述
Markdown
891
5.78 K
jiuwenswarmjiuwenswarm
JiuwenSwarm 是一款基于openJiuwen开发的智能AI Agent,它能够将大语言模型的强大能力,通过你日常使用的各类通讯应用,直接延伸至你的指尖。
Python
3.53 K
1.01 K
ops-mathops-math
本项目是CANN提供的数学类基础计算算子库,实现网络在NPU上加速计算。
C++
1.34 K
1.45 K
cann-learning-hubcann-learning-hub
CANN 学习中心仓,支持在线互动运行、边学边练,提供教程、示例与优化方案,一站式助力昇腾开发者快速上手。
Jupyter Notebook
987
506
AscendNPU-IRAscendNPU-IR
AscendNPU-IR是基于MLIR(Multi-Level Intermediate Representation)构建的,面向昇腾亲和算子编译时使用的中间表示,提供昇腾完备表达能力,通过编译优化提升昇腾AI处理器计算效率,支持通过生态框架使能昇腾AI处理器与深度调优
C++
540
384