# es-memory

Part of **ES**

# Elasticsearch Memory Management

## Capabilities Overview

| Sub-capability | Calling Mode | Description |
|----------------|--------------|-------------|
| Manage Memory | Synchronous | Perform CRUD operations on agentic memory entries and associated skills. |

## API Calling Patterns

### Authentication
Use **Bearer Token** authentication as the primary method.

- Include the header: `Authorization: Bearer <your_api_key>`
- Store your credential in the environment variable: `ES_MEMORY_API_KEY`
- While other methods may exist, Bearer Token is the standard for all documented endpoints.

### Service Endpoint
The base URL follows this pattern:

`http://{workspace_id}.opensearch.{region}.aliyuncs.com`

Common regions include:
- `cn-hangzhou`
- `cn-shanghai`
- `cn-beijing`

The full API path is: `{base_url}/v3/openapi/workspaces/{workspace_name}/memory/agentic-memory/...`

### Synchronous Operations with Asynchronous Task Handling
Although the API uses synchronous HTTP calls, memory and skill creation trigger **asynchronous tasks**. The workflow is:

1. **Submit** a POST request to create memory or upload a skill → receive a `task_id` in the response.
2. **Poll** the task endpoint (`/tasks/{task_id}`) until the task completes.
3. **Use** the resulting `memory_id` (prefixed with `m-`) or `skill_id` (prefixed with `s-`) for subsequent operations.

All other operations (GET, PUT, DELETE on existing IDs) are fully synchronous and return results immediately.

Key headers:
- `Content-Type: application/json` for POST/PUT requests
- `Authorization: Bearer <API_KEY>` on every request

## Parameter Reference

### Manage Memory

| Parameter | Type | Required | Default | Constraints | Description |
|----------|------|----------|---------|-------------|-------------|
| host | String | Yes | — | — | The service endpoint (e.g., `http://xxxx-hangzhou.opensearch.aliyuncs.com`) |
| workspace_name | String | Yes | — | — | The workspace name (e.g., `default`) |
| service_id | String | Yes | — | — | Always `agentic-memory` |
| messages | String / Object / Array | Yes | — | — | Message content: string (simple), object (single message), or array (multi-turn) |
| user_id | String | Yes | — | — | Unique identifier for the user |
| agent_id | String | No | — | — | If provided, extracts assistant attributes instead of user attributes |
| run_id | String | No | — | — | The run ID |
| enhancements | Object | No | — | — | Enables optional features like skill extraction |
| enhancements.skill.enable | Boolean | No | false | — | Enable skill extraction from multi-turn conversations |
| query | String | Yes | — | — | Search query for memory/skill retrieval |
| size | Int | No | 10 | — | Max number of results to return |
| zip_base64 | String | Yes | — | — | Base64-encoded ZIP file content for skill upload |
| memory | String | Yes | — | — | Updated memory content (for PUT) |
| description | String | No | — | — | Skill description |
| tags | Array | No | — | — | List of skill tags |
| version | String | No | — | — | Skill version |
| files | Object | No | — | — | Skill file content (from GET skill response) |
| name | String | No | — | — | Skill name |
| task_id | String | Yes | — | — | Asynchronous task ID (from initial POST) |
| memory_id | String | Yes | — | Must start with `m-` | Unique memory identifier |
| skill_id | String | Yes | — | Must start with `s-` | Unique skill identifier |

## Code Examples

### Health Check - curl - all

```bash
curl --location 'http://****-hangzhou.opensearch.aliyuncs.com/v3/openapi/workspaces/default/memory/agentic-memory/health' \
--header 'Authorization: Bearer <YOUR_API_KEY>'
```

### Store Memory with Skill Extraction - curl - all

```bash
curl --location 'http://****-hangzhou.opensearch.aliyuncs.com/v3/openapi/workspaces/default/memory/agentic-memory/memories' \
--header 'Authorization: Bearer <YOUR_API_KEY>' \
--header 'Content-Type: application/json' \
--data '{
  "messages": [
    {"role": "user", "content": "I like coffee. Please recommend some."},
    {"role": "assistant", "content": "Here are some coffee recommendations..."}
  ],
  "user_id": "user_123",
  "enhancements": {
    "skill": {
      "enable": true
    }
  }
}'
```

### Poll Asynchronous Task - curl - all

```bash
curl --location 'http://****-hangzhou.opensearch.aliyuncs.com/v3/openapi/workspaces/default/memory/agentic-memory/tasks/mt-52b939a7-5a20-47e6-97e4-3cbb87bd9227' \
--header 'Authorization: Bearer <your API key>'
```

### Search Memory and Skills - curl - all

```bash
curl --location 'http://****-hangzhou.opensearch.aliyuncs.com/v3/openapi/workspaces/default/memory/agentic-memory/search' \
--header 'Authorization: Bearer <YOUR_API_KEY>' \
--header 'Content-Type: application/json' \
--data '{
  "query": "coffee",
  "user_id": "user_123",
  "enhancements": {
    "skill": {
      "enable": true
    }
  }
}'
```

### Update Memory - curl - all

