> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.runtype.com/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.runtype.com/_mcp/server.

# Using memory steps

Memory steps let a Flow store text in a long-term memory profile and read it back in later runs. Use them to keep facts about a customer, a workspace, or a project across executions without managing Records yourself.

Three step types work with memory:

* `save-memory`: stores the value of a variable in a memory profile.
* `recall-memory`: answers a question from the memories in a profile and returns the answer as text.
* `memory-summary`: returns a Markdown summary of a profile, with sections for key facts, recent events, and active tasks.

The Flow editor's step picker doesn't list memory steps, and the editor has no settings form for them. Add memory steps in a Flow definition with the TypeScript SDK or the API. For more information, see [Manage flows as code](/user-guide/flows/manage-flows-as-code).

## Before you begin

Before you add memory steps, set up the following:

* Install the TypeScript SDK with `npm install @runtypelabs/sdk`.
* Create an API key with the **Flows (Write)** permission (`FLOWS:WRITE`).
* Decide which identity each memory profile belongs to, such as one profile for each end user.

## Choose a memory profile

Every memory step has a `profileTemplate` field. The template resolves to the name of the memory profile that the step reads or writes. It accepts `{{variable}}` references, so one Flow can keep a separate profile for each end user, tenant, or record.

The following table lists common templates:

| Template          | Profile scope                                       | Requires                           |
| ----------------- | --------------------------------------------------- | ---------------------------------- |
| `{{_endUser.id}}` | One profile for each end user                       | An `endUser` object in the request |
| `{{_tenant.id}}`  | One profile for each Product Tenant                 | A `tenant` object in the request   |
| `{{_user.id}}`    | One profile for each Runtype user who runs the Flow | Nothing                            |
| `{{_flow.id}}`    | One profile shared by every run of this Flow        | Nothing                            |
| `customer-{{id}}` | One profile for each value of a Flow input variable | An `id` variable in the run        |

Runtype keeps memory profiles separate for each organization. Two organizations that use the same template never share a profile.

A memory step and an Agent with memory turned on use the same profiles. If a Flow and an Agent in your organization resolve to the same profile, they read and write the same memories. For more information about Agent memory, see [Creating and configuring agents](/user-guide/agents/creating-and-configuring-agents#memory).

If a variable in `profileTemplate` doesn't resolve, the step fails. When a request might not include an end user, add a fallback, such as `{{_endUser.id ?? "anonymous"}}`. For more information about system variables and fallbacks, see [Flow variables and templates](/user-guide/flows/flow-variables-and-templates).

## Save a memory

A `save-memory` step reads the variable that `contentVariable` names and stores its value in the profile. A string value is stored as is. Any other value is stored as JSON text. If the variable is empty or undefined, the step fails.

The following fields configure a `save-memory` step:

* `profileTemplate`: required. The memory profile to write to.
* `contentVariable`: required. The name of the variable that holds the content, without braces. Dot paths such as `ticket.summary` work.
* `sessionId`: optional. Groups the memory with others from the same session.
* `outputVariable`: optional. Stores `{ "success": true, "profileId": "...", "memoryId": "...", "type": "..." }` after the save.

## Recall a memory

A `recall-memory` step sends a question to the profile and stores the answer. The step returns a written answer, not the raw memories.

The following fields configure a `recall-memory` step:

* `profileTemplate`: required. The memory profile to read from.
* `queryTemplate`: required. The question to answer. It accepts `{{variable}}` references. If a reference doesn't resolve, the step fails.
* `outputVariable`: required. The variable that stores the result.
* `thinkingLevel`: optional. How broadly to search the profile: `low`, `medium`, or `high`.
* `responseLength`: optional. How long the answer is: `short`, `medium`, or `long`.

The result object has an `answer` string, a `count` of matched memories, and a `candidates` array. If the output variable is `customer_memory`, reference the answer as `{{customer_memory.answer}}`.

## Get a memory summary

A `memory-summary` step returns an overview of everything in the profile. Use it when a prompt needs the full profile rather than the answer to one question.

The following fields configure a `memory-summary` step:

* `profileTemplate`: required. The memory profile to summarize.
* `outputVariable`: required. The variable that stores the result.
* `sessionId`: optional. Adds a section for the named session.

The result object has one field, `summary`, which holds Markdown text. If the output variable is `profile`, reference it as `{{profile.summary}}`.

## Remember a customer's preferences

The following Flow recalls what it knows about an end user, answers their question with that context, and saves the question for later runs:

**`TypeScript SDK`**

```typescript title="TypeScript SDK"
import { defineFlow } from '@runtypelabs/sdk'

export const supportReply = defineFlow({
  name: 'Support reply with memory',
  steps: [
    {
      type: 'recall-memory',
      name: 'Recall customer context',
      config: {
        profileTemplate: '{{_endUser.id}}',
        queryTemplate: 'What do we know that helps answer: {{question}}',
        responseLength: 'short',
        outputVariable: 'customer_memory',
      },
    },
    {
      type: 'prompt',
      name: 'Answer question',
      config: {
        model: 'claude-sonnet-5',
        userPrompt:
          'Known context: {{customer_memory.answer}}\n\nAnswer: {{question}}',
        outputVariable: 'reply',
      },
    },
    {
      type: 'save-memory',
      name: 'Remember question',
      config: {
        profileTemplate: '{{_endUser.id}}',
        contentVariable: 'question',
      },
    },
  ],
})
```

Run the Flow with a `question` input and an `endUser` object that has an `id`. On the first run, the recall step finds nothing about the end user. On later runs with the same `endUser.id`, `{{customer_memory.answer}}` draws on the questions that earlier runs saved.

To create or update the Flow from this definition, pass it to `ensure`.

## Handle errors

When `errorHandling` is unset, a failed memory step doesn't stop the Flow. The step reports the error and writes a default value to its output variable:

* `save-memory` writes `{ "success": false }`.
* `recall-memory` writes `{ "answer": "", "count": 0, "candidates": [] }`.
* `memory-summary` writes `{ "summary": "" }`.

To use your own value, set `defaultValue` on the step. To stop the Flow when a memory step fails, set `errorHandling` to `{ "onError": "fail" }`. For example, set it on a recall step whose answer the rest of the Flow depends on, so an unresolved profile template doesn't produce a reply with no context.

For more information about step errors, see [When a step fails](/user-guide/flows/flow-step-types-overview#when-a-step-fails).

## Next steps

* [Debugging flows](/user-guide/flows/debugging-flows): inspect what each memory step wrote in a run
* [Using record steps (get/list/upsert)](/user-guide/flows/using-record-steps-upsert-retrieve): store structured data that you query by field