Skip to content

多租户 ​

OpenViking 的多租户不是“为每个团队部署一套独立服务”,而是在同一个 Server 内,通过 account 和 user 两层身份边界隔离和共享数据。

它适合两类典型场景:

  • 多个团队或客户共享一套 OpenViking 服务,但数据必须隔离
  • 一个团队内的多个用户需要共享资源、隔离记忆

能做什么 ​

启用多租户后,你可以:

  • 用一个 OpenViking Server 服务多个团队、客户或应用
  • 用 account 隔离不同团队的数据
  • 在同一个 account 内共享 resources,并用 ACL 对目录或文件细化授权
  • 用 user 隔离用户级记忆和会话
  • 用 ROOT / ADMIN / USER 角色分层管理权限
  • 支持 OpenClaw 插件、Vikingbot、CLI、HTTP SDK 等不同接入方式

核心身份模型 ​

account_id ​

account 是最外层租户边界,可以理解为工作区、团队或客户空间。

  • 不同 account 之间的数据默认完全隔离
  • Root 用户可以创建、删除 account
  • resources、user、session 都落在某个 account 下

user_id ​

user 是 account 内的用户边界。

  • 用户记忆和用户会话按 user_id 隔离
  • 普通 user 只能访问自己的 user space
  • admin 可以管理本 account 下的用户

角色 ​

角色作用域典型能力
ROOT全局创建/删除 account、管理用户;API Key 模式下不用于租户数据读写
ADMIN单个 account管理本 account 的用户、重置 user key
USER单个 account访问自己的 user/peer/session 数据和 account 内共享资源

认证模式 ​

OpenViking Server 支持两种多租户相关认证模式:

模式配置身份来源适用场景
api_keyserver.auth_mode = "api_key"Root key 或 user key标准部署方式
trustedserver.auth_mode = "trusted"上游显式注入 X-OpenViking-Account / X-OpenViking-User受信网关后面

在 trusted 模式下,上游网关还可以断言 X-OpenViking-Role: user 或 X-OpenViking-Role: admin。角色断言要求服务端已配置 root_api_key,且请求携带匹配的 API Key。X-OpenViking-Role: root 会被拒绝;ROOT 只保留给已校验的 Admin API 回退路径。

root_api_key 的作用 ​

在 api_key 模式下,配置 server.root_api_key 后启用基于 key 的账户和用户管理:

  • Root key 用于管理 account 和 user
  • User key 由 Admin API 生成,用于普通业务读写
  • 服务端会从 user key 反解出 account_id、user_id 和角色

如果 auth_mode = "api_key" 且未配置 root_api_key,服务端会进入开发模式:

  • 默认所有请求都被视为 ROOT
  • 默认身份是 default/default
  • 只允许绑定在 localhost 上使用

共享与隔离边界 ​

逻辑层 ​

