Files
memory-gateway/README.md

16 KiB
Raw Blame History

Memory Gateway

Memory Gateway 是一个通用记忆网关,用于给 AI agent / harness 提供统一的记忆检索、文档上传、LLM 总结和知识沉淀能力。

它的定位不是某个单一业务场景的垂直应用,而是一个可复用的本地 memory/context gateway上层 agent 通过 REST、MCP 或 Hermes skill 调用它,底层由 OpenViking 承载 memory/resource由 Obsidian 承载人工可维护的 Markdown 知识。

当前能力

  • 搜索 OpenViking memory / resource。
  • 写入普通 memory。
  • 写入结构化 resource。
  • 对任意文本调用 LLM 总结,并按需沉淀到 OpenViking。
  • 上传文档,使用 MarkItDown 转 Markdown。
  • 将上传文档保存到 Obsidian vault。
  • 将文档摘要和结构化 artifact 写入 OpenViking knowledge。
  • 给 Hermes 提供通用 memory-gateway skill。
  • 新增通用 Memory Gateway v1 方案与 POC 骨架多用户、namespace、visibility/ACL、episode、session commit、audit、skills 分层。
  • v1 metadata 默认持久化到 SQLite覆盖 users、memories、episodes、profiles、audit。
  • /v1/memory/search 先做本地 ACL 过滤,再按可见 namespace 查询 OpenViking。
  • v1 MCP tools 已接入现有 /mcp/rpc
  • /v1/sessions/{session_id}/commit 优先调用独立 EverMemOS HTTP 服务;服务不可用且允许 fallback 时,才使用 Gateway 进程内 POC worker。

完整方案见:

docs/generic-memory-gateway-design.md

架构

Agent / Harness / CLI
  -> Memory Gateway REST / MCP
  -> OpenViking memory / resource
  -> Obsidian markdown vault
  -> OpenAI-compatible LLM summary

目录结构

memory-gateway/
├── memory_gateway/                 # Gateway 服务代码
│   ├── server.py                    # REST / MCP 接口
│   ├── openviking_client.py         # OpenViking client
│   ├── llm.py                       # OpenAI-compatible LLM summary
│   ├── document_ingest.py           # MarkItDown + Obsidian write helpers
│   ├── config.py
│   └── types.py
├── integrations/hermes/
│   └── memory-gateway/              # 通用 Hermes skill
├── obsidian-vault/
│   ├── 01_Knowledge/Uploaded/       # 上传文档转成的 Markdown
│   └── 05_Templates/                # 通用知识模板
├── tests/
├── config.example.yaml
└── pyproject.toml

环境

使用当前虚拟环境:

cd /home/tom/memory-gateway
source /home/tom/OpenViking/.venv/bin/activate

本地配置文件:

/home/tom/memory-gateway/config.yaml

关键配置:

memory:
  default_namespace: memory-gateway

llm:
  base_url: https://oai.bwgdi.com/v1
  api_key: <local secret, git ignored>
  model: MiniMaxAI

obsidian:
  vault_path: /home/tom/memory-gateway/obsidian-vault
  knowledge_dir: 01_Knowledge/Uploaded
  review_dir: Reviews/Queue

storage:
  backend: sqlite
  sqlite_path: /home/tom/memory-gateway/memory_gateway.sqlite3

config.yaml 已被 .gitignore 忽略,不会提交密钥。

启动

OpenViking 需要先运行在 127.0.0.1:1933

source /home/tom/OpenViking/.venv/bin/activate
openviking-server --host 127.0.0.1 --port 1933

启动本机 EverMemOS 服务:

cd /home/tom/memory-gateway
source /home/tom/OpenViking/.venv/bin/activate
python -m memory_gateway.evermemos_service \
  --config /home/tom/memory-gateway/config.yaml \
  --host 127.0.0.1 \
  --port 1995

启动 Memory Gateway

cd /home/tom/memory-gateway
source /home/tom/OpenViking/.venv/bin/activate
python -m memory_gateway.server --config /home/tom/memory-gateway/config.yaml

健康检查:

curl http://127.0.0.1:1934/health
curl http://127.0.0.1:1995/health
curl http://127.0.0.1:1934/v1/evermemos/health

REST 接口

GET /health

检查 Gateway 和 OpenViking 状态。

POST /api/search

搜索 OpenViking memory / resource。

curl -X POST http://127.0.0.1:1934/api/search \
  -H "Content-Type: application/json" \
  -d '{
    "query": "memory gateway document upload summary",
    "uri": "viking://resources",
    "limit": 5
  }'

