# opensearch-memory

Part of **OPENSEARCH**

# OpenSearch Memory Management

## Capabilities Overview

| Sub-capability | Calling Mode | Description |
|----------------|--------------|-------------|
| Store Memory | Synchronous | Store user or agent memory from conversation messages; returns an async task ID. |
| Search Memory and Skill | Synchronous | Perform hybrid BM25 and vector search over memory and skill data using a query string. |
| Retrieve Memory | Synchronous | Fetch a specific memory entry by its unique memory_id (prefixed with m-). |
| Update Memory | Synchronous | Modify the content of an existing memory entry using PUT. |
| Delete Memory | Synchronous | Remove a memory entry by its memory_id. |
| Upload Skill | Synchronous | Upload a Base64-encoded ZIP file containing a skill package; returns an async task ID. |
| Retrieve Skill | Synchronous | Fetch a specific skill by its unique skill_id (prefixed with s-). |
| Update Skill | Synchronous | Update metadata (e.g., version, description) of an existing skill. |
| Delete Skill | Synchronous | Remove a skill entry by its skill_id. |
| Query Task Status | Synchronous | Check the status and result of an asynchronous memory or skill operation using task_id. |

## API Calling Patterns

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

- Include the header: `Authorization: Bearer <your_api_key>`
- Store your API key in the environment variable: `OPENSEARCH_API_KEY`
- While other auth methods may exist, Bearer Token is the standard for all provided examples.

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

`http://{region}-opensearch.aliyuncs.com/v3/openapi/workspaces/{workspace_name}/memory/agentic-memory`

- Replace `{region}` with your deployment region (e.g., `cn-hangzhou`, `cn-shanghai`, `cn-beijing`)
- The default `workspace_name` is `default`
- Example full endpoint: `http://cn-hangzhou-opensearch.aliyuncs.com/v3/openapi/workspaces/default/memory/agentic-memory/memories`

### Synchronous with Asynchronous Task Handling
Although the API calls are synchronous (immediate HTTP response), memory and skill creation operations return **asynchronous task IDs** that must be polled for final results.

**Flow for Store/Upload Operations**:
1. POST to `/memories` or `/skills` → receive `task_id` (e.g., `mt-...` or `st-...`)
2. Poll `GET /tasks/{task_id}` until `status` is `SUCCEEDED` or `FAILED`
3. Extract resulting `memory_ids` or `skill_ids` from the task result

**Flow for Direct Operations**:
- GET, PUT, DELETE on `/memories/{memory_id}` or `/skills/{skill_id}` return immediate results (no polling needed)

## Parameter Reference

### Store Memory / Search Memory

| Parameter | Type | Required | Default | Constraints | Description |
|----------|------|----------|---------|-------------|-------------|
| messages | String / Object / Array | Yes | — | — | Conversation content: String (text), 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 | — | — | Identifier for the current execution run. |
| enhancements | Object | No | — | — | Enables optional features when included. |
| enhancements.skill.enable | Boolean | No | false | — | Enable skill extraction (only works with multi-turn `messages`). |
| query | String | Yes | — | — | Search term for memory/skill retrieval. |
| size | Int | No | 10 | ≥1 | Maximum number of results to return. |

### Update Memory / Skill

| Parameter | Type | Required | Default | Constraints | Description |
|----------|------|----------|---------|-------------|-------------|
| memory | String | Yes | — | — | Updated content for the memory entry. |
| version | String | No | — | — | New version string for the skill. |
| description | String | No | — | — | Human-readable description of the skill. |
| tags | Array | No | — | — | List of string tags for categorizing the skill. |
| files | Object | No | — | — | Updated file content (format matches GET skill response). |

### Upload Skill

| Parameter | Type | Required | Default | Constraints | Description |
|----------|------|----------|---------|-------------|-------------|
| zip_base64 | String | Yes | — | — | Base64-encoded ZIP file containing the skill package. |

### Common Identifiers

