---
name: memory-system-api
description: "Use when an AI agent needs to operate this repository's Memory System API, including creating users, writing session messages, committing or extracting memory, managing memory URIs, searching memories, reading profiles, or debugging OpenViking/EverOS backend results."
---

# Memory System API

This skill is for using the Memory Gateway service in this repo. Prefer it over direct OpenViking or EverOS calls unless the user explicitly asks to debug a backend.

## Current Contract

The API is user-gated:

- Create a user first with `POST /memory-system/users`.
- Save the returned `account.result.user_key`.
- Send that value back as `user_key` on business API calls.
- Do not send `account_id` on business APIs.

Do not assume business APIs will auto-create users. Non-user-creation endpoints fail when the user was not created first or when the supplied `user_key` does not match the stored key.

`X-API-Key` is separate. It protects the Memory System API itself only when `server.api_key` is configured.

## Identity Model

- `user_id`: end user.
- `user_key`: OpenViking key returned when the user is created.
- `session_id`: conversation ID and OpenViking session ID.

Internally the gateway creates one isolated OpenViking account per business user:

```json
{"account_id": "<user_id>_account", "admin_user_id": "<user_id>"}
```

The gateway does not call `/api/v1/admin/accounts/admin/users`. User creation goes through `/api/v1/admin/accounts`, stores the returned `user_key`, and later business calls use that user key directly.

The SQLite store is the source of truth for:

- `user_id -> user_key`
- `user_id + session_id`
- `task_id`
- `archive_uri`

Session memory is retrieved under OpenViking using the explicit user/session URI paths:

```text
viking://user/memories
viking://user/memories/...
viking://user/<session_id>
```

## Endpoints

Base path: `/memory-system`

| Method | Path | Purpose | Requires `user_key` |
|---|---|---|---|
| `GET` | `/health` | Check OpenViking and EverOS health | No |
| `POST` | `/users` | Create OpenViking user and store user key | No |
| `POST` | `/messages` | Write user/assistant messages to backends | Yes |
| `POST` | `/sessions/{session_id}/commit` | Commit OpenViking session and flush EverOS | Yes |
| `POST` | `/sessions/{session_id}/extract` | Trigger OpenViking extract only | Yes |
| `GET/POST` | `/sessions/{session_id}/context` | Read OpenViking session context plus EverOS recall | Yes |
| `GET` | `/openviking/tasks/{task_id}` | Poll OpenViking task status | Yes |
| `GET` | `/memories` | List OpenViking memory URIs under a memory root | Yes |
| `GET` | `/memories/content` | Read one OpenViking memory URI | Yes |
| `POST` | `/memories` | Create, replace, or append an OpenViking memory via `content/write` | Yes |
| `DELETE` | `/memories` | Delete an OpenViking memory URI via `fs` | Yes |
| `POST` | `/resources` | Upload local file or remote URL to OpenViking resources | Yes |
| `DELETE` | `/resources` | Delete OpenViking resource URI via `fs` | Yes |
| `POST` | `/search` | Search OpenViking and EverOS | Yes |
| `GET` | `/users/{user_id}/profile` | Read EverOS profile | Yes |

## Required Inputs

For business APIs:

```text
user_id: <user id from /users>
user_key: <account.result.user_key from /users>
```

If configured:

```text
X-API-Key: <server.api_key>
```

Never place OpenViking root keys in user-facing examples unless the user is explicitly configuring the server. Never ask callers to send `X-Account-Key`; that contract is obsolete.

## Examples

Create user:

```bash
curl -sS -X POST "$BASE/memory-system/users" \
  -H "Content-Type: application/json" \
  -d '{"user_id":"userA"}'
```

Write messages:

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

Commit:

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

Search:

```bash
curl -sS -X POST "$BASE/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
  }'
```

Session context:

```bash
curl -sS -X POST "$BASE/memory-system/sessions/sessionA1/context" \
  -H "Content-Type: application/json" \
  -d '{
    "user_id": "userA",
    "user_key": "'"$USER_KEY"'",
    "query": "我喜欢喝什么？",
    "limit": 10
  }'
```

GET with query parameters is also supported:

```bash
curl -sS "$BASE/memory-system/sessions/sessionA1/context?user_id=userA&user_key=$USER_KEY&query=我喜欢喝什么？&limit=10"
```

List memories:

```bash
curl -sS -G "$BASE/memory-system/memories" \
  --data-urlencode "user_id=userA" \
  --data-urlencode "user_key=$USER_KEY" \
  --data-urlencode "uri=viking://user/memories" \
  --data-urlencode "recursive=true"
```

Read memory:

```bash
curl -sS -G "$BASE/memory-system/memories/content" \
  --data-urlencode "user_id=userA" \
  --data-urlencode "user_key=$USER_KEY" \
  --data-urlencode "uri=viking://user/memories/preferences/python.md"
```

Create, replace, or append memory:

```bash
curl -sS -X POST "$BASE/memory-system/memories" \
  -H "Content-Type: application/json" \
  -d '{
    "user_id": "userA",
    "user_key": "'"$USER_KEY"'",
    "uri": "viking://user/memories/preferences/python.md",
    "content": "# Python 偏好\n\n用户偏好使用 Python 做数据分析。",
    "mode": "replace",
    "wait": true
  }'
```

Delete memory:

```bash
curl -sS -X DELETE -G "$BASE/memory-system/memories" \
  --data-urlencode "user_id=userA" \
  --data-urlencode "user_key=$USER_KEY" \
  --data-urlencode "uri=viking://user/memories/preferences/python.md" \
  --data-urlencode "recursive=false"
```

For directory-like or composite memories, retry deletion with `recursive=true` only after OpenViking reports that recursive deletion is required.

## Response Handling

Top-level `status` is one of:

- `success`: all attempted backends succeeded.
- `partial_success`: at least one backend succeeded and one failed.
- `failed`: all attempted backends failed.

Search responses include merged `items` and compact backend diagnostics under `backends`. Keep `source_backend` when using results. Fields named `vector` are stripped from returned payloads, and the raw EverOS `original_data` blob is not returned by search anymore.

Session context responses include OpenViking context under `context`, EverOS recall under `items`, and compact backend diagnostics under `backends`.

## Common Mistakes

- Calling `/messages` before `/users`.
- Omitting `user_key` on business calls.
- Sending `account_id` to business APIs.
- Confusing `X-API-Key` with `user_key`.
- Assuming memory updates use a PATCH endpoint; use `POST /memory-system/memories` with `mode=replace` or `mode=append`.
- Deleting memories recursively by default; use `recursive=false` unless the target is a directory or composite resource.
- Expecting `backends.everos.result` to still contain full `episodes` or `original_data`.
- Assuming the gateway stores these values only in memory; it persists them in SQLite.

## Validation

After changing API behavior or this skill:

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