POST /api/memory

写入普通 memory。

curl -X POST http://127.0.0.1:1934/api/memory \
  -H "Content-Type: application/json" \
  -d '{
    "namespace": "memory-gateway",
    "memory_type": "preference",
    "content": "The user prefers concise technical summaries."
  }'

POST /api/resource

写入结构化 resource。

curl -X POST http://127.0.0.1:1934/api/resource \
  -H "Content-Type: application/json" \
  -d '{
    "uri": "viking://resources/memory-gateway/knowledge/example.json",
    "resource_type": "json",
    "content": "{\"title\":\"example\"}"
  }'

POST /api/summary

调用 LLM 总结任意文本,并按需沉淀到 OpenViking。

curl -X POST http://127.0.0.1:1934/api/summary \
  -H "Content-Type: application/json" \
  -d '{
    "title": "Project decision summary",
    "content": "需要总结和沉淀的内容...",
    "namespace": "memory-gateway",
    "memory_type": "decision",
    "tags": ["project", "decision"],
    "persist_as": "resource"
  }'

persist_as 支持:nonememoryresourceboth

POST /api/knowledge/upload

上传文档MarkItDown 转 Markdown保存到 ObsidianLLM 总结后写入 OpenViking knowledge。

curl -X POST http://127.0.0.1:1934/api/knowledge/upload \
  -F "file=@/path/to/document.pdf" \
  -F "title=Design Notes" \
  -F "namespace=memory-gateway" \
  -F "knowledge_type=design_doc" \
  -F "tags=project,design,reference" \
  -F "persist_as=resource"

默认保存到:

obsidian-vault/01_Knowledge/Uploaded/

v1 通用 Memory API

v1 API 面向多 agent 框架,带 user / agent / workspace / session 上下文和基础 ACL。

创建用户

curl -X POST http://127.0.0.1:1934/v1/users \
  -H "Content-Type: application/json" \
  -d '{"user_id":"user_tom","display_name":"Tom","preferences":{"language":"zh-CN"}}'

写入记忆

curl -X POST http://127.0.0.1:1934/v1/memory \
  -H "Content-Type: application/json" \
  -d '{
    "user_id": "user_tom",
    "agent_id": "agent_hermes",
    "workspace_id": "ws_memory_gateway",
    "memory_type": "preference",
    "content": "用户偏好中文输出,结构化但不要过度工程化。",
    "summary": "中文、结构化、轻量 POC 优先。",
    "tags": ["preference", "style"],
    "importance": 0.8,
    "confidence": 0.9,
    "visibility": "private",
    "source": "manual"
  }'

检索记忆

curl -X POST http://127.0.0.1:1934/v1/memory/search \
  -H "Content-Type: application/json" \
  -d '{
    "user_id": "user_tom",
    "agent_id": "agent_hermes",
    "workspace_id": "ws_memory_gateway",
    "query": "中文输出",
    "limit": 5
  }'

返回会包含:

  • local_totalSQLite metadata 命中的记忆数量。
  • openviking_total:按可见 namespace 查询 OpenViking 的命中数量。
  • searched_namespacesGateway 展开并允许查询的 namespace。

修改记忆

curl -X PATCH "http://127.0.0.1:1934/v1/memory/MEMORY_ID?user_id=user_tom&agent_id=agent_hermes&workspace_id=ws_memory_gateway" \
  -H "Content-Type: application/json" \
  -d '{"summary":"用户偏好中文、结构化、少废话。","importance":0.9}'

写入 episode 并 commit session

curl -X POST http://127.0.0.1:1934/v1/episodes \
  -H "Content-Type: application/json" \
  -d '{
    "user_id": "user_tom",
    "agent_id": "agent_hermes",
    "workspace_id": "ws_memory_gateway",
    "session_id": "sess_demo",
    "content": "结论:这个项目必须保留用户隔离和 namespace ACL。",
    "tags": ["decision"]
  }'

curl -X POST http://127.0.0.1:1934/v1/sessions/sess_demo/commit \
  -H "Content-Type: application/json" \
  -d '{
    "user_id": "user_tom",
    "agent_id": "agent_hermes",
    "workspace_id": "ws_memory_gateway",
    "session_id": "sess_demo",
    "promote": true,
    "min_importance": 0.6
  }'

