# Memory System API Reference

Use the deployed service URL supplied by the user, runtime, or configuration:

```text
<MEMORY_SYSTEM_BASE_URL>
```

Do not assume a localhost address. In agent workflows, resolve the endpoint from `MEMORY_SYSTEM_ENDPOINT`, Hermes memory config, platform config, or user input.

If an API key is configured, add:

```bash
-H "X-API-Key: <gateway-api-key>"
```

## Health

```bash
curl -s <MEMORY_SYSTEM_BASE_URL>/memory-system/health
```

## Create User

Create the business user before calling any business endpoint:

```bash
curl -s -X POST <MEMORY_SYSTEM_BASE_URL>/memory-system/users \
  -H "Content-Type: application/json" \
  -d '{"user_id": "<USER_ID>"}'
```

Save the returned `account.result.user_key` and pass it as `user_key` on later calls:

```json
{
  "status": "success",
  "account": {
    "status": "ok",
    "result": {
      "account_id": "<USER_ID>_account",
      "admin_user_id": "<USER_ID>",
      "user_key": "<USER_KEY>"
    }
  }
}
```

Do not send `account_id` to business endpoints.

## Write Messages

```bash
curl -s -X POST <MEMORY_SYSTEM_BASE_URL>/memory-system/messages \
  -H "Content-Type: application/json" \
  -d '{
    "user_id": "<USER_ID>",
    "user_key": "<USER_KEY>",
    "session_id": "<SESSION_ID>",
    "user_message": "我喜欢喝拿铁，不喜欢美式。",
    "assistant_message": "好的，我会记住你的咖啡偏好。"
  }'
```

`user_message` and `assistant_message` are optional independently, but at least one must be present.

## Commit Session

```bash
curl -s -X POST <MEMORY_SYSTEM_BASE_URL>/memory-system/sessions/<SESSION_ID>/commit \
  -H "Content-Type: application/json" \
  -d '{"user_id": "<USER_ID>", "user_key": "<USER_KEY>"}'
```

Use the returned OpenViking task ID, if present:

```bash
curl -s "<MEMORY_SYSTEM_BASE_URL>/memory-system/openviking/tasks/<TASK_ID>?user_id=<USER_ID>&user_key=<USER_KEY>&session_id=<SESSION_ID>"
```

`commit` can return `partial_success` if OpenViking accepted the archive but EverOS flush failed or timed out. This is retryable:

```json
{
  "status": "partial_success",
  "backends": {
    "openviking": {"status": "success", "result": {"status": "ok"}},
    "everos": {"status": "failed", "error": "ReadTimeout"}
  }
}
```

Wait for EverOS or its upstream LLM/rerank service to recover, then call the same commit endpoint again.

## Immediate Extract

```bash
curl -s -X POST <MEMORY_SYSTEM_BASE_URL>/memory-system/sessions/<SESSION_ID>/extract \
  -H "Content-Type: application/json" \
  -d '{"user_id": "<USER_ID>", "user_key": "<USER_KEY>"}'
```

## Session Context

Use this when the caller needs the OpenViking working-memory context for one session plus related EverOS recall for the same user/session.

```bash
curl -s -X POST <MEMORY_SYSTEM_BASE_URL>/memory-system/sessions/<SESSION_ID>/context \
  -H "Content-Type: application/json" \
  -d '{
    "user_id": "<USER_ID>",
    "user_key": "<USER_KEY>",
    "query": "我喜欢喝什么？",
    "limit": 10
  }'
```

Equivalent GET form:

```bash
curl -s "<MEMORY_SYSTEM_BASE_URL>/memory-system/sessions/<SESSION_ID>/context?user_id=<USER_ID>&user_key=<USER_KEY>&query=我喜欢喝什么？&limit=10"
```

Response shape:

```json
{
  "status": "success",
  "context": {
    "latest_archive_overview": "# Working Memory\n...",
    "pre_archive_abstracts": [],
    "messages": [],
    "estimatedTokens": 342,
    "stats": {"totalArchives": 3}
  },
  "items": [
    {
      "source_backend": "everos",
      "memory_type": "episode",
      "id": "episode-1",
      "summary": "userB 在对话中表示自己喜欢拿铁。",
      "score": 0.72
    }
  ],
  "backends": {
    "openviking": {
      "status": "success",
      "result": {
        "status": "ok",
        "estimatedTokens": 342,
        "has_latest_archive_overview": true,
        "message_count": 0
      }
    },
    "everos": {
      "status": "success",
      "result": {
        "counts": {"episodes": 1, "profiles": 0, "raw_messages": 0}
      }
    }
  }
}
```

## Manage Memories

Memory management operates on OpenViking memory URIs, usually under `viking://user/memories`. There is no separate PATCH endpoint. Update existing memory by writing directly to its URI.

### List Memory URIs

