> ## Documentation Index
> Fetch the complete documentation index at: https://developer.watson-orchestrate.ibm.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Memory

## Overview

Use the Agentic SDK memory APIs to persist user information and retrieve relevant data during agent execution.\
This page defines the supported APIs, runtime requirements, and correct usage patterns for runs-on custom agents.

### Initialize the SDK

Initialize the SDK client before using memory features.

For more information, see [Client](/sdk/client).

##### Example endpoints the SDK calls

* `/memories`
* `/memories/search`

##### Additional behavior

* `WXO_API_PROXY_URL` overrides `execution_context["api_proxy_url"]`
* runs-on defaults to `verify=False` unless overridden

### Minimal Runs-On Agent

```python PYTHON [expandable] theme={null}
from __future__ import annotations

from typing import Annotated, TypedDict

from langchain_core.messages import AIMessage, BaseMessage
from langgraph.graph import END, StateGraph
from langgraph.graph.message import add_messages
from langgraph.graph.state import RunnableConfig

from ibm_watsonx_orchestrate_sdk import Client


class AgentState(TypedDict):
    messages: Annotated[list[BaseMessage], add_messages]


def _latest_user_message(messages: list[BaseMessage]) -> str:
    for message in reversed(messages):
        if getattr(message, "type", "") == "human":
            content = getattr(message, "content", "")
            if isinstance(content, str) and content.strip():
                return content
    return ""


def create_agent(config: RunnableConfig):
    client = Client.from_runnable_config(config)

    def agent_node(state: AgentState):
        user_text = _latest_user_message(state.get("messages", []))
        if not user_text:
            return {"messages": [AIMessage(content="No user message found.")]}

        search_response = client.memory.search(query=user_text, limit=3)

        if search_response.results:
            memory_text = "\n".join(item.content for item in search_response.results)
            response_text = f"I found related memories:\n{memory_text}"
        else:
            response_text = "I do not have anything relevant in memory yet."

        return {"messages": [AIMessage(content=response_text)]}

    builder = StateGraph(AgentState)
    builder.add_node("agent", agent_node)
    builder.set_entry_point("agent")
    builder.add_edge("agent", END)
    return builder
```

### Packaging and Import

```bash BASH [expandable] theme={null}
./.venv/bin/orchestrate agents import \
  --experimental-package-root examples/custom_agents/local_memory_sdk_agent
```

##### This command

* Packages the directory
* Uploads code and dependencies
* Creates or updates the agent

### Memory APIs

##### Write API

```python PYTHON theme={null}
client.memory.add_messages(...)
```

##### Read APIs

```python PYTHON [expandable] theme={null}
client.memory.search(...)
client.memory.list(...)
client.memory.retrieve(...)
```

##### Delete APIs

```python PYTHON [expandable] theme={null}
client.memory.delete(memory_id="...")
client.memory.delete_all()
```

##### Removed API

* `store()` is removed
* Use `add_messages(...)`

##### Recommended Usage

```python PYTHON [expandable] theme={null}
client.memory.add_messages(
    messages=[{"role": "user", "content": "I prefer coffee"}],
    memory_type="preference",
    infer=False,
    metadata={"source": "manual-test"},
)
```

##### Search examples

```python PYTHON theme={null}
response = client.memory.search(query="favorite drink", limit=3)
```

```python PYTHON [expandable] theme={null}
response = client.memory.search(
    query="favorite drink",
    limit=3,
    memory_type="preference",
)
```

### Public Method Signatures

##### add\_messages

```python PYTHON [expandable] theme={null}
add_messages(
    *,
    messages,
    infer=None,
    memory_type=None,
    metadata=None,
    agent_id=None,
    run_id=None,
    sensitivity_classification=None,
    source_reference=None,
)
```

##### search

```python PYTHON [expandable] theme={null}
search(
    *,
    query,
    limit=10,
    memory_type=None,
    expanded_query=None,
    recall=None,
)
```

##### retrieve

```python PYTHON theme={null}
retrieve(query, limit=10)
```

##### list

```python PYTHON theme={null}
list(*, limit=100, offset=0)
```

##### delete

```python PYTHON theme={null}
delete(*, memory_id)
```

##### delete\_all

```python PYTHON theme={null}
delete_all()
```

#### Valid Message Format

```bash BASH theme={null}
{"role": "user", "content": "I prefer coffee"}
```

##### Common message shapes

* single user message
* user + assistant
* user + tool

#### Supported memory\_type Values

##### Canonical values

* `conversational`
* `profile_fact`
* `preference`
* `outcome`
* `tool`

#### Supported aliases

* `conversation` → `conversational`
* `fact` → `conversational`
* `episodic` → `conversational`
* `profile` → `profile_fact`
* `identity` → `profile_fact`
* `preferences` → `preference`
* `task` → `tool`
* `procedure` → `tool`
* `derived_event` → `outcome`

##### Validation behavior

* Invalid values fail fast with an SDK error

### Metadata

```python PYTHON [expandable] theme={null}
metadata={
    "source": "chat",
    "source_request_id": "req-123",
    "scope": "user_profile",
    "case_id": "case-42",
    "ticket_id": "ticket-99",
}
```

#### Prefer top-level fields

##### Use

* `memory_type`
* `agent_id`
* `run_id`
* `sensitivity_classification`
* `source_reference`

#### Scoping Rules

##### Memory is user-scoped

* Not agent-owned
* Not thread-scoped

##### Implications

* Users can recall memory across agents
* `delete_all()` affects all memory for the user
* `list()` returns all user memory

#### Infer behavior

##### Use `infer=False` when

* Memory type is known
* Deterministic storage is required

##### Use default inference when

* Passing rich message windows
* Backend extraction is preferred

#### Example Memory Loop

```python PYTHON [expandable] theme={null}
from ibm_watsonx_orchestrate_sdk import Client


def remember_preference(config, text: str):
    client = Client.from_runnable_config(config)
    return client.memory.add_messages(
        messages=[{"role": "user", "content": text}],
        memory_type="preference",
        infer=False,
        metadata={"source": "agent"},
    )


def recall_preferences(config, query: str):
    client = Client.from_runnable_config(config)
    return client.memory.search(
        query=query,
        memory_type="preference",
        limit=3,
    )
```

#### Common failure modes

##### Missing api\_proxy\_url

* Runtime did not provide it
* Environment variable not set

##### TLS or hostname errors

* SDK uses URL exactly as provided
* Invalid certificates cause failures

##### Invalid memory\_type

* Fails immediately with validation error

##### Empty search results

* Valid outcome
* Not an error

##### What to test

* Agent initializes from `RunnableConfig`
* `add_messages(...)` succeeds
* `search(...)` returns structured response
* Empty results handled correctly
* Invalid types fail fast

##### Mental model

* runs-on is the runtime path
* `Client.from_runnable_config(config`) is the standard entry
* `add_messages(...)` writes memory
* `search(...)` reads memory
* memory is user-scoped
* `api_proxy_url` must already be correct

### References

* [Client](/sdk/client)
* [Runs-on](/sdk/runs_on)