流程说明:

  • 短期记忆先写入 SQLite 的 episodesnamespace 通常是 session/{session_id}/episodic
  • commit session 时Gateway 把当前 session episodes、可见长期记忆和访问上下文发给 http://127.0.0.1:1995/v1/sessions/consolidate
  • EverMemOS 返回候选记忆、可直接提升的长期记忆、重复/冲突信息和 review draft 路径。
  • Gateway 只把正常稳定候选写入长期 memory高价值或冲突候选不会直接进入长期记忆会写入
obsidian-vault/Reviews/Queue/

MCP Tools

POST /mcp/rpc 支持:

  • search
  • add_memory
  • add_resource
  • commit_summary
  • get_status
  • list_memories
  • list_resources
  • memory_search
  • memory_upsert
  • memory_append_episode
  • memory_commit_session
  • memory_get_profile
  • memory_list_namespaces
  • memory_delete
  • memory_feedback

Hermes Skill

通用 Hermes skill

/home/tom/.hermes/skills/memory-gateway/

仓库副本:

integrations/hermes/memory-gateway/

安装或更新到本机 Hermes skill 目录:

mkdir -p /home/tom/.hermes/skills/memory-gateway
rsync -a --delete \
  /home/tom/memory-gateway/integrations/hermes/memory-gateway/ \
  /home/tom/.hermes/skills/memory-gateway/

使用方式:

  • Hermes 对话中可以加载 memory-gateway skill让 agent 按 skill 文档主动调用脚本。
  • skill 不等于自动记忆;只有 agent 根据 skill/policy 主动调用脚本时才会写入或检索记忆。
  • 适合人工可控的显式操作:创建用户、检索记忆、追加 episode、commit session、上传知识和检查 EverMemOS。

主要脚本:

scripts/evermemos_health.py
scripts/memory_create_user.py
scripts/memory_append_episode.py
scripts/memory_commit_session.py
scripts/memory_search.py
scripts/memory_upsert.py
scripts/retrieve_memory.py
scripts/commit_summary.py
scripts/upload_knowledge.py
scripts/search_obsidian.py

检查 EverMemOS

python /home/tom/.hermes/skills/memory-gateway/scripts/evermemos_health.py

检索记忆:

python /home/tom/.hermes/skills/memory-gateway/scripts/retrieve_memory.py \
  --query "document upload summary memory gateway" \
  --uri viking://resources \
  --limit 5

总结沉淀:

python /home/tom/.hermes/skills/memory-gateway/scripts/commit_summary.py \
  --title "Reusable conclusion" \
  --namespace memory-gateway \
  --memory-type decision \
  --tag project \
  --persist-as resource \
  --text "最终结论或可复用知识..."

上传知识:

python /home/tom/.hermes/skills/memory-gateway/scripts/upload_knowledge.py \
  --file /path/to/document.md \
  --title "Knowledge note" \
  --namespace memory-gateway \
  --knowledge-type reference \
  --tags project,reference \
  --persist-as resource

完整长短期记忆测试:

python /home/tom/.hermes/skills/memory-gateway/scripts/memory_create_user.py \
  --user-id user_tom \
  --display-name "Tom" \
  --preference language=zh-CN

python /home/tom/.hermes/skills/memory-gateway/scripts/memory_append_episode.py \
  --user-id user_tom \
  --agent-id agent_hermes \
  --workspace-id ws_memory_gateway \
  --session-id sess_demo \
  --tag decision \
  --text "结论:本机 EverMemOS 服务负责从 session episode 中整理稳定长期记忆。"

python /home/tom/.hermes/skills/memory-gateway/scripts/memory_append_episode.py \
  --user-id user_tom \
  --agent-id agent_hermes \
  --workspace-id ws_memory_gateway \
  --session-id sess_demo \
  --tag review \
  --tag high-value \
  --text "重要:高价值记忆应该进入 Obsidian review queue避免错误记忆污染长期系统。"

python /home/tom/.hermes/skills/memory-gateway/scripts/memory_commit_session.py \
  --user-id user_tom \
  --agent-id agent_hermes \
  --workspace-id ws_memory_gateway \
  --session-id sess_demo \
  --min-importance 0.6

python /home/tom/.hermes/skills/memory-gateway/scripts/memory_search.py \
  --user-id user_tom \
  --agent-id agent_hermes \
  --workspace-id ws_memory_gateway \
  --session-id sess_demo \
  --query "EverMemOS 服务负责" \
  --limit 5

Hermes / OpenClaw Agent Plugin

通用 Agent plugin 位于:

plugins/memory-gateway-agent/