| Parameter | Type | Required | Default | Constraints | Description |
|----------|------|----------|---------|-------------|-------------|
| memory_id | String | Yes | — | Must start with `m-` | Unique ID for a memory entry. |
| skill_id | String | Yes | — | Must start with `s-` | Unique ID for a skill entry. |
| task_id | String | Yes | — | Must start with `mt-` or `st-` | ID returned from async memory/skill operations. |

## Code Examples

### Store Memory with Skill Extraction - curl - cn-hangzhou

```bash
curl --location 'http://cn-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
    }
  }
}'
```

### Search Memory and Skills - curl - cn-hangzhou

```bash
curl --location 'http://cn-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 Content - curl - cn-hangzhou

```bash
curl -X PUT --location 'http://cn-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 Package - curl - cn-hangzhou

```bash
curl -X POST --location 'http://cn-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"
}'
```

### Check Async Task Status - curl - cn-hangzhou

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

### Delete Memory Entry - curl - cn-hangzhou

```bash
curl --location --request DELETE 'http://cn-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` — Overall operation status (`OK`, `ERROR`, etc.)
- `result.memory.task_id` — Async task ID for memory operations
- `result.skill.task_id` — Async task ID for skill operations
- `result.memory_ids` — List of created/updated memory IDs (in task result)
- `result.skill_ids` — List of created/updated skill IDs (in task result)
- `result.error_message` — Error details if status indicates failure

## Error Handling

| Error Code | Description | Recommended Action |
|------------|-------------|---------------------|
| 400 | InvalidParameter - One or more request parameters are invalid. | Validate required fields (`user_id`, `messages`, etc.) and format (e.g., `memory_id` must start with `m-`). |
| 401 | Unauthorized - The request is not authorized. | Ensure your `Authorization: Bearer <API_KEY>` header uses a valid key with proper permissions. |
| 404 | NotFound - The specified resource, such as a memory, skill, or task, does not exist. | Verify the `memory_id`, `skill_id`, or `task_id` exists and is correctly formatted. |
| 429 | RateLimitExceeded - The request rate exceeds the rate limit. | Reduce request frequency; implement retry with 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) per workspace
- **Retry Strategy**: Use exponential backoff (e.g., 1s, 2s, 4s delays) for 429 errors
- **Async Tasks**: Final billing occurs on task completion, not submission

## Environment Requirements

- Set your API key: `export OPENSEARCH_API_KEY=your_api_key_here`
- Use any standard HTTP client (curl, requests, axios, etc.)
- No specific SDK is required; the service uses standard REST/JSON

## FAQ

Q: Do I need to poll for every memory operation?
A: Only for POST operations (`/memories`, `/skills`) that return a `task_id`. GET, PUT, and DELETE on specific IDs return immediately.

Q: What format should the skill ZIP file contain?
A: The ZIP should include skill definition files (e.g., YAML/JSON manifest and code assets). The exact structure is defined by the skill runtime; refer to skill documentation for templates.

Q: Can I search across multiple users' memories?
A: No. All operations are scoped to a single `user_id` for data isolation and privacy.

Q: Why am I getting a 404 when retrieving a memory right after storing it?
A: Memory creation is asynchronous. You must poll the task endpoint until completion before the `memory_id` becomes available for retrieval.

Q: Are memory and skill IDs globally unique?
A: Yes. Each `memory_id` (prefixed `m-`) and `skill_id` (prefixed `s-`) is unique across the entire service.

## Pricing & Billing

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

### Price Reference

| Tier | Input Price | Output Price |
|------|-------------|--------------|
| agentic-memory | ¥0.002 per 1k tokens | ¥0.002 per 1k tokens |

### Free Tier
100 requests per month free

### Usage Limits
- Rate limit: 10 QPS
- No explicit token limits per request, but large payloads may affect latency

### Billing Notes
Asynchronous tasks (memory/skill creation) are billed only when the task reaches `SUCCEEDED` status. Failed tasks are not billed.