```bash
curl -sS --get "<MEMORY_SYSTEM_BASE_URL>/memory-system/memories" \
  --data-urlencode "user_id=<USER_ID>" \
  --data-urlencode "user_key=<USER_KEY>" \
  --data-urlencode "uri=viking://user/memories" \
  --data-urlencode "recursive=true"
```

This maps to OpenViking `GET /api/v1/fs/ls`.

### Read Memory Content

```bash
curl -sS --get "<MEMORY_SYSTEM_BASE_URL>/memory-system/memories/content" \
  --data-urlencode "user_id=<USER_ID>" \
  --data-urlencode "user_key=<USER_KEY>" \
  --data-urlencode "uri=viking://user/memories/preferences/python.md"
```

This maps to OpenViking `GET /api/v1/content/read`.

### Create, Replace, Or Append Memory

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

`mode` supports:

- `create`: create a new memory URI.
- `replace`: fully replace an existing memory.
- `append`: append content to an existing memory.

This maps to OpenViking `POST /api/v1/content/write`. OpenViking refreshes semantic and vector indexes after writing.

### Delete Memory

```bash
curl -sS -X DELETE --get "<MEMORY_SYSTEM_BASE_URL>/memory-system/memories" \
  --data-urlencode "user_id=<USER_ID>" \
  --data-urlencode "user_key=<USER_KEY>" \
  --data-urlencode "uri=viking://user/memories/preferences/python.md" \
  --data-urlencode "recursive=false"
```

Default to `recursive=false`. If OpenViking reports that the URI is a directory or composite resource, retry with `recursive=true`.

## Search

Without LLM planning:

```bash
curl -s -X POST <MEMORY_SYSTEM_BASE_URL>/memory-system/search \
  -H "Content-Type: application/json" \
  -d '{
    "user_id": "<USER_ID>",
    "user_key": "<USER_KEY>",
    "session_id": "<SESSION_ID>",
    "query": "我喜欢喝什么咖啡？",
    "use_llm": false,
    "limit": 10,
    "level": 2,
    "score_threshold": 0.8,
    "target_uri": "viking://user/memories"
  }'
```

With LLM planning:

```bash
curl -s -X POST <MEMORY_SYSTEM_BASE_URL>/memory-system/search \
  -H "Content-Type: application/json" \
  -d '{
    "user_id": "<USER_ID>",
    "user_key": "<USER_KEY>",
    "session_id": "<SESSION_ID>",
    "query": "我的偏好是什么？",
    "use_llm": true,
    "limit": 10,
    "level": 2,
    "score_threshold": 0.8,
    "target_uri": "viking://user/memories"
  }'
```

Raw API search responses include merged `items` plus compact backend diagnostics. Fields named `vector` are stripped recursively before the API returns JSON. The API does not return EverOS `original_data` or full episode payloads inside `backends` anymore. OpenViking search uses `/api/v1/search/search`; `target_uri`, `level`, and `score_threshold` are optional request fields.

The search response shape should now look more like:

```json
{
  "status": "success",
  "items": [
    {
      "source_backend": "everos",
      "memory_type": "episode",
      "id": "episode-1",
      "user_id": "userB",
      "session_id": "sessionB1",
      "timestamp": "2026-05-22T07:50:51.750000Z",
      "summary": "userB 在对话中表示自己喜欢拿铁。",
      "score": 0.72
    }
  ],
  "backends": {
    "everos": {
      "status": "success",
      "result": {
        "counts": {"episodes": 1, "profiles": 0, "raw_messages": 0},
        "query": {"text": "我喜欢喝什么？", "method": "agentic"}
      }
    }
  }
}
```

When the API is used through the Hermes `memory_system` provider, the tool result is intentionally compact and should look like:

```json
{
  "status": "success",
  "items": [
    {
      "source_backend": "openviking",
      "memory_type": "event",
      "score": 0.92,
      "text": "Relevant recalled memory text",
      "uri": "viking://..."
    }
  ]
}
```

Use the compact `text` fields for answering. Only inspect raw `backends` when debugging API/backend failures.

## Profile

```bash
curl -sS --get "<MEMORY_SYSTEM_BASE_URL>/memory-system/users/<USER_ID>/profile" \
  --data-urlencode "user_key=<USER_KEY>" \
  --data-urlencode "query=我想喝东西" \
  --data-urlencode "limit=10" \
  --data-urlencode "level=2"
```

This combines EverOS profile with OpenViking memory recall. The OpenViking request uses `/api/v1/search/search` with `target_uri: viking://user/memories`, `limit`, and `level`.

## Response Interpretation

Inspect backend status:

```json
{
  "status": "partial_success",
  "backends": {
    "openviking": {"status": "success", "result": {}},
    "everos": {"status": "failed", "error": "..."}
  }
}
```

Use backend-specific errors for debugging.

OpenViking user keys are intentionally hidden from other users, but the caller must present the matching `user_key` for business APIs. The gateway stores the created `user_id/user_key`, `session_id`, `task_id`, and `archive_uri` in SQLite.