它是独立 adapter不 import Gateway 内部 services/repositories/server,所有调用都通过现有 /v1 HTTP API。它面向 Hermes/OpenClaw 这类 agent runtime 暴露统一工具:

  • memory_search
  • memory_append_episode
  • memory_commit_session
  • memory_upsert
  • memory_feedback

Hermes 本机安装:

mkdir -p /home/tom/.hermes/plugins
ln -s /home/tom/memory-gateway/plugins/memory-gateway-agent \
  /home/tom/.hermes/plugins/memory-gateway-agent
hermes plugins enable memory-gateway-agent
hermes plugins list
hermes tools list

如果软链接已存在,先确认它指向当前仓库:

ls -l /home/tom/.hermes/plugins/memory-gateway-agent

运行配置:

export MEMORY_GATEWAY_URL=http://127.0.0.1:1934
export MEMORY_GATEWAY_API_KEY=
export MEMORY_GATEWAY_DEFAULT_USER_ID=test_user_memory_gateway_plugin
export MEMORY_GATEWAY_DEFAULT_AGENT_ID=test_hermes_memory_gateway_plugin
export MEMORY_GATEWAY_DEFAULT_WORKSPACE_ID=test_workspace_memory_gateway_plugin
export MEMORY_GATEWAY_AUTO_SEARCH=true
export MEMORY_GATEWAY_AUTO_APPEND_EPISODE=true
export MEMORY_GATEWAY_AUTO_COMMIT_SESSION=false

Hermes plugin 已验证:

  • hermes plugins list 可发现并启用 memory-gateway-agent
  • hermes tools list 可看到 memory_gateway toolset。
  • pre_llm_call 会自动检索 Memory Gateway。
  • post_llm_call 会按 policy 写入摘要型 candidate episode。
  • on_session_end 默认不会 commit只有 MEMORY_GATEWAY_AUTO_COMMIT_SESSION=true 才会 commit。

真实 Hermes chat 验证:

PYTHONPATH=/home/tom/memory-gateway/plugins/memory-gateway-agent \
python /home/tom/memory-gateway/plugins/memory-gateway-agent/scripts/hermes_interactive_session_check.py

插件 E2E 验证:

PYTHONPATH=/home/tom/memory-gateway/plugins/memory-gateway-agent \
python /home/tom/memory-gateway/plugins/memory-gateway-agent/scripts/gateway_e2e_check.py

PYTHONPATH=/home/tom/memory-gateway/plugins/memory-gateway-agent \
python /home/tom/memory-gateway/plugins/memory-gateway-agent/scripts/hermes_hook_probe.py

清理测试数据:

PYTHONPATH=/home/tom/memory-gateway/plugins/memory-gateway-agent \
python /home/tom/memory-gateway/plugins/memory-gateway-agent/scripts/cleanup_test_memories.py

安全边界:

  • plugin 不保存完整原始对话,只写摘要型 episode。
  • 默认拒绝 password、token、API key、cookie、private key、完整 transcript 和大段日志。
  • memory_upsert 是高风险长期记忆写入,不会自动触发。
  • 用户要求 forget/delete 时,应走 memory_feedback 或 delete 能力。
  • hook trace 默认关闭;需要排查时设置 MEMORY_GATEWAY_PLUGIN_TRACE_HOOKS=true,只会写入 hook 名称、短 session id、Gateway action 和状态到 plugins/memory-gateway-agent/.tmp/hook_trace.log

OpenClaw manifest 目前是 best-effort 草案:

plugins/memory-gateway-agent/openclaw.plugin.yaml

需要等 OpenClaw runtime 可用后再做第五阶段实测。

测试

cd /home/tom/memory-gateway
source /home/tom/OpenViking/.venv/bin/activate
PYTHONPATH=/home/tom/memory-gateway pytest -q

PYTHONPATH=/home/tom/memory-gateway/plugins/memory-gateway-agent \
  pytest -q plugins/memory-gateway-agent/tests

当前测试覆盖:

  • API key 校验。
  • MCP tools/list。
  • OpenViking search 透传。
  • LLM summary artifact 构建。
  • document upload -> markdown -> Obsidian -> OpenViking resource。

下一步

  • 在 Gateway 层加强 /api/search 的 URI prefix 过滤和去重。
  • /api/knowledge/upload 增加文件大小限制、类型白名单和 dry-run。
  • 增加 Obsidian -> OpenViking 增量同步脚本。
  • 给 Memory Gateway skill 增加更稳定的“回答时引用 memory/resource/Obsidian note”输出约束。
  • 增加更多文档解析格式和异常处理测试。