> ## 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.

# Long-term memory

Long-term memory persists important information across sessions and over time — user preferences, task history, key facts, or long-lived state. Short-term memory only lives within a single session; long-term memory lets an agent remember facts **across different sessions**.

Why you need it:

* Continuous conversation experience across sessions;
* Retain learnings and user-specific information over many interactions;
* Avoid repetitive questions, improving satisfaction and efficiency;
* Support long-term strategy optimization such as personalization or task tracking.

## Single entry point: `LongTermMemory`

Whatever backend you use, you interact with `veadk.memory.long_term_memory.LongTermMemory`. It plugs directly into an agent as its memory service and selects the storage backend through `backend`.

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

ltm = LongTermMemory(backend="viking", app_name="ltm_demo")
```

### Parameters

| Parameter | Type | Default | Description |
| :- | :- | :- | :- |
| `backend` | `"local" \| "opensearch" \| "redis" \| "viking" \| "mem0" \| "openviking" \| "tos_context"` | `"opensearch"` | Selects the backend. `viking_mem` is deprecated and maps to `viking`. |
| `backend_config` | `dict` | `{}` | Backend-specific settings. If `index` is absent, VeADK fills it from `index` or `app_name`. |
| `top_k` | `int` | `5` | Number of most-similar chunks to retrieve. |
| `index` | `str` | `""` | Index/collection name for storing memories. Falls back to `app_name`, then `default_app`. |
| `app_name` | `str` | `""` | The owning application name; used for data isolation and as the `index` fallback. |
| `user_id` | `str` | `""` | **Deprecated**, kept only for backward compatibility. |

<Note>
  Vector backends (`local`, `opensearch`, and `redis`) embed memories locally and require the extensions extra and an embedding model. `viking`, `mem0`, `openviking`, and `tos_context` use external services and do not need local embedding.
</Note>

## Choosing a backend

Use `local` for debugging. In production, select `viking`, `mem0`, or `tos_context` according to your existing services and data-governance requirements.

| Backend | Storage | Requires | Use case | Docs |
| :- | :- | :- | :- | :- |
| `local` | In-memory vector index | `extensions` + embedding | Local debugging | [In-memory](/productions/veadk/preview/en/components/memory/local) |
| `viking` | VikingDB memory (managed) | Volcengine account | Recommended for production | [VikingDB](/productions/veadk/preview/en/components/memory/vikingdb) |
| `mem0` | Mem0 memory (managed) | Mem0 API key | Recommended for production | [Mem0](/productions/veadk/preview/en/components/memory/mem0) |
| `opensearch` | OpenSearch vector store | OpenSearch + embedding | Self-hosted vector search | [OpenSearch](/productions/veadk/preview/en/components/memory/opensearch) |
| `redis` | Redis vector store | Redis (RediSearch) + embedding | Self-hosted vector search | [Redis](/productions/veadk/preview/en/components/memory/redis) |
| `openviking` | OpenViking user memory | OpenViking service | Entity, event, and preference memory | [OpenViking](/productions/veadk/preview/en/components/memory/openviking) |
| `tos_context` | TOS ContextBucket (managed) | Volcengine account and TOS SDK `>=2.9.4b1` | Managed memory inference with per-user isolation | [TOS ContextBucket](/productions/veadk/preview/en/components/memory/tos-context) |

## Binding to an Agent

Passing `long_term_memory` to an `Agent` **auto-injects the `load_memory` tool** so the agent can retrieve past sessions at run time.

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

APP_NAME = "ltm_demo"
ltm = LongTermMemory(backend="viking", app_name=APP_NAME)

root_agent = Agent(
    name="ltm_agent",
    instruction="Answer the user. If the answer might be in past conversations, use the `load_memory` tool.",
    long_term_memory=ltm,
)
runner = Runner(agent=root_agent, app_name=APP_NAME)
```

## Managing memory

### Write: `add_session_to_memory`

When a session ends or hits a checkpoint, call the async `add_session_to_memory` to persist it. `LongTermMemory` filters events according to the auto-save policy — by default keeping only user text events to improve retrieval quality. You can customize the filtering rules with the `auto_save_memory_policy` parameter before passing events to the backend.

```python lines theme={null}
completed_session = await runner.session_service.get_session(
    app_name=APP_NAME, user_id=USER_ID, session_id=SESSION_ID
)
await ltm.add_session_to_memory(completed_session)
```

`add_session_to_memory` accepts an optional `auto_save_memory_policy` keyword argument to override the default filtering policy:

```python lines theme={null}
from veadk.memory import MemoryAutoSavePolicy

await ltm.add_session_to_memory(
    completed_session,
    auto_save_memory_policy=MemoryAutoSavePolicy(preset="all"),
)
```

### Retrieve: `search_memory`

Besides the agent's automatic retrieval via `load_memory`, you can call the async `search_memory` directly for semantic search — useful for debugging or custom RAG:

```python lines theme={null}
response = await ltm.search_memory(
    app_name=APP_NAME,
    user_id=USER_ID,
    query="favorite project",
)
print(response.memories)
```

<Note>
  `get_user_profile(user_id)` is supported only by the `viking` backend; others return an empty string.
</Note>

## Auto-save sessions

Set `auto_save_session=True` on the `Agent` with long-term memory configured, and VeADK persists sessions automatically — no manual `add_session_to_memory`.

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

