Files
memory-gateway/docs/openviking_memory_api_flow.md
tomtan 70cda923b2 Refactor OpenViking Memory API and User Management
- Updated API authentication headers to use `X-API-Key` for both admin and user APIs.
- Modified the account creation process to directly create user-specific accounts without requiring an admin workspace.
- Enhanced user creation to return account-specific details, including `admin_user_id`.
- Introduced new endpoints for retrieving task status and user profiles, allowing for more flexible user data management.
- Updated search functionality to include additional parameters such as `level` and `score_threshold`.
- Improved the handling of user keys in the storage layer to associate them with specific accounts.
- Added tests to validate the new user account creation process and search functionalities, ensuring proper integration with the OpenViking service.
- Included new documentation to reflect changes in API usage and expected request/response formats.
2026-05-27 16:09:28 +08:00

9.4 KiB
Raw Blame History

OpenViking Memory API 流程说明

本文档整理 OpenViking 中「创建账号/用户 → 创建 session → 写入消息 → commit 抽取长期 memory → 查询 task 状态 → 检索 user memory/session memory」的完整 API 流程。

出于安全原因,示例中不写入真实 root_api_keyuser_key,统一使用环境变量占位。

0. 前置变量

# 在config.yaml里设置的 openviking url 和 api_key
export OV_HOST="http://localhost:1933"
export ROOT_KEY="your-secret-root-key"

# 创建用户后填入返回的 user_key
export USER_A_KEY="<userA-user-key>"
export USER_B_KEY="<userB-user-key>"

OpenViking 的常见鉴权方式:

场景 Header
Admin API例如创建 account X-API-Key: $ROOT_KEY
普通用户 API例如 session/message/search X-API-Key: $USER_A_KEY

1. 创建用户隔离工作区 / account

Admin API 用于多租户管理。Memory Gateway 为每个业务用户直接创建一个 admin account不再调用 /api/v1/admin/accounts/admin/users

curl -X POST "$OV_HOST/api/v1/admin/accounts" \
  -H "X-API-Key: $ROOT_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "account_id": "userA_account",
    "admin_user_id": "userA"
  }'

典型返回:

{
  "status": "ok",
  "result": {
    "account_id": "userA_account",
    "admin_user_id": "userA",
    "user_key": "<userA-user-key>"
  },
  "error": null,
  "telemetry": null
}

2. 创建更多用户

2.1 创建 userA

curl -X POST "$OV_HOST/api/v1/admin/accounts" \
  -H "X-API-Key: $ROOT_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "account_id": "userA_account",
    "admin_user_id": "userA"
  }'

返回后保存:

export USER_A_KEY="<userA-user-key>"

2.2 创建 userB

curl -X POST "$OV_HOST/api/v1/admin/accounts" \
  -H "X-API-Key: $ROOT_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "account_id": "userB_account",
    "admin_user_id": "userB"
  }'

返回后保存:

export USER_B_KEY="<userB-user-key>"

注意:不同用户必须使用各自的 user_key。用 userA 的 key 只能访问 userA 的用户空间,用 userB 的 key 只能访问 userB 的用户空间。


3. 创建 session

Session 是会话容器用于保存消息、跟踪上下文使用、commit 后抽取长期 memories。

3.1 创建 userA 的 sessionA1

curl -X POST "$OV_HOST/api/v1/sessions" \
  -H "X-API-Key: $USER_A_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "session_id": "sessionA1"
  }'

典型返回:

{
  "status": "ok",
  "result": {
    "session_id": "sessionA1",
    "user": {
      "account_id": "userA_account",
      "user_id": "userA",
      "agent_id": "default"
    }
  },
  "error": null,
  "telemetry": null
}

3.2 创建 userB 的 sessionB1

curl -X POST "$OV_HOST/api/v1/sessions" \
  -H "X-API-Key: $USER_B_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "session_id": "sessionB1"
  }'

4. 写入 session 消息

HTTP API 支持简单文本模式:role + contentrole 通常为 userassistant

4.1 写入 userA / sessionA1 消息

curl -X POST "$OV_HOST/api/v1/sessions/sessionA1/messages" \
  -H "X-API-Key: $USER_A_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "role": "user",
    "content": "我喜欢用 Python 写数据分析脚本。"
  }'
curl -X POST "$OV_HOST/api/v1/sessions/sessionA1/messages" \
  -H "X-API-Key: $USER_A_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "role": "assistant",
    "content": "好的,我会记住你偏好 Python 数据分析。"
  }'

4.2 写入 userB / sessionB1 消息

curl -X POST "$OV_HOST/api/v1/sessions/sessionB1/messages" \
  -H "X-API-Key: $USER_B_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "role": "user",
    "content": "我喜欢用 vibe coding 写项目。"
  }'
curl -X POST "$OV_HOST/api/v1/sessions/sessionB1/messages" \
  -H "X-API-Key: $USER_B_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "role": "assistant",
    "content": "好的,我会记住你偏好 vibe coding 项目。"
  }'

5. Commit session触发长期 memory 抽取

