# 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 调用入口。 ## 架构 ```mermaid 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 后端中。 ## 项目结构 ```text 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+。 ```bash cd /home/tom/memory-gateway python3 -m venv .venv source .venv/bin/activate pip install -U pip pip install -e ".[dev]" ``` 如果使用 `uv`: ```bash cd /home/tom/memory-gateway uv sync --extra dev ``` ## 依赖服务 ### OpenViking 参考 `/home/tom/OpenViking/CONTRIBUTING.md`。当前约定启动方式: ```bash openviking-server --host 127.0.0.1 --port 1933 ``` 配置文件: ```text /home/tom/.openviking/ov.conf ``` ### EverOS / EverCore 参考 `/home/tom/EverOS/methods/EverCore/docs/installation/SETUP.md`。当前约定启动方式: ```bash cd /home/tom/EverOS/methods/EverCore uv run python src/run.py --port 1995 ``` 配置文件: ```text /home/tom/EverOS/methods/EverCore/.env ``` ## 配置 复制示例配置: ```bash cd /home/tom/memory-gateway cp config.example.yaml config.yaml ``` 核心配置示例: ```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" ``` 也可以用环境变量覆盖后端配置,例如: ```bash export OPENVIKING_URL=http://127.0.0.1:1933 export EVEROS_URL=http://127.0.0.1:1995 export EVEROS_MODE=real ``` ## 启动 ```bash cd /home/tom/memory-gateway source .venv/bin/activate python -m memory_gateway.server --config config.yaml ``` 也可以显式指定 host/port: ```bash python -m memory_gateway.server --config config.yaml --host 127.0.0.1 --port 1934 ``` 健康检查: ```bash curl http://127.0.0.1:1934/health curl http://127.0.0.1:1934/v1/everos/health ``` 如果设置了 `server.api_key`,请求需要带: ```bash -H "X-API-Key: " ``` ## v2 工作流 ### 1. Ingest 一轮对话 ```bash 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_archive` ref - EverOS `message_memory` ref 这些 refs 保存的是 native id/uri、状态、hash、trace 等 metadata,不是完整记忆正文。 ### 2. Retrieve 上下文 ```bash 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 ```bash 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 ```bash curl -s -X POST 'http://127.0.0.1:1934/v2/admin/outbox/process?limit=20' ``` 处理成功后会生成长期 refs: - OpenViking `session_archive` ref:session archive / summary 的 native 引用。 - EverOS `profile` ref:用户 profile 的 native 引用。 - EverOS `long_term_memory` ref:session 提炼出的长期记忆 native 引用。 这些 ref 保存在 SQLite 的 `memory_refs` 表中。 ### 5. 查看 refs 和 job ```bash 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/ ``` SQLite 默认路径取决于配置,例如: ```text /home/tom/memory-gateway/memory_gateway.sqlite3 ``` 主要表: - `memory_refs` - `outbox_events` - `commit_jobs` - `audit_logs` - `users` / `memories` / `episodes` / `profiles` ## v1 和 legacy API v1 保留用户隔离、namespace、visibility/ACL、episode、session commit、audit 等基础能力: ```text 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/*` 接口仍保留: ```text POST /api/search POST /api/memory POST /api/resource POST /api/summary POST /api/knowledge/upload ``` ## MCP / Hermes MCP endpoints: ```text POST /mcp/rpc GET /mcp/sse ``` Hermes skill 位于: ```text integrations/hermes/memory-gateway/ ``` 常用脚本示例: ```bash python integrations/hermes/memory-gateway/scripts/everos_health.py python integrations/hermes/memory-gateway/scripts/memory_commit_session.py --help ``` ## 开发与验证 运行测试: ```bash cd /home/tom/memory-gateway PYTHONPATH=/home/tom/memory-gateway pytest -q ``` 编译检查: ```bash python -m compileall -q memory_gateway tests integrations/hermes/memory-gateway plugins/memory-gateway-agent ``` Ruff 已在 `pyproject.toml` 中配置。如果本地环境安装了 ruff: ```bash 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 和网络访问控制。