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

# Memory

> The values a skill tracks across a conversation.

Memory is what a skill remembers as the conversation unfolds: the selected
card, the reason for a replacement, whether the user is authenticated. Tools
write to it, the framework checks it, and instructions branch on it.

## Everything must be declared

A memory entry has to exist in a schema before anything can write to it. A tool
that writes an undeclared key fails `rasa train` with `undeclared_memory_write`.

```yaml skills/card_replace/memory.yml theme={null}
schema:
  public:
    replacement_reason:
      type: categorical
      enum_values: [lost, stolen, damaged, not_received]
      llm_settable: true
      description: Why the card is being replaced.
    selected_card_id:
      type: text
  private:
    eligibility_checked:
      type: bool
```

The top-level key is `schema:`, not `memory:`.

* **`public`** values are readable by every other skill.
* **`private`** values stay internal to this skill.

Once declared, a tool writes with a bare entry name; the active skill decides
the namespace:

```python theme={null}
context.memory.set("selected_card_id", card.id)
```

## Who is allowed to write

Two different actors write memory, and they're governed separately:

* **Tools** write whatever the skill declares, via `context.memory.set()`.
* **The LLM** may only write entries flagged `llm_settable: true`, or entries
  owned by a `collect:` step. It does so through the built-in `set_fields` tool.

That flag matters. Mark the customer's *decisions* settable, such as the
replacement reason or the shipping choice. Leave engine-derived values such as
eligibility results, lock state, and computed flags unflagged, so the model can
neither invent them nor "correct" them later.

The LLM never writes **project** memory. Those fields are filled by a tool, a
post-write hook, or session-start metadata on fields marked `seed: true`, then
locked for the rest of the session. See the [`memory.yml` reference](https://rasa.com/docs/mantle/reference/memory-yml).

## Sharing between skills

Values shared across skills go in a **project-level `memory.yml`** at the agent
root. It is a flat map of entry name to attributes:

```yaml memory.yml theme={null}
authenticated:
  type: bool
  description: Whether the customer has verified their identity.
```

These live in the `project.` namespace. This is how a skill depends on
authentication without depending on the authentication *skill*:

```yaml theme={null}
requires: "session.project.authenticated"
```

The only contract between the two skills is the key. Put session-wide facts in
project memory; keep collectable labels and working state on the skill. The
engine refuses a second write to a set project field.

Skill public and private are working state for the current run. They stay after
complete or cancel so other skills can still read leftover public, and they
reset when that same skill starts again. Put facts that must last the whole
conversation in project memory.

## Branching on memory

A `categorical` value can drive
[scoped instructions](https://rasa.com/docs/mantle/build-guide/scoped-instructions.md), so the LLM only ever
sees the relevant branch:

```markdown theme={null}
if: session.card_replace.replacement_reason == 'stolen'
Tell the customer the card will be locked for their protection.
```

Conditions always use the three-segment namespaced form,
`session.<skill_id>.<entry>` or `session.project.<entry>`. See
[Conditions](https://rasa.com/docs/mantle/reference/conditions.md). To put a live value into instruction
prose itself, use `@memory.…` — see [skill.md](https://rasa.com/docs/mantle/reference/skill-md.md).

## Access control

A skill can further restrict what its own tools may touch:

```yaml theme={null}
access:
  deny_read:
    - card_replace.card_list
  deny_write:
    - project.authenticated
```

A denied read returns `None`; a denied write raises. Entries are written as
fully-qualified names, `<skill_id>.<entry>` or `project.<entry>`.

When Mantle persists a write, the tracker records `memory_set` or
`memory_cleared` **and** a matching `slot_set` (same key and value) so existing
consumers still match. See
[Tracker events](https://rasa.com/docs/mantle/reference/execution-loop.md#tracker-events).

## Reference

For every field attribute, the full type list, visibility rules, and naming, see
the [`memory.yml` reference](https://rasa.com/docs/mantle/reference/memory-yml).


## Related topics

- [memory.yml](https://rasa.com/docs/mantle/reference/memory-yml.md)
- [Assistant Memory (Slots)](https://rasa.com/docs/pro/build/assistant-memory.md)
- [Assertions](https://rasa.com/docs/mantle/reference/assertions.md)
- [Trying Your Assistant](https://rasa.com/docs/pro/testing/trying-assistant.md)
- [skill.md](https://rasa.com/docs/mantle/reference/skill-md.md)


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.