```bash
curl -X PUT --location 'http://****-hangzhou.opensearch.aliyuncs.com/v3/openapi/workspaces/default/memory/agentic-memory/memories/m-60aa2de5-c43e-4b3d-9efd-f058bc3994be' \
--header 'Authorization: Bearer <YOUR_API_KEY>' \
--header 'Content-Type: application/json' \
--data '{
  "memory": "Likes Americano coffee"
}'
```

### Upload Skill - curl - all

```bash
curl -X POST --location 'http://****-hangzhou.opensearch.aliyuncs.com/v3/openapi/workspaces/default/memory/agentic-memory/skills' \
--header 'Authorization: Bearer <YOUR_API_KEY>' \
--header 'Content-Type: application/json' \
--data '{
  "zip_base64": "<Base64-encoded content of the ZIP file>",
  "user_id": "user_123"
}'
```

### Delete Memory - curl - all

```bash
curl --location --request DELETE 'http://****-hangzhou.opensearch.aliyuncs.com/v3/openapi/workspaces/default/memory/agentic-memory/m-60aa2de5-c43e-4b3d-9efd-f058bc3994be' \
--header 'Authorization: Bearer <YOUR_API_KEY>'
```

## Response Format

```json
{
  "request_id": "9907b179-7bcc-2c43-21db-d3c9d777bbfe",
  "latency": 161,
  "status": "OK",
  "result": {
    "memory": {
      "task_id": "mt-52b939a7-5a20-47e6-97e4-3cbb87bd9227"
    },
    "skill": {
      "task_id": "st-1b0bfe52-d44d-4fdb-94ae-8513fa77ab55"
    }
  }
}
```

**Key Fields**:
- `request_id` — Unique ID for the API request (useful for debugging)
- `latency` — Processing time in milliseconds
- `status` — Operation status (`OK` or error code)
- `result.memory.task_id` — Asynchronous task ID for memory creation
- `result.skill.task_id` — Asynchronous task ID for skill creation
- `result.memory_ids` — List of retrieved memory IDs (in search responses)
- `result.skill_ids` — List of retrieved skill IDs (in search responses)
- `result.error_message` — Error details if status is not OK

## Error Handling

| Error Code | Description | Recommended Action |
|------------|-------------|-------------------|
| 400 | InvalidParameter - One or more request parameters are invalid. | Validate required fields, correct data types, and ensure `memory_id`/`skill_id` prefixes (`m-`/`s-`) |
| 401 | Unauthorized - The request is not authorized. | Verify your API key and ensure it’s included in the `Authorization: Bearer` header |
| 404 | NotFound - The specified resource does not exist. | Confirm the `memory_id`, `skill_id`, or `task_id` exists and is spelled correctly |
| 429 | RateLimitExceeded - The request rate exceeds the rate limit. | Reduce request frequency; implement exponential backoff |
| 500 | InternalServerError - An internal server error occurred. | Retry the request after a short delay; contact support if persistent |

### Rate Limits & Retry
- **Rate limit**: 10 QPS (queries per second)
- **Retry strategy**: Use exponential backoff (e.g., 1s, 2s, 4s delays) on 429 errors
- Respect the `Retry-After` header if present in error responses

## Environment Requirements

- Set your API key: `export ES_MEMORY_API_KEY=your_api_key_here`
- No specific SDK is required — use standard HTTP clients (curl, requests, etc.)
- For OpenClaw integration: Node.js 18+ and proper plugin configuration

## FAQ

Q: Are memory and skill creation truly synchronous?
A: No — while the initial API call returns immediately with a `task_id`, the actual processing is asynchronous. You must poll the `/tasks/{task_id}` endpoint to confirm completion before using the resulting `memory_id` or `skill_id`.

Q: What format should the `messages` parameter use?
A: Use an array of role-content objects for multi-turn conversations (e.g., `[{"role": "user", "content": "..."}, {"role": "assistant", "content": "..."}]`). A single string is acceptable for simple cases.

Q: How do I enable skill extraction during memory storage?
A: Include `"enhancements": {"skill": {"enable": true}}` in your POST request to `/memories`. Note: skills can only be extracted from multi-turn conversations.

Q: Can I search only memories or only skills?
A: The `/search` endpoint returns both by default when `enhancements.skill.enable` is true. To restrict results, filter client-side using the `result.memory_ids` and `result.skill_ids` fields.

Q: What regions are supported?
A: The service is available in major Alibaba Cloud regions including `cn-hangzhou`, `cn-shanghai`, and `cn-beijing`. Use the region-specific endpoint provided in your console.

## Pricing & Billing

### Billing Model
Billed **per request**. Asynchronous tasks are charged upon completion.

### Price Reference

| Tier | Input Price | Output Price |
|------|-------------|--------------|
| agentic-memory | 0.002 /tokens | 0.002 /tokens |

### Free Tier
100 requests per month free

### Usage Limits
- Rate limit: 10 QPS
- Single request max: 8K tokens

### Billing Notes
Asynchronous tasks are billed on completion. Minimum billing unit for tasks is 1 hour (as noted in secondary documentation).