Memory Gateway

Memory Gateway 是一个轻量级记忆网关项目,用统一的 HTTP API 把上层应用接到两个记忆后端:

  • OpenViking负责会话归档、长期记忆抽取、按 user_id / session_id 隔离的语义检索。
  • EverOS负责用户画像、episodic memory、profile 查询等补充记忆能力。

当前重点模块是 memory_system_api。它不是 OpenViking 的替代品,而是一个更窄的业务网关:上层只面对 user、user key、session 和 message网关内部固定使用 OpenViking admin 工作区。

核心模型

身份字段

字段 含义 是否自定义 备注
user_id 真实终端用户 先通过 /users 创建后续写入、查询、commit 时使用
user_key OpenViking 返回的用户 key /users 返回并写入 SQLite业务调用时随请求体或 query 传入
session_id 一次会话 ID OpenViking session 容器,同时用于带 session context 的搜索

建议 ID 只使用字母、数字、_-.@,不要使用空格、斜杠或中文。

先创建用户再使用

除健康检查外,业务调用分两步:

  1. 调用 POST /memory-system/users 创建 OpenViking user。
  2. 保存返回的 user_key后续写入消息、commit、extract、task、search、profile 都传 user_id + user_key,不需要传 account_id

如果没有先创建 user或者 user_key 与数据库里的 user_id 不匹配,messagescommitextracttaskssearchprofile 都会返回 401

第一次创建业务 user 时,如果 SQLite 里还没有 OpenViking admin 工作区记录,网关会先调用 OpenViking

POST /api/v1/admin/accounts
{"account_id": "admin", "admin_user_id": "admin"}

随后创建具体用户:

POST /api/v1/admin/accounts/admin/users
{"user_id": "<user_id>", "role": "user"}

后续创建第二、第三个用户时,网关直接调用 /api/v1/admin/accounts/admin/users。所有返回的 user_id / user_key、创建过的 session_id、commit 返回的 task_id / archive_uri 都写入 SQLite不放在进程内缓存里。

鉴权

Memory Gateway 有两类 key

Key 请求头 用途 是否必需
Memory System API key X-API-Key 保护 Memory Gateway 服务本身 仅当 server.api_key 配置非空时需要
OpenViking user key 请求体/query 的 user_key 校验具体用户并调用 OpenViking 普通用户 API /health/users 外都需要

OpenViking 的 root key 配在服务端 config.yaml 中,由网关内部使用。调用方不需要也不应该在业务请求中传 OpenViking root key。

OpenViking 内部调用遵循:

OpenViking 场景 鉴权
Admin API例如创建 account/user X-API-Key: <openviking root key>
普通用户 API例如 session/message/commit/task/search Authorization: Bearer <openviking user key>

Session 与搜索范围

OpenViking session 由请求里的 session_id 创建和提交。普通向量搜索使用显式用户 memory 路径 viking://user/<user_id>/memories/use_llm=true 的智能搜索会同时传 session_idtarget_uri: viking://user/<user_id>/<session_id>,用于结合当前 session context。

安装

cd /home/tom/memory-gateway
python -m venv .venv
source .venv/bin/activate
pip install -U pip
pip install -e ".[dev]"

配置

复制配置模板:

cp config.example.yaml config.yaml

主要配置:

server:
  host: "127.0.0.1"
  port: 1934
  api_key: ""

openviking:
  url: "http://127.0.0.1:1933"
  api_key: "your-secret-root-key"
  timeout: 30
  verify_ssl: true

everos:
  url: "http://127.0.0.1:1995"
  api_key: ""
  timeout: 180
  verify_ssl: true
  health_path: "/health"

storage:
  sqlite_path: "/home/tom/memory-gateway/memory_system_api.sqlite3"

环境变量也可以覆盖部分配置:

环境变量 覆盖字段
MEMORY_SYSTEM_SERVER_API_KEY server.api_key
MEMORY_SYSTEM_SERVER_HOST server.host
MEMORY_SYSTEM_SERVER_PORT server.port
OPENVIKING_URL / OPENVIKING_BASE_URL openviking.url
OPENVIKING_API_KEY openviking.api_key
EVEROS_URL / EVEROS_BASE_URL everos.url
EVEROS_API_KEY everos.api_key
MEMORY_SYSTEM_STORAGE_SQLITE_PATH storage.sqlite_path

启动

先启动 OpenViking 和 EverOS再启动 Memory System API

python -m memory_system_api.server --config config.yaml --host 127.0.0.1 --port 1934

如果 server.api_key 非空,所有请求还要加:

-H "X-API-Key: <memory-system-api-key>"

API 总览

Base URL

http://127.0.0.1:1934/memory-system
方法 路径 作用 User key
GET /health 检查 OpenViking 和 EverOS 健康状态 不需要
POST /users 在固定 admin 工作区创建 OpenViking user并保存 user key 不需要
POST /messages 写入一轮或半轮会话消息 需要
POST /sessions/{session_id}/commit 提交会话,触发 OpenViking commit 和 EverOS flush 需要
POST /sessions/{session_id}/extract 立即触发 OpenViking extract 需要
GET /openviking/tasks/{task_id} 查询 OpenViking 后台任务状态 需要
POST /search 同时搜索 OpenViking 和 EverOS 记忆 需要
GET /users/{user_id}/profile 查询 EverOS profile 需要

API 详情

GET /health

检查两个后端是否可访问。

curl -sS http://127.0.0.1:1934/memory-system/health

返回字段:

字段 含义
status successpartial_successfailed
backends.openviking OpenViking 健康检查结果
backends.everos EverOS 健康检查结果

POST /users

创建新的 OpenViking user并把返回的 user_id / user_key 保存到本地 SQLite。

请求体:

参数 类型 必需 说明
user_id string 要创建的用户 ID

示例:

curl -sS -X POST http://127.0.0.1:1934/memory-system/users \
  -H "Content-Type: application/json" \
  -d '{"user_id": "userA"}'

返回中的 account.result.user_key 是后续业务调用要传的 user_key

{
  "status": "success",
  "account": {
    "status": "ok",
    "result": {
      "account_id": "admin",
      "user_id": "userA",
      "user_key": "..."
    }
  }
}

POST /messages

写入用户消息和/或助手消息。至少要传 user_messageassistant_message 其中一个。网关会先确保 OpenViking user/session 存在,再把消息写入 OpenViking session同时写入 EverOS。

请求体:

参数 类型 必需 说明
user_id string 已创建的用户 ID
user_key string /users 返回的 user key
session_id string 会话 ID
user_message string/null 用户消息
assistant_message string/null 助手消息
timestamp int/null 预留字段
metadata object 预留字段

示例:

USER_KEY="..."

curl -sS -X POST http://127.0.0.1:1934/memory-system/messages \
  -H "Content-Type: application/json" \
  -d '{
    "user_id": "userA",
    "user_key": "'"$USER_KEY"'",
    "session_id": "sessionA1",
    "user_message": "请记住:我喜欢拿铁。",
    "assistant_message": "好的,我记住了。"
  }'

POST /sessions/{session_id}/commit

提交会话。OpenViking 会归档 session 并异步抽取长期记忆,通常会返回 task_idEverOS 会 flush 当前 session。

路径参数:

参数 类型 说明
session_id string 要提交的会话 ID

请求体:

参数 类型 必需 说明
user_id string 用户 ID
user_key string /users 返回的 user key

示例:

curl -sS -X POST http://127.0.0.1:1934/memory-system/sessions/sessionA1/commit \
  -H "Content-Type: application/json" \
  -d '{
    "user_id": "userA",
    "user_key": "'"$USER_KEY"'"
  }'

如果返回里有 OpenViking task_id,需要继续查询任务直到完成。

POST /sessions/{session_id}/extract

立即触发 OpenViking extract只作用于 OpenViking不触发 EverOS flush。适合调试或明确要求“现在就抽取”的场景。