agent = Agent(
    name="ltm_agent",
    auto_save_session=True,
    long_term_memory=LongTermMemory(backend="viking", app_name="ltm_demo"),
)
```

To avoid frequent index re-initialization, VeADK exposes `MIN_MESSAGES_THRESHOLD` and `MIN_TIME_THRESHOLD` env vars to tune the save cadence: by default it saves after 10 accumulated events or a 60-second interval; additionally, when you switch `session_id` and start a new turn, VeADK saves the previous session to long-term memory.

Auto-save uses incremental writes: each save only persists the events that are new since the last save, rather than the entire session. If there are no new events between two saves, the write is skipped.

### Controlling what gets saved: `auto_save_memory_policy`

The `Agent` accepts an `auto_save_memory_policy` parameter that controls which events are written to long-term memory during auto-save. The same value is passed as the `auto_save_memory_policy` keyword argument to `add_session_to_memory`.

The parameter type is `MemoryAutoSavePolicyInput`, which accepts one of:

* A string preset: `"default"`, `"all"`, or `"custom"`;
* A `MemoryAutoSavePolicy` instance;
* A `dict` with the same fields as `MemoryAutoSavePolicy`;
* `None` (equivalent to `"default"`).

| Preset | What is saved |
| :- | :- |
| `"default"` | Saves only user-role text events (the default). The `openviking` backend includes assistant-role events as well due to its own limitations. |
| `"all"` | Saves all roles and all event types, including thoughts and empty text. |
| `"custom"` | Starts from an empty policy and filters only by the fields you explicitly set. |

Using a preset string:

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

agent = Agent(
    name="ltm_agent",
    auto_save_session=True,
    auto_save_memory_policy="all",
    long_term_memory=LongTermMemory(backend="viking", app_name="ltm_demo"),
)
```

Using a `MemoryAutoSavePolicy` instance for fine-grained control:

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

agent = Agent(
    name="ltm_agent",
    auto_save_session=True,
    auto_save_memory_policy=MemoryAutoSavePolicy(
        preset="custom",
        include_roles=["user", "assistant"],
        include_event_types=["text", "function_call", "function_response"],
        include_thought=False,
    ),
    long_term_memory=LongTermMemory(backend="viking", app_name="ltm_demo"),
)
```

Full fields of `MemoryAutoSavePolicy`:

| Field | Type | Default | Description |
| :- | :- | :- | :- |
| `preset` | `"default" \| "all" \| "custom"` | `"default"` | Selects the base preset. Fields you do not explicitly override keep the preset's defaults. |
| `include_roles` | `list["user" \| "assistant" \| "system"] \| None` | Depends on preset | Only save events from these roles. Set to `None` to disable role filtering. |
| `exclude_roles` | `list["user" \| "assistant" \| "system"]` | `[]` | Exclude events from these roles. |
| `include_authors` | `list[str] \| None` | Depends on preset | Only save events from these authors (`author`). Set to `None` to disable author filtering. |
| `exclude_authors` | `list[str]` | `[]` | Exclude events from these authors. |
| `include_event_types` | `list[MemoryEventType] \| None` | Depends on preset | Only save these event types. Set to `None` to disable event-type filtering. |
| `exclude_event_types` | `list[MemoryEventType]` | `[]` | Exclude these event types. |
| `text_only` | `bool` | Depends on preset | When `True` and `include_event_types` is not set, only text and thought content is kept. |
| `include_thought` | `bool` | Depends on preset | Whether to save thought content. |
| `include_empty_text` | `bool` | Depends on preset | Whether to save events with no actual content. |

`MemoryEventType` includes the following event types: `text`, `thought`, `function_call`, `function_response`, `tool_call`, `tool_response`, `media`, `executable_code`, `code_execution_result`, `transcription`, `error`.

<Note>
  String presets provide a quick configuration shortcut. When you pass a `MemoryAutoSavePolicy` instance or `dict`, the policy starts from the base preset indicated by `preset`; only the fields you explicitly set override the preset, while all other fields keep the preset's default behavior.
</Note>

## Cross-session example

An end-to-end flow: session #1 tells the agent a fact and auto-archives it, then a **brand-new** session #2 asks a question — and the agent recalls the fact via memory retrieval (not the context window). This uses the `local` backend, which needs `pip install "veadk-python[extensions]"`.

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

from veadk import Agent, Runner
from veadk.memory.long_term_memory import LongTermMemory

APP_NAME = "ltm_demo"
USER_ID = "user-42"


def build_runner() -> Runner:
    ltm = LongTermMemory(backend="local", app_name=APP_NAME)
    agent = Agent(
        name="ltm_agent",
        instruction=(
            "You are a personal assistant. When the user asks about something they "
            "told you earlier, use the `load_memory` tool to recall it."
        ),
        long_term_memory=ltm,
        auto_save_session=True,
    )
    return Runner(agent=agent, app_name=APP_NAME, user_id=USER_ID)


async def main() -> None:
    runner = build_runner()

    print(
        "Session 1 ->",
        await runner.run(
            messages="Note this: I'm allergic to peanuts and I'm vegetarian.",
            session_id="session-1",
        ),
    )

    print(
        "Session 2 ->",
        await runner.run(
            messages="Recommend a dish for me, considering my dietary restrictions.",
            session_id="session-2",
        ),
    )


if __name__ == "__main__":
    asyncio.run(main())
```

In session #2 the agent recognizes the same user's preferences left in session #1 and answers coherently and personally (e.g. a peanut-free vegetarian dish).
