Memory Gateway
Memory Gateway 是一个本地 memory/context gateway,用统一的 HTTP、MCP 和 Hermes skill 入口,把上层 agent 的记忆写入、上下文检索、会话提交和知识沉淀路由到 OpenViking、EverOS、SQLite metadata store 和可选 Obsidian vault。
当前项目的主线是 OpenViking + EverOS 双后端:
- OpenViking 运行在
127.0.0.1:1933,负责 session/resource/context 层能力。 - EverOS/EverCore 运行在
127.0.0.1:1995,负责长期记忆、profile 和检索。 - Memory Gateway 默认运行在
127.0.0.1:1934,提供统一 API、认证、metadata、outbox 和 adapter 编排。
核心能力
/v2/conversations/ingest:把一轮对话写入 OpenViking 和 EverOS,并在本地保存memory_refs控制面引用。/v2/context/retrieve:实际调用 OpenViking / EverOS 的 retrieve 接口,把两个后端返回的上下文合并到items。/v2/conversations/{session_id}/commit:创建 commit job 和 outbox events,用于异步生成长期 ref。/v2/admin/outbox/process:处理 pending outbox,生成 OpenViking session ref、EverOS profile ref、EverOS long-term ref。/v2/memory/refs:查询本地保存的后端引用元数据。/v1/*:保留基础用户、memory、episode、session commit、audit 和 EverOS health 能力。/api/*:保留旧版搜索、写 memory/resource、LLM summary、文档上传到 Obsidian/OpenViking 的兼容接口。/mcp/rpc与/mcp/sse:提供 MCP 调用入口。
架构
flowchart LR
Agent[Agent / Hermes / MCP Client] --> Gateway[Memory Gateway]
Gateway --> SQLite[(SQLite metadata)]
Gateway --> OpenViking[OpenViking API]
Gateway --> EverOS[EverOS / EverCore API]
Gateway --> Obsidian[Obsidian Markdown Vault]
Gateway --> LLM[OpenAI-compatible LLM]
SQLite --> Refs[memory_refs / outbox_events / commit_jobs]
OpenViking --> OVStore[(session / resource / context index)]
EverOS --> EverStore[(memory / profile / long-term store)]
Memory Gateway 不把完整对话正文长期保存到 SQLite。SQLite 主要保存控制面 metadata:用户、episode、audit、memory_refs、commit_jobs、outbox_events。真正的记忆正文和检索上下文在 OpenViking / EverOS 后端中。
项目结构
memory_gateway/
api_v1.py # v1 REST API
api_v2.py # v2 workflow API
server.py # FastAPI + MCP + legacy /api entrypoint
services.py # v1 service
services_v2.py # v2 ingest/retrieve/commit/outbox orchestration
openviking_client.py # OpenViking adapter
everos_client.py # EverOS adapter
repositories.py # in-memory / SQLite metadata repository
schemas.py # v1 schemas
schemas_v2.py # v2 schemas
backend_contracts.py # backend adapter result contracts
backend_normalization.py # backend response normalization
backend_ref_mapping.py # native ref type -> MemoryRefType mapping
obsidian_review.py # Obsidian review draft support
integrations/hermes/memory-gateway/
SKILL.md
scripts/
plugins/memory-gateway-agent/
tests/
config.example.yaml
pyproject.toml
安装
要求 Python 3.10+。
cd /home/tom/memory-gateway
python3 -m venv .venv
source .venv/bin/activate
pip install -U pip
pip install -e ".[dev]"
如果使用 uv:
cd /home/tom/memory-gateway
uv sync --extra dev
依赖服务
OpenViking
参考 /home/tom/OpenViking/CONTRIBUTING.md。当前约定启动方式:
openviking-server --host 127.0.0.1 --port 1933
配置文件:
/home/tom/.openviking/ov.conf
EverOS / EverCore
参考 /home/tom/EverOS/methods/EverCore/docs/installation/SETUP.md。当前约定启动方式:
cd /home/tom/EverOS/methods/EverCore
uv run python src/run.py --port 1995
配置文件:
/home/tom/EverOS/methods/EverCore/.env
配置
复制示例配置:
cd /home/tom/memory-gateway
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: ""
timeout: 30
everos:
enabled: true
mode: "real"
url: "http://127.0.0.1:1995"
api_key: ""
timeout: 30
health_path: "/health"
ingest_path: "/api/v1/memories"
search_path: "/api/v1/memories/search"
flush_path: "/api/v1/memories/flush"
retrieve_method: "keyword"
storage:
backend: "sqlite"
sqlite_path: "/home/tom/memory-gateway/memory_gateway.sqlite3"
也可以用环境变量覆盖后端配置,例如:
export OPENVIKING_URL=http://127.0.0.1:1933
export EVEROS_URL=http://127.0.0.1:1995
export EVEROS_MODE=real
启动
cd /home/tom/memory-gateway
source .venv/bin/activate
python -m memory_gateway.server --config config.yaml
也可以显式指定 host/port:
python -m memory_gateway.server --config config.yaml --host 127.0.0.1 --port 1934
健康检查:
curl http://127.0.0.1:1934/health
curl http://127.0.0.1:1934/v1/everos/health
如果设置了 server.api_key,请求需要带:
-H "X-API-Key: <your-api-key>"
v2 工作流
1. Ingest 一轮对话
curl -s http://127.0.0.1:1934/v2/conversations/ingest \
-H 'Content-Type: application/json' \
-d '{
"workspace_id": "ws_1",
"user_id": "user_a",
"agent_id": "agent_cli",
"session_id": "sess_1",
"turn_id": "turn_1",
"namespace": "workspace/ws_1/user/user_a",
"role": "user",
"content": "Remember that the demo environment uses EverOS and OpenViking.",
"metadata": {"channel": "manual-test"}
}'
结果中的 refs 是本地 memory_refs 控制面引用,通常包括:
- OpenViking
session_archiveref - EverOS
message_memoryref
这些 refs 保存的是 native id/uri、状态、hash、trace 等 metadata,不是完整记忆正文。
2. Retrieve 上下文
curl -s http://127.0.0.1:1934/v2/context/retrieve \
-H 'Content-Type: application/json' \
-d '{
"workspace_id": "ws_1",
"user_id": "user_a",
"agent_id": "agent_cli",
"session_id": "sess_1",
"namespace": "workspace/ws_1/user/user_a",
"query": "EverOS OpenViking demo environment",
"limit": 5,
"metadata": {"trace_id": "trace_manual_1"}
}'
返回结构重点:
items:真实上下文,由 OpenViking / EverOS retrieve 返回后合并,包含text、source_backend、ref_id、score、memory_type。refs:本地已有的memory_refs视图,用于追踪哪些后端引用已保存。metadata.backend_results:每个后端 retrieve 的状态、返回数量和错误信息。
3. Commit 一个 session
curl -s http://127.0.0.1:1934/v2/conversations/sess_1/commit \
-H 'Content-Type: application/json' \
-d '{
"workspace_id": "ws_1",
"user_id": "user_a",
"agent_id": "agent_cli",
"namespace": "workspace/ws_1/user/user_a"
}'
该接口只创建 commit job 和 outbox events,不直接执行长期记忆生成。返回中会有 job_id 和 metadata.gateway_id。
4. Process outbox
curl -s -X POST 'http://127.0.0.1:1934/v2/admin/outbox/process?limit=20'
处理成功后会生成长期 refs:
- OpenViking
session_archiveref:session archive / summary 的 native 引用。 - EverOS
profileref:用户 profile 的 native 引用。 - EverOS
long_term_memoryref:session 提炼出的长期记忆 native 引用。
这些 ref 保存在 SQLite 的 memory_refs 表中。
5. 查看 refs 和 job
curl -s 'http://127.0.0.1:1934/v2/memory/refs?workspace_id=ws_1&user_id=user_a&session_id=sess_1&limit=20'
curl -s http://127.0.0.1:1934/v2/jobs/<job_id>
SQLite 默认路径取决于配置,例如:
/home/tom/memory-gateway/memory_gateway.sqlite3
主要表:
memory_refsoutbox_eventscommit_jobsaudit_logsusers/memories/episodes/profiles
v1 和 legacy API
v1 保留用户隔离、namespace、visibility/ACL、episode、session commit、audit 等基础能力:
POST /v1/users
GET /v1/users/{user_id}
POST /v1/memory/search
POST /v1/memory
GET /v1/memory/{memory_id}
PATCH /v1/memory/{memory_id}
DELETE /v1/memory/{memory_id}
POST /v1/episodes
POST /v1/sessions/{session_id}/commit
GET /v1/users/{user_id}/profile
POST /v1/memory/{memory_id}/feedback
GET /v1/namespaces
GET /v1/audit
GET /v1/everos/health
旧 /api/* 接口仍保留:
POST /api/search
POST /api/memory
POST /api/resource
POST /api/summary
POST /api/knowledge/upload
MCP / Hermes
MCP endpoints:
POST /mcp/rpc
GET /mcp/sse
Hermes skill 位于:
integrations/hermes/memory-gateway/
常用脚本示例:
python integrations/hermes/memory-gateway/scripts/everos_health.py
python integrations/hermes/memory-gateway/scripts/memory_commit_session.py --help
开发与验证
运行测试:
cd /home/tom/memory-gateway
PYTHONPATH=/home/tom/memory-gateway pytest -q
编译检查:
python -m compileall -q memory_gateway tests integrations/hermes/memory-gateway plugins/memory-gateway-agent
Ruff 已在 pyproject.toml 中配置。如果本地环境安装了 ruff:
python -m ruff check .
当前仓库不要求真实 OpenViking / EverOS 服务才能跑单元测试;真实服务流程需要先启动 127.0.0.1:1933 和 127.0.0.1:1995。
设计约束
- SQLite 保存控制面 metadata,不作为长期记忆正文数据库。
refs是后端 native 对象引用,不等于上下文正文。retrieve.items才是运行时上下文内容。commit只创建 job/outbox;长期 refs 由 outbox process 生成。- 默认只绑定本机地址;远程暴露时必须设置 API key、TLS 和网络访问控制。