数据类型是否跨 account 共享account 内是否共享默认隔离边界
共享资源 (viking://resources)否默认共享,可用 ACL 限制account / ACL
用户资源 (viking://user/{user_id}/resources)否否user
Peer 资源 (viking://user/{user_id}/peers/{peer_id}/resources)否否user / peer
记忆否否user / peer
私有技能 (viking://user/{user_id}/skills)否否user
共享技能 (viking://agent/skills)否是,受访问权限约束account
会话否否user / session

存储层 ​

对用户来说,URI 仍然是统一的 viking://...:

text
viking://resources/project-a/
viking://user/alice/memories/
viking://user/alice/resources/
viking://user/alice/peers/web-visitor-alice/resources/

但底层存储会自动带上 account 前缀:

text
/local/{account_id}/resources/project-a/
/local/{account_id}/user/alice/memories/
/local/{account_id}/user/alice/resources/
/local/{account_id}/user/alice/peers/web-visitor-alice/resources/

因此多租户隔离不是靠“不同 URI 前缀”,而是靠请求上下文中的 account_id 和 user_id 共同生效。

文件系统与检索层 ​

文件系统操作和语义检索都受租户约束:

  • 非 ROOT 请求会自动按 account_id 过滤
  • resources 默认允许检索 account 内共享资源;开启账号级 acl.enabled 并设置 ACL 后按有效 ACL 过滤
  • 用户资源始终按当前 user space 隔离;需要共享时移动到 viking://resources
  • 记忆和私有技能按当前 user space 过滤;共享技能位于 account 内的 viking://agent/skills
  • Actor peer 会把 viking://user/{user}/peers 过滤到一个 peer,并作用于文件系统和检索操作

这意味着“能搜到什么”与“能读到什么”保持一致,不会因为向量召回而越权。

Peer 集合过滤 ​

peer_id 是当前 user 边界内的内容范围,不会改变 tenant 或 user 身份。

当一次请求只应该看到当前用户 peer 集合中的某一个 peer 时,设置 X-OpenViking-Actor-Peer: <peer_id>,或使用 SDK/CLI 的 actor_peer_id:

  • 空 target 检索仍包含当前用户根和公共 viking://resources。
  • 检索解析到 viking://user/{user}/peers 时,只选择该 peer 的 memories/resources。
  • 文件系统操作不能 read、list、tree、grep/search/find、write、move 或 delete viking://user/{user}/peers 下的其他 peer。
  • User-scoped memories、resources、skills、共享 resources 和 session 归属不因 actor peer 改变。
  • peer ID 必须是安全的单段路径标识,例如 web-visitor-alice。

标准使用流程 ​

1. 启用多租户 ​

json
{
  "server": {
    "auth_mode": "api_key",
    "root_api_key": "your-secret-root-key"
  }
}

2. ROOT 创建工作区和首个管理员 ​

bash
curl -X POST http://localhost:1933/api/v1/admin/accounts \
  -H "Content-Type: application/json" \
  -H "X-API-Key: your-secret-root-key" \
  -d '{
    "account_id": "acme",
    "admin_user_id": "alice"
  }'

3. ADMIN 或 ROOT 注册普通用户 ​

bash
curl -X POST http://localhost:1933/api/v1/admin/accounts/acme/users \
  -H "Content-Type: application/json" \
  -H "X-API-Key: <admin-or-root-key>" \
  -d '{
    "user_id": "bob",
    "role": "user"
  }'

4. 普通业务访问优先使用 user key ​

常规读写、搜索、会话提交等请求,优先用 user key:

bash
curl http://localhost:1933/api/v1/fs/ls?uri=viking:// \
  -H "X-API-Key: <bob-user-key>"

这样服务端可以直接从 key 反解身份,无需额外传 account / user。

5. 数据 API 身份来自 user 或 admin key ​

在 api_key 模式下,ls、find、sessions 这类租户级数据 API 会从 API key 自身解析有效的 account 和 user。不要在该模式下发送 X-OpenViking-Account 或 X-OpenViking-User;基于 header 的身份断言只属于 trusted mode。

ADMIN key 可以用它自己的 account/user 身份访问数据 API:

bash
curl http://localhost:1933/api/v1/fs/ls?uri=viking:// \
  -H "X-API-Key: <admin-user-key>"

ROOT key 用于 Admin API 以及少量 system/monitoring API。它在 api_key 模式下不能访问租户级数据 API,因为它没有绑定到某个租户用户。数据访问请使用 user/admin key;如果需要上游断言身份,请使用 trusted mode。

接入实践 ​

OpenClaw 插件 2.0:每个实例使用 user key ​

OpenClaw 插件当前的多租户实践是“插件侧只持有一个用户身份”:

  • 远程模式配置 baseUrl + apiKey,可选 peer_role / peer_prefix
  • apiKey 推荐配置为某个 user 的 user key
  • 服务端从 user key 自动解析 account_id 和 user_id
  • 插件把 OpenClaw agent 身份保留在 peer/session metadata 中,而不是租户 header 中

典型配置:

bash
openclaw config set plugins.entries.openviking.config.mode remote
openclaw config set plugins.entries.openviking.config.baseUrl "http://your-server:1933"
openclaw config set plugins.entries.openviking.config.apiKey "<user-api-key>"
openclaw config set plugins.entries.openviking.config.peer_role assistant
openclaw config set plugins.entries.openviking.config.peer_prefix "<peer-prefix>"

这种模式的特点:

  • 接入简单,插件不需要管理 account/user 生命周期
  • 最适合“一个 OpenClaw 实例对应一个 OpenViking 用户”的场景
  • peer_prefix 用于区分 OpenClaw 运行时身份,参与 peer/session 元数据
  • 同一 account 内的 resources 默认共享,也可以通过 ACL 限制到指定用户;memory 按 user scope 隔离

OpenClaw 插件为何通常不配 account / user ​

因为在 api_key 模式下,user key 已经足够表达身份:

  • account、user 由服务端从 key 反解
  • 插件可以提供 peer_prefix 作为运行时身份标签
  • 插件内部写入 user-scoped memory,并用 peer_id 表达每条消息的说话人

如果给插件直接配置 root key,则普通租户数据 API 没有从 key 绑定出来的租户用户, 这不适合作为日常读写方式。

VikingBot:匹配 Server 的认证模式 ​

当前 VikingBot 通过 bot.ov_server.api_key_type 选择连接方式,不会通过 root key 自动注册并缓存每个终端用户的 user key:

  • user:连接 api_key 模式的 Server,api_key 必须是 User/Admin key,数据身份由 key 决定。
  • root:用于 trusted 模式,Bot 以受信连接传递 account/user 身份;不能拿它访问 api_key 模式的租户数据接口。
  • 同配置启动时可以继承当前 Server 的地址和认证设置;外部 Server 应显式配置连接。

固定用户身份的配置示例:

json
{
  "bot": {
    "ov_server": {
      "server_url": "http://127.0.0.1:1933",
      "api_key_type": "user",
      "api_key": "your-user-api-key"
    }
  }
}

共享同一个 user key 的聊天参与者仍属于同一 OpenViking user。actor_peer_id 可限制其 peer 集合视图,但不会把该用户自己的记忆和共享资源变成逐聊天用户私有数据。需要独立 user 边界时,应由可信身份入口提供不同的用户连接或使用 trusted 身份传递,见VikingBot 安装与配置。

什么时候选哪种实践 ​

场景推荐方式
一个 OpenClaw 实例对应一个固定身份OpenClaw 插件 + user key
一个网关/机器人服务承载很多最终用户按用户配置连接或由受信入口传递 trusted 身份
受信网关统一注入身份trusted 模式
单机本地体验、无需真正租户隔离开发模式(无 root_api_key)

常见误区 ​

1. root_api_key 不是常规业务 key ​

Root key 主要用于:

  • 创建/删除 account
  • 注册用户
  • 重置 key
  • 运维和调试

正常业务请求应按调用者身份使用 user key 或 admin key。

2. peer_id 不决定 account ​

peer_id 表示当前用户下的交互对象。它不创建租户,但可以通过显式 peer URI 或 peer 集合过滤选择当前用户内的 peer 内容子空间,例如 viking://user/{user_id}/peers/{peer_id}/memories 或 viking://user/{user_id}/peers/{peer_id}/resources。

  • account 边界由 account_id 决定
  • user 边界由 user_id 决定
  • peer 内容仍位于该 user 边界内

3. 不配置 root_api_key 不等于“单租户正式部署” ​

这只是开发模式:

  • 默认全部请求以 ROOT 身份运行
  • 不适合暴露到公网或团队共享环境

4. OpenClaw 插件和 Vikingbot 不是同一种租户实践 ​

  • OpenClaw 插件:更像“客户端拿到一个 user 身份后直接访问”
  • VikingBot:支持固定 User/Admin key,也可作为受信入口传递身份;选择取决于 Server 认证模式

相关文档 ​

Open source under the AGPL-3.0 License. Font licenses