> ## Documentation Index
> Fetch the complete documentation index at: https://docs.veadk.xyz/llms.txt
> Use this file to discover all available pages before exploring further.

# Use OpenSearch storage

The `opensearch` backend uses OpenSearch as the vector store. Memory text is embedded by an embedding model, written to OpenSearch with a per-user index (the actual index name is `{index}_{user_id}`), and retrieved by similarity. It is the **default backend** for `LongTermMemory`.

## When to use

* You already run an OpenSearch cluster and want self-hosted vector search;
* You need persistence, sharing across processes and instances, and full control over indexing and retrieval.

## Dependencies

```bash lines theme={null}
pip install "veadk-python[extensions]"
```

## Usage

Before running, provide a reachable OpenSearch cluster, an account allowed to create and access indexes, a valid CA certificate, and the connection and embedding variables below. Dimensions must match an existing index; use a new index and reinsert memories when changing dimensions

```python lines theme={null}
from veadk import Agent
from veadk.memory.long_term_memory import LongTermMemory

# index must be lowercase, only a-z0-9_-., and not start with _ or -
ltm = LongTermMemory(backend="opensearch", index="ltm_demo")

agent = Agent(
    name="demo",
    instruction="Answer the user; when needed, use the `load_memory` tool to recall past conversations.",
    long_term_memory=ltm,
)
```

You can also pass connection and embedding config explicitly via `backend_config`:

```python lines theme={null}
import os

from veadk.memory.long_term_memory import LongTermMemory
from veadk.configs.database_configs import OpensearchConfig

ltm = LongTermMemory(
    backend="opensearch",
    index="ltm_demo",
    backend_config={
        "index": "ltm_demo",
        "opensearch_config": OpensearchConfig(
            host="localhost",
            port=9200,
            username="admin",
            password=os.environ["DATABASE_OPENSEARCH_PASSWORD"],
            use_ssl=True,
            cert_path="/path/to/ca.pem",
        ),
    },
)
```

## Parameters

### LongTermMemory parameters

| Parameter | Type | Default | Description |
| - | - | - | - |
| `backend` | `str \| BaseLongTermMemoryBackend` | `"opensearch"` | Set to `opensearch` for this page, or pass a configured backend instance |
| `backend_config` | `dict` | `{}` | Backend settings; a supplied backend instance takes precedence |
| `index` | `str` | `""` | Without backend\_config, resolves from index, app\_name, then default\_app; supply a nonempty index with a configuration dictionary |
| `app_name` | `str` | `""` | Fallback for index; the actual user comes from the saved Session or search arguments |
| `top_k` | `int` | `5` | Number of retrieved chunks; use a positive integer |
| `user_id` | `str` | `""` | Deprecated; does not select the runtime user |

### Constructor parameters

`backend_config` supports the following settings:

| Parameter | Type | Default | Description |
| :- | :- | :- | :- |
| `index` | `str` | No default; provided by `LongTermMemory` | Memory index name; must follow OpenSearch naming rules. |
| `opensearch_config` | `OpensearchConfig` | Read automatically from `DATABASE_OPENSEARCH_*` env vars | OpenSearch connection config. |
| `embedding_config` | `EmbeddingModelConfig` | Read automatically from `MODEL_EMBEDDING_*` env vars | Embedding model config. |

### OpenSearch connection config

`opensearch_config` is an `OpensearchConfig` with env prefix `DATABASE_OPENSEARCH_`:

| Field | Env var | Type | Default | Description |
| :- | :- | :- | :- | :- |
| `host` | `DATABASE_OPENSEARCH_HOST` | `str` | `""` | OpenSearch host. |
| `port` | `DATABASE_OPENSEARCH_PORT` | `int` | `9200` | Port. |
| `use_ssl` | `DATABASE_OPENSEARCH_USE_SSL` | `bool` | `true` | Whether to enable SSL. |
| `username` | `DATABASE_OPENSEARCH_USERNAME` | `str` | `""` | Username. |
| `password` | `DATABASE_OPENSEARCH_PASSWORD` | `str` | `""` | Password. |
| `cert_path` | `DATABASE_OPENSEARCH_CERT_PATH` | `str` | `""` | CA certificate path. When empty, certificates are not verified — a security risk that triggers a warning. |
| `secret_token` | `DATABASE_OPENSEARCH_SECRET_TOKEN` | `str` | `""` | Not used by current OpenSearch long-term memory connections |

### Embedding config

`embedding_config` is an `EmbeddingModelConfig` with env prefix `MODEL_EMBEDDING_`:

| Field | Env var | Type | Default | Description |
| :- | :- | :- | :- | :- |
| `name` | `MODEL_EMBEDDING_NAME` | `str` | `doubao-embedding-vision-250615` | Embedding model name. |
| `dim` | `MODEL_EMBEDDING_DIM` | `int` | `2048` | Embedding vector dimension; used to build the index's vector field. |
| `api_base` | `MODEL_EMBEDDING_API_BASE` | `str` | `https://ark.cn-beijing.volces.com/api/v3/` | API base of the embedding service. |
| `api_key` | `MODEL_EMBEDDING_API_KEY` | `str` | Falls back to `MODEL_AGENT_API_KEY`, then an auto-fetched Ark token | Key for accessing the embedding service. |

## Environment variables

```bash lines theme={null}
# OpenSearch connection
export DATABASE_OPENSEARCH_HOST="localhost"
export DATABASE_OPENSEARCH_PORT=9200
export DATABASE_OPENSEARCH_USERNAME="admin"
export DATABASE_OPENSEARCH_PASSWORD="admin"
export DATABASE_OPENSEARCH_USE_SSL=true
export DATABASE_OPENSEARCH_CERT_PATH="/path/to/ca.pem"

# Embedding model
export MODEL_EMBEDDING_NAME="doubao-embedding-vision-250615"
export MODEL_EMBEDDING_DIM=2048
export MODEL_EMBEDDING_API_KEY="your-ark-api-key"
```

<Warning>
  `index` must follow OpenSearch naming rules: all lowercase, only `a-z0-9_-.`, and not starting with `_` or `-`; otherwise initialization fails. In production, set `cert_path` to enable certificate verification and avoid security risks.
</Warning>

## Verify writes and retrieval

After configuring the dependencies and credentials on this page, run this standalone example. It saves user text and searches for that user directly without calling a conversation model

```python lines theme={null}
import asyncio

from google.adk.events import Event
from google.adk.sessions import Session
from google.genai import types
from veadk.memory.long_term_memory import LongTermMemory

async def main():
    memory = LongTermMemory(backend="opensearch", index="ltm_demo")
    session = Session(
        id="memory_check", app_name="ltm_demo", user_id="user_42",
        events=[Event(author="user", content=types.Content(
            role="user", parts=[types.Part(text="My preferred language is Chinese")]
        ))],
    )
    await memory.add_session_to_memory(session)
    result = await memory.search_memory(
        app_name="ltm_demo", user_id="user_42", query="preferred language"
    )
    for entry in result.memories:
        print(entry.content)

asyncio.run(main())
```

Results should contain the saved language preference. Managed services may extract memories asynchronously, so a completed write does not guarantee immediate retrieval. An empty result can also indicate permission, network, or service failure; check error logs and service records. The save method does not return a success Boolean

The final index includes `user_id`, so user IDs must also meet the index character rules. The same `index` and `user_id` access the same memory; `search_memory(app_name=...)` does not add another index boundary
