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

# Memory

> Agents learn from their finished sessions automatically, and you can add curated memory stores, review every change, and restore or redact old versions.

Memory gives an agent knowledge that lasts across sessions. Each memory is a short text document at a path such as `/conventions/testing.md`, with a one-line summary.

There are two kinds of memory store:

| Store              | Who writes it                                                                      | How sessions get it                                                           |
| ------------------ | ---------------------------------------------------------------------------------- | ----------------------------------------------------------------------------- |
| **Learned memory** | Recursion, automatically, from the agent's finished sessions. Every agent has one. | Attached to every session of that agent.                                      |
| **Curated store**  | You, through the API.                                                              | Attached to the sessions an [automation](/managed-agents/automations) starts. |

Store contents never go into the prompt up front. A session sees each attached store's name and description, and the agent browses, searches, and reads a memory only when it helps the task. What a session costs doesn't grow with how much the agent has learned.

The samples assume the `rl` client from [Client setup](/managed-agents/api#client-setup).

## Before you begin

* Reading memory needs any role that can read Managed Agents. Creating stores and memories needs create permission, editing needs update, and deleting or redacting needs delete. Organization developers and admins have all of them. See [Organizations and roles](/managed-agents/organizations-and-roles).
* You need an agent. Learned memory starts once the agent's first session starts. See [Agents](/managed-agents/agents).

## How learned memory works

```mermaid theme={"theme":"css-variables"}
flowchart LR
  sessions["Finished sessions"] --> reports["A short report per session"]
  reports --> run["Learning run"]
  run --> store["Agent's learned memory"]
  store --> next["Later sessions browse, search, and read it"]
```

1. When a session finishes, Recursion writes a short report of what it was for, what worked, what failed, and any reusable tactic. Most sessions teach nothing, and their report says so.
2. When enough useful reports are waiting, or on the regular schedule, a **learning run** reviews them and applies a small set of changes: it adds memories, refines existing ones, merges duplicates, and retires ones that no longer hold.
3. The next session of the agent can use the updated memory.

Learning always runs automatically; there's nothing to switch on. You choose the model it uses. A learning run is an ordinary session, so you can read its reasoning and see what it spent.

### Learning states

| State      | Console label              | Meaning                                                                                            |
| ---------- | -------------------------- | -------------------------------------------------------------------------------------------------- |
| `waiting`  | **Waiting for sessions**   | No useful reports yet.                                                                             |
| `idle`     | **Learning automatically** | Memory is current. New sessions are reviewed as they finish.                                       |
| `updating` | **Updating memories**      | A learning run is in progress.                                                                     |
| `delayed`  | **Updates delayed**        | A learning run failed. It retries on its own at `next_retry_at`. Existing memories stay available. |

## See what an agent learned

<Tabs>
  <Tab title="Console">
    1. In the sidebar, click **Memory**. The table lists every agent with its **Memories** count, **Learning status**, and **Last updated** time.
    2. Click an agent. You can also open an agent and choose its **Memory** tab.
    3. On **Memories**, search, filter by **Topic**, or sort by **Recently updated** or **Alphabetical**. Click a memory to read it and its **History**.
    4. On **Activity**, open an update to see **Why it ran**, **Reports read**, the sessions it **Learned from**, and **What the memory update did**.
  </Tab>

  <Tab title="TypeScript">
    ```typescript theme={"theme":"css-variables"}
    const summary = await rl.managedAgents.getAgentMemory({
      agent_id: '5f0c2a1e-8b7d-4c3a-9e21-6d4f0b9a7c55',
    });
    const { memories, topics } = await rl.managedAgents.listAgentMemories({
      agent_id: '5f0c2a1e-8b7d-4c3a-9e21-6d4f0b9a7c55',
      query: 'release',
    });
    ```
  </Tab>

  <Tab title="cURL">
    ```bash theme={"theme":"css-variables"}
    curl 'https://api.recursion.labelbox.com/managed-agents/v1/agents/5f0c2a1e-8b7d-4c3a-9e21-6d4f0b9a7c55/memory' \
      -H "Authorization: Bearer $RECURSION_API_KEY"
    curl 'https://api.recursion.labelbox.com/managed-agents/v1/agents/5f0c2a1e-8b7d-4c3a-9e21-6d4f0b9a7c55/memories?query=release' \
      -H "Authorization: Bearer $RECURSION_API_KEY"
    ```
  </Tab>
</Tabs>

```json theme={"theme":"css-variables"}
{
  "agent_id": "5f0c2a1e-8b7d-4c3a-9e21-6d4f0b9a7c55",
  "agent_name": "Release engineer",
  "memory_store_id": "0b3e7d52-9c14-4a86-b2f1-6e8d4c7a9f05",
  "memory_count": 14,
  "total_bytes": 18240,
  "revision": 6,
  "state": "idle",
  "effective_model": "anthropic/claude-sonnet-4-5",
  "pending_session_count": 0,
  "failed_session_count": 0,
  "last_updated_at": "2026-09-24T17:42:10Z",
  "last_checked_at": "2026-09-25T09:12:44Z"
}
```

`listAgentMemories` returns current memories without their content, 50 per page by default and up to 100, plus `topics` from the whole collection. Pass `topic`, `sort` (`updated` or `alphabetical`), `limit`, and `cursor` to narrow and page. `listAgentMemorySummaries` returns the same summary for every agent at once.

To follow learning runs, call `listAgentMemoryActivity` for one agent, or `listReflections` for the organization, filtered by `agent_id`, `status`, or `triggered_by`. `getReflection` returns one run with the sessions it read, the counts it `added`, `updated`, `merged`, and `retired`, and `driver_session_id`, the session that ran it.

## Choose the memory model

Learning uses the agent's model unless you set another one.

<Tabs>
  <Tab title="Console">
    1. Open the agent's memory, as above.
    2. Under **Memory model**, choose a model. Choose **Same as agent** to go back to the agent's model.
  </Tab>

  <Tab title="TypeScript">
    ```typescript theme={"theme":"css-variables"}
    const learning = await rl.managedAgents.updateAgentLearning({
      agent_id: '5f0c2a1e-8b7d-4c3a-9e21-6d4f0b9a7c55',
      body: { memory_model_ref: 'anthropic/claude-sonnet-4-5' },
    });
    ```
  </Tab>

  <Tab title="cURL">
    ```bash theme={"theme":"css-variables"}
    curl -X PATCH 'https://api.recursion.labelbox.com/managed-agents/v1/agents/5f0c2a1e-8b7d-4c3a-9e21-6d4f0b9a7c55/learning' \
      -H "Authorization: Bearer $RECURSION_API_KEY" \
      -H 'Content-Type: application/json' \
      -d '{"memory_model_ref":"anthropic/claude-sonnet-4-5"}'
    ```
  </Tab>
</Tabs>

```json theme={"theme":"css-variables"}
{
  "memory_model_ref": "anthropic/claude-sonnet-4-5"
}
```

Send `"memory_model_ref": null` to inherit the agent's model again. The model must be a `provider/model` id from `listModels` (see [Agents](/managed-agents/agents)). The change applies to the next learning run. Read the setting with `getAgentLearning`.

## Create a curated store

A curated store holds reference material you write, such as release policy or team conventions. Scope it to one agent with `agent_id`, or leave `agent_id` out to make a workspace store any agent's automation can attach.

The `description` is shown to every agent the store is attached to, so write it as what the agent would be looking for.

<Tabs>
  <Tab title="Console">
    Curated stores are created and edited through the API. The console's **Memory** screen shows each agent's learned memory.
  </Tab>

  <Tab title="TypeScript">
    ```typescript theme={"theme":"css-variables"}
    const store = await rl.managedAgents.createMemoryStore({
      body: {
        name: 'Release policy',
        description: 'How we version, tag, and ship releases, and who approves them.',
        agent_id: '5f0c2a1e-8b7d-4c3a-9e21-6d4f0b9a7c55',
      },
    });
    ```
  </Tab>

  <Tab title="cURL">
    ```bash theme={"theme":"css-variables"}
    curl -X POST 'https://api.recursion.labelbox.com/managed-agents/v1/memory_stores' \
      -H "Authorization: Bearer $RECURSION_API_KEY" \
      -H 'Content-Type: application/json' \
      -d '{
        "name": "Release policy",
        "description": "How we version, tag, and ship releases, and who approves them.",
        "agent_id": "5f0c2a1e-8b7d-4c3a-9e21-6d4f0b9a7c55"
      }'
    ```
  </Tab>
</Tabs>

The response is `201` with the store:

```json theme={"theme":"css-variables"}
{
  "memory_store_id": "6e2a9c41-5b73-4d08-a1f6-9c3e7b5d2a80",
  "name": "Release policy",
  "slug": "release-policy",
  "description": "How we version, tag, and ship releases, and who approves them.",
  "agent_id": "5f0c2a1e-8b7d-4c3a-9e21-6d4f0b9a7c55",
  "origin": "curated",
  "status": "active",
  "memory_count": 0,
  "total_bytes": 0,
  "revision": 0,
  "created_at": "2026-09-25T10:02:11Z",
  "updated_at": "2026-09-25T10:02:11Z"
}
```

`slug` stays the same when you rename the store. `origin` is `curated` for stores you create and `reflection` for an agent's learned memory.

## Add memories

Keep each memory small and focused. The path is how agents find things, so group related memories under a shared prefix.

<Tabs>
  <Tab title="Console">
    Memories in curated stores are added through the API.
  </Tab>

  <Tab title="TypeScript">
    ```typescript theme={"theme":"css-variables"}
    const memory = await rl.managedAgents.createMemory({
      memory_store_id: '6e2a9c41-5b73-4d08-a1f6-9c3e7b5d2a80',
      body: {
        path: '/releases/versioning.md',
        summary: 'How release versions are chosen.',
        content: 'Bump the minor version for features and the patch version for fixes.',
      },
    });
    ```
  </Tab>

  <Tab title="cURL">
    ```bash theme={"theme":"css-variables"}
    curl -X POST 'https://api.recursion.labelbox.com/managed-agents/v1/memory_stores/6e2a9c41-5b73-4d08-a1f6-9c3e7b5d2a80/memories' \
      -H "Authorization: Bearer $RECURSION_API_KEY" \
      -H 'Content-Type: application/json' \
      -d '{
        "path": "/releases/versioning.md",
        "summary": "How release versions are chosen.",
        "content": "Bump the minor version for features and the patch version for fixes."
      }'
    ```
  </Tab>
</Tabs>

```json theme={"theme":"css-variables"}
{
  "memory_store_id": "6e2a9c41-5b73-4d08-a1f6-9c3e7b5d2a80",
  "memory_id": "8c4f1a62-7d95-4b30-a2e8-5f0c9d3b6a71",
  "path": "/releases/versioning.md",
  "summary": "How release versions are chosen.",
  "content": "Bump the minor version for features and the patch version for fixes.",
  "content_sha256": "4f1c9a0e7b2d5836c1e04a9f7d3b6e2a8c5f0d1b9e7a3c6f2d8b4e0a1c7f5d93",
  "byte_size": 72,
  "status": "active",
  "head_version_id": "2f9a6c41-3b75-4d08-a1e6-8c5e7b2d9a30",
  "created_at": "2026-09-25T10:04:52Z",
  "updated_at": "2026-09-25T10:04:52Z"
}
```

`path`, `summary`, and `content` are all required. Create never overwrites: a path that already exists is refused, so change it with `updateMemory` instead. A retried create can't destroy content.

## Browse and read a store

`listMemories` lists one level of a store, like a directory: memories and `memory_prefix` entries that stand for the paths beneath them, with a `count`. Content isn't included. `path_prefix` matches whole path segments, so `/releases/` returns `/releases/versioning.md` and never `/releases-old/notes.md`.

<Tabs>
  <Tab title="TypeScript">
    ```typescript theme={"theme":"css-variables"}
    const { entries } = await rl.managedAgents.listMemories({
      memory_store_id: '6e2a9c41-5b73-4d08-a1f6-9c3e7b5d2a80',
      path_prefix: '/releases/',
    });
    const memory = await rl.managedAgents.getMemoryByPath({
      memory_store_id: '6e2a9c41-5b73-4d08-a1f6-9c3e7b5d2a80',
      path: '/releases/versioning.md',
    });
    ```
  </Tab>

  <Tab title="cURL">
    ```bash theme={"theme":"css-variables"}
    curl 'https://api.recursion.labelbox.com/managed-agents/v1/memory_stores/6e2a9c41-5b73-4d08-a1f6-9c3e7b5d2a80/memories?path_prefix=/releases/' \
      -H "Authorization: Bearer $RECURSION_API_KEY"
    curl 'https://api.recursion.labelbox.com/managed-agents/v1/memory_stores/6e2a9c41-5b73-4d08-a1f6-9c3e7b5d2a80/memory?path=/releases/versioning.md' \
      -H "Authorization: Bearer $RECURSION_API_KEY"
    ```
  </Tab>
</Tabs>

```json theme={"theme":"css-variables"}
{
  "entries": [
    { "type": "memory", "path": "/releases/versioning.md", "summary": "How release versions are chosen.", "byte_size": 72 },
    { "type": "memory_prefix", "path": "/releases/checklists/", "count": 3 }
  ]
}
```

Read by id with `getMemory` after a create or a search. Both reads return the full `content` and its `content_sha256`.

## Update a memory safely

Pass the `content_sha256` you read. If someone changed the memory since, the update is refused with `409 content_sha256_mismatch` instead of overwriting their change. A different `path` renames the memory. Omitted fields stay as they are.

<Tabs>
  <Tab title="TypeScript">
    ```typescript theme={"theme":"css-variables"}
    const updated = await rl.managedAgents.updateMemory({
      memory_store_id: '6e2a9c41-5b73-4d08-a1f6-9c3e7b5d2a80',
      memory_id: '8c4f1a62-7d95-4b30-a2e8-5f0c9d3b6a71',
      body: {
        content: 'Bump the minor version for features, the patch version for fixes, and the major version for breaking changes.',
        content_sha256: '4f1c9a0e7b2d5836c1e04a9f7d3b6e2a8c5f0d1b9e7a3c6f2d8b4e0a1c7f5d93',
      },
    });
    ```
  </Tab>

  <Tab title="cURL">
    ```bash theme={"theme":"css-variables"}
    curl -X POST 'https://api.recursion.labelbox.com/managed-agents/v1/memory_stores/6e2a9c41-5b73-4d08-a1f6-9c3e7b5d2a80/memories/8c4f1a62-7d95-4b30-a2e8-5f0c9d3b6a71' \
      -H "Authorization: Bearer $RECURSION_API_KEY" \
      -H 'Content-Type: application/json' \
      -d '{
        "content": "Bump the minor version for features, the patch version for fixes, and the major version for breaking changes.",
        "content_sha256": "4f1c9a0e7b2d5836c1e04a9f7d3b6e2a8c5f0d1b9e7a3c6f2d8b4e0a1c7f5d93"
      }'
    ```
  </Tab>
</Tabs>

The response is the updated memory with a new `head_version_id`. `deleteMemory` removes a memory from every read path, returns `204`, records the deletion in history, and frees the path for reuse.

## Attach curated stores to sessions

Curated stores reach sessions through an automation's run defaults. Every session the automation starts gets the stores in `runDefaults.memoryStores`, next to the agent's learned memory. See [Automations](/managed-agents/automations#set-run-defaults).

```json theme={"theme":"css-variables"}
{
  "runDefaults": {
    "metadata": null,
    "memoryStores": [
      {
        "memoryStoreId": "6e2a9c41-5b73-4d08-a1f6-9c3e7b5d2a80",
        "access": "read_only",
        "instructions": "Check release policy before you change a release workflow."
      }
    ]
  }
}
```

* The store must be active, and either a workspace store or one scoped to the automation's agent.
* `access` is `read_only` or `read_write`. Sessions browse, search, and read attached stores the same way with either.
* `instructions` is shown to the agent beside the store's name and description, up to 4,096 characters.

In the transcript, agents use three memory tools: `list_memories` to browse a store, `search_memories` to find memories by content, and `read_memory` to read one in full.

## Manage stores

| To                   | Call                                             | Result                                                                                                                                 |
| -------------------- | ------------------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------- |
| List stores          | `listMemoryStores`                               | `memory_stores`, filtered by `agent_id`, `origin`, and `status`. Archived stores are left out unless you pass `include_archived=true`. |
| Rename or redescribe | `updateMemoryStore` with `name` or `description` | The store. Omitted fields stay as they are.                                                                                            |
| Freeze a store       | `archiveMemoryStore`                             | `204`. The store becomes read-only and can't be attached to new sessions. There's no unarchive.                                        |
| Delete a store       | `deleteMemoryStore`                              | `204`. The store and its memories disappear from every read path.                                                                      |

Archive and delete apply to curated stores only. An agent's learned memory can't be archived, deleted, or edited by hand; its history is still readable, and you can shape it by choosing the memory model.

<Tabs>
  <Tab title="TypeScript">
    ```typescript theme={"theme":"css-variables"}
    const { memory_stores } = await rl.managedAgents.listMemoryStores({ origin: 'curated' });
    await rl.managedAgents.archiveMemoryStore({
      memory_store_id: '6e2a9c41-5b73-4d08-a1f6-9c3e7b5d2a80',
    });
    ```
  </Tab>

  <Tab title="cURL">
    ```bash theme={"theme":"css-variables"}
    curl 'https://api.recursion.labelbox.com/managed-agents/v1/memory_stores?origin=curated' \
      -H "Authorization: Bearer $RECURSION_API_KEY"
    curl -X POST 'https://api.recursion.labelbox.com/managed-agents/v1/memory_stores/6e2a9c41-5b73-4d08-a1f6-9c3e7b5d2a80/archive' \
      -H "Authorization: Bearer $RECURSION_API_KEY"
    ```
  </Tab>
</Tabs>

## Review, restore, and redact versions

Every create, update, rename, delete, and retirement writes an immutable version. Versions belong to the store, so history survives a deleted memory. Each version records who wrote it (`author_kind` is `session`, `api`, `reflection`, or `admin`), and a learning run's versions also carry a `rationale` and the `evidence_session_ids` behind the change.

| Action         | Call                                              | Result                                                                                                  |
| -------------- | ------------------------------------------------- | ------------------------------------------------------------------------------------------------------- |
| List history   | `listMemoryVersions`, optionally with `memory_id` | Newest first, without content. 50 per page by default, up to 100, with `next_cursor`.                   |
| Read a version | `getMemoryVersion`                                | The version with its content, unless it was redacted.                                                   |
| Roll back      | `restoreMemoryVersion`                            | Writes that version's content back as a new version and returns the memory. Recreates a deleted memory. |
| Scrub a secret | `redactMemoryVersion`                             | `204`. The content is removed for good; who wrote it and when are kept.                                 |

<Tabs>
  <Tab title="TypeScript">
    ```typescript theme={"theme":"css-variables"}
    const { memory_versions } = await rl.managedAgents.listMemoryVersions({
      memory_store_id: '6e2a9c41-5b73-4d08-a1f6-9c3e7b5d2a80',
      memory_id: '8c4f1a62-7d95-4b30-a2e8-5f0c9d3b6a71',
    });
    const restored = await rl.managedAgents.restoreMemoryVersion({
      memory_store_id: '6e2a9c41-5b73-4d08-a1f6-9c3e7b5d2a80',
      memory_version_id: '2f9a6c41-3b75-4d08-a1e6-8c5e7b2d9a30',
    });
    ```
  </Tab>

  <Tab title="cURL">
    ```bash theme={"theme":"css-variables"}
    curl 'https://api.recursion.labelbox.com/managed-agents/v1/memory_stores/6e2a9c41-5b73-4d08-a1f6-9c3e7b5d2a80/memory_versions?memory_id=8c4f1a62-7d95-4b30-a2e8-5f0c9d3b6a71' \
      -H "Authorization: Bearer $RECURSION_API_KEY"
    curl -X POST 'https://api.recursion.labelbox.com/managed-agents/v1/memory_stores/6e2a9c41-5b73-4d08-a1f6-9c3e7b5d2a80/memory_versions/2f9a6c41-3b75-4d08-a1e6-8c5e7b2d9a30/redact' \
      -H "Authorization: Bearer $RECURSION_API_KEY"
    ```
  </Tab>
</Tabs>

You can't redact the version that is a memory's current content. To remove a leaked secret, write or restore a clean version first, then redact the old one. Redaction can't be undone, and a redacted version can't be restored.

Versions are kept for 30 days. The recent versions of a live memory are kept regardless of age.

## Write memory that helps

* **One idea per memory.** Small documents are cheaper for the agent to read and easier to keep current.
* **Paths are the index.** Use folders such as `/releases/` and `/testing/` so an agent can browse to the right place.
* **Summaries are for people and search.** Say what the memory tells the agent in one line.
* **Store descriptions route the agent.** Describe when to look in the store, not just what's in it.
* **Keep secrets out.** Memory is text agents read. Put credentials in [vaults](/managed-agents/vaults).

## What can go wrong

| Code or symptom                                             | Cause                                                                                              | Fix                                                                                 |
| ----------------------------------------------------------- | -------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------- |
| `400 invalid_request` on `content` or `summary`             | Content is empty or over 100 KiB, or the summary is over 512 characters.                           | Split large content into several memories, and shorten the summary.                 |
| `400 invalid_request` on `memory_store_id`                  | The store is an agent's learned memory, or it's archived.                                          | Write to an active curated store.                                                   |
| `400 invalid_request` on `memory_model_ref`                 | The model isn't a `provider/model` id.                                                             | Copy an id from `listModels`, or send `null`.                                       |
| `400 invalid_request` on `memory_version_id` when restoring | The version was redacted.                                                                          | Restore a different version.                                                        |
| `404 not_found`                                             | The agent, store, memory, or version doesn't exist in your organization.                           | Use an id from a list in the same organization.                                     |
| `409 content_sha256_mismatch`                               | The memory changed after you read it.                                                              | Read it again, reapply your change, and retry with the new hash.                    |
| Create is refused for an existing path                      | Create never overwrites.                                                                           | Use `updateMemory`.                                                                 |
| Redact is refused                                           | The version is the memory's current content.                                                       | Write or restore a replacement, then redact.                                        |
| **Updates delayed** in the console                          | A learning run failed.                                                                             | Nothing to do. It retries at `next_retry_at`, and existing memories stay available. |
| An agent doesn't use a curated store                        | The store isn't attached, is archived, belongs to another agent, or is past the per-session limit. | Attach it through the automation's run defaults, and keep to 7 extra stores.        |

For every error code, see [Errors](/managed-agents/errors).

## Limits

| Limit                                          | Value                                                  |
| ---------------------------------------------- | ------------------------------------------------------ |
| One memory's content                           | 100 KiB                                                |
| One memory's summary                           | 512 characters                                         |
| Memories in one store                          | 10,000                                                 |
| Stores one session uses                        | 8, including the agent's learned memory                |
| Curated stores in an automation's run defaults | 7                                                      |
| Attachment instructions                        | 4,096 characters                                       |
| Version history retention                      | 30 days, plus the recent versions of every live memory |
| History and memory list page size              | 1 to 100, default 50                                   |

See [Limits](/managed-agents/limits) for every other limit.

## Next steps

<CardGroup cols={2}>
  <Card title="Automations" href="/managed-agents/automations">
    Attach curated stores to every run.
  </Card>

  <Card title="Agents" href="/managed-agents/agents">
    Configure the agent whose sessions it learns from.
  </Card>

  <Card title="Files" href="/managed-agents/files">
    Give sessions input files and download deliverables.
  </Card>

  <Card title="Skills" href="/managed-agents/skills">
    Package procedures agents follow every time.
  </Card>
</CardGroup>
