> ## Documentation Index
> Fetch the complete documentation index at: https://maestro.rasa.com/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.

## 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}
selected_card_id:
  type: text
  description: Account id of the card the customer chose.
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.

## Branching on memory

A `categorical` value can drive
[scoped instructions](/build-guide/scoped-instructions), 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](/reference/conditions).

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

## Reference

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