参数同 commit

curl -sS -X POST http://127.0.0.1:1934/memory-system/sessions/sessionA1/extract \
  -H "Content-Type: application/json" \
  -d '{
    "user_id": "userA",
    "user_key": "'"$USER_KEY"'"
  }'

GET /openviking/tasks/{task_id}

查询 OpenViking 后台任务状态,例如 commit 返回的任务。

Query 参数:

参数 类型 必需 说明
user_id string 用户 ID
user_key string /users 返回的 user key
session_id string/null 会话 ID传入后会按同一 session identity 查询

示例:

curl -sS -X POST "http://127.0.0.1:1934/memory-system/openviking/tasks/${TASK_ID}" \
  -H "Content-Type: application/json" \
  -d '{
    "user_id": "userA",
    "user_key": "'"$USER_KEY"'",
    "session_id": "sessionA1"
  }'

POST /search

同时查询 OpenViking 和 EverOS并合并结果。

请求体:

参数 类型 必需 说明
user_id string 用户 ID
user_key string /users 返回的 user key
session_id string/null 会话 IDuse_llm=true 时会作为 OpenViking search 的 session context
query string 查询文本
use_llm bool false 使用 OpenViking find + EverOS hybridtrue 使用 OpenViking search + EverOS agentic
limit int 返回条数,默认 10范围 1 到 100

示例:

curl -sS -X POST http://127.0.0.1:1934/memory-system/search \
  -H "Content-Type: application/json" \
  -d '{
    "user_id": "userA",
    "user_key": "'"$USER_KEY"'",
    "session_id": "sessionA1",
    "query": "我喜欢喝什么?",
    "use_llm": false,
    "limit": 10
  }'

返回字段:

字段 含义
status 总体状态
items 合并后的记忆结果,含 source_backend
backends 两个后端的精简诊断信息例如命中数量、query plan 或查询过滤条件;不再回传完整原始命中和 original_data

GET /users/{user_id}/profile

读取 EverOS profile。该接口需要 user_key,用于确认调用方属于该 user。

示例:

curl -sS "http://127.0.0.1:1934/memory-system/users/userA/profile?user_key=$USER_KEY"

完整测试流程

API=http://127.0.0.1:1934/memory-system

curl -sS -X POST "$API/users" \
  -H "Content-Type: application/json" \
  -d '{"user_id":"userA"}'

USER_KEY="把上一步返回的 account.result.user_key 填到这里"

curl -sS -X POST "$API/messages" \
  -H "Content-Type: application/json" \
  -d '{
    "user_id": "userA",
    "user_key": "'"$USER_KEY"'",
    "session_id": "sessionA1",
    "user_message": "请记住:我在 sessionA1 喜欢拿铁,项目代号 alpha-session。",
    "assistant_message": "好的。"
  }'

curl -sS -X POST "$API/sessions/sessionA1/commit" \
  -H "Content-Type: application/json" \
  -d '{"user_id":"userA","user_key":"'"$USER_KEY"'"}'

curl -sS -X POST "$API/search" \
  -H "Content-Type: application/json" \
  -d '{
    "user_id": "userA",
    "user_key": "'"$USER_KEY"'",
    "session_id": "sessionA1",
    "query": "我喜欢喝什么?",
    "limit": 10
  }'

OpenViking commit 返回 task_id 后,轮询到 completed 再搜索长期 memory

curl -sS "$API/openviking/tasks/<task_id>?user_id=userA&user_key=$USER_KEY&session_id=sessionA1"

开发检查

PYTHONPATH=/home/tom/memory-gateway pytest -q
python -m compileall -q memory_system_api plugins eval tests

Hermes Plugin 状态

仓库里仍保留 Hermes memory providerplugins/memory/memory_system

注意Memory System API 已切换为 user_id + user_key 鉴权plugin 代码如需继续使用,需要同步传递这两个字段。

Description
No description provided
Readme 4 MiB
Languages
Python 100%