commit 是两阶段流程:

  1. Phase 1同步完成:把当前 live messages 快照归档,创建 archive 目录,清空 live session。
  2. Phase 2异步完成:生成 session 摘要,抽取长期 memories更新关系和 active count。

因此 commit 请求会很快返回 task_id,后续要轮询 task 状态。

5.1 Commit userA / sessionA1

curl -X POST "$OV_HOST/api/v1/sessions/sessionA1/commit" \
  -H "X-API-Key: $USER_A_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "keep_recent_count": 0
  }'

典型返回:

{
  "status": "ok",
  "result": {
    "session_id": "sessionA1",
    "status": "accepted",
    "task_id": "fe6510e1-fdee-4f2d-9f87-5e48b519c2a2",
    "archive_uri": "viking://session/userA/sessionA1/history/archive_001",
    "archived": true
  }
}

5.2 Commit userB / sessionB1

curl -X POST "$OV_HOST/api/v1/sessions/sessionB1/commit" \
  -H "X-API-Key: $USER_B_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "keep_recent_count": 0
  }'

6. 查询 commit task 状态

curl -s "$OV_HOST/api/v1/tasks/<task_id>" \
  -H "X-API-Key: $USER_A_KEY" | jq .

成功完成后类似:

{
  "status": "ok",
  "result": {
    "task_id": "fe6510e1-fdee-4f2d-9f87-5e48b519c2a2",
    "task_type": "session_commit",
    "status": "completed",
    "resource_id": "sessionA1",
    "result": {
      "session_id": "sessionA1",
      "archive_uri": "viking://session/userA/sessionA1/history/archive_001",
      "memories_extracted": {
        "preferences": 1
      },
      "active_count_updated": 0
    },
    "error": null
  },
  "error": null,
  "telemetry": null
}

关键字段说明:

字段 含义
status: completed Phase 2 已完成memory 抽取结束
result.archive_uri 本次归档目录 URI
result.memories_extracted 本次 commit 提取到的 memory 分类计数,不是 memory 内容
active_count_updated 本次基于 sessions/{id}/used 使用记录更新的活跃计数数量

如果返回:

"status": "running"

说明后台任务还没完成。此时可以稍后继续查询同一个 task。


7. 用 search/find 向量搜索 user 长期 memory

find 是纯向量检索,不使用 session 上下文,也不做意图分析。适合直接按语义检索用户长期 memory。

使用显式用户路径:

curl -s -X POST "$OV_HOST/api/v1/search/find" \
  -H "Content-Type: application/json" \
  -H "X-API-Key: $USER_A_KEY" \
  -d '{
    "query": "我之前说了什么",
    "target_uri": "viking://user/userA/memories/",
    "limit": 3
  }' | jq .

典型返回:

{
  "status": "ok",
  "result": {
    "memories": [
      {
        "context_type": "memory",
        "uri": "viking://user/userA/memories/preferences/mem_xxx.md",
        "level": 2,
        "score": 0.7411,
        "abstract": "Python 数据分析:偏好使用 Python 编写数据分析脚本"
      }
    ],
    "resources": [],
    "skills": [],
    "total": 1
  }
}

9. 用 search/search 做带 session 上下文的 LLM 搜索

search 是智能检索:在 find 的基础上增加 session context、意图分析和 query expansion。它适合「用户当前对话里有上下文查询语义不完整」的场景。

curl -s -X POST "$OV_HOST/api/v1/search/search" \
  -H "Content-Type: application/json" \
  -H "X-API-Key: $USER_A_KEY" \
  -d '{
    "query": "我正在做什么",
    "target_uri": "viking://user/userA/sessionA1", # 
    "session_id": "sessionA1",
    "limit": 10,
  }

典型返回:

{
  "status": "ok",
  "result": {
    "memories": [],
    "resources": [],
    "skills": [],
    "total": 0,
    "query_plan": {
      "reasoning": "1. Conversational task (user asking '我正在做什么' - 'What am I doing?'); 2. This is a simple conversational query about current state/activity; 3. The session context contains the user's previous interactions about Python preferences and EverOS API questions; 4. No specific context gaps need to be filled for this conversational task, but a memory query about the user's current activity context could help provide a more personalized response",
      "queries": [
        {
          "query": "User's current activity and task context",
          "context_type": "memory",
          "intent": "Understand what the user is currently working on to provide relevant context",
          "priority": 3
        }
      ]
    }
  }
}

10. findsearch 的选择

接口 是否使用 session 上下文 是否做意图分析 适合场景
/api/v1/search/find 直接按 query 做向量检索,稳定查 user memory
/api/v1/search/search 是,可传 session_id 对话式检索,需要结合 session 语境、自动扩展 query

推荐实践:

  1. 验证 memory 是否已经写入:先用 tasks/{task_id} 确认 completed
  2. 确认 user 长期 memory 是否可召回:用 /api/v1/search/findquery 写得贴近 memory 内容。
  3. 需要结合当前会话上下文:再用 /api/v1/search/searchsession_id