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

# responses.yml

> Named response templates, memory interpolation, and how they are delivered.

`responses.yml` holds named text templates the framework delivers verbatim. Use
it for wording that must be exact: legal disclosures, compliance notices,
regulated confirmations. Everything else should stay prose so the agent sounds
natural.

```yaml skills/card_replace/responses.yml theme={null}
responses:
  utter_ask_shipping:
    - text: >-
        How would you like the new card shipped: rush delivery in 1 to 2
        business days, or standard in 5 to 7?

  utter_card_replacement_fee:
    - text: Standard replacement is free.
    - text: A fee applies for lost-card replacement.
      condition: 'session.card_replace.replacement_reason == "lost"'

  utter_card_replace_completed:
    - text: >-
        All set. Your replacement card has been ordered and will ship via
        {session.card_replace.order_shipping_summary} delivery.
```

The top-level key is `responses:`. Each name maps to a **list of variants**. At
delivery the engine selects **one** variant from that list (see
[Conditional variants](#conditional-variants) below). A response with a single
variant and no `condition` always selects that single variant.

An entry is either a mapping with a `text` key, or a plain string:

```yaml theme={null}
responses:
  utter_goodbye:
    - "Thanks for calling. Goodbye!"
```

## Conditional variants

Add an optional `condition` on a variant to gate its wording on current memory.
Conditions use the same [expression grammar](https://rasa.com/docs/mantle/reference/conditions.md) as skill
`requires:` and prose `if:` lines.

```yaml theme={null}
responses:
  utter_card_replacement_fee:
    - text: Standard replacement is free.
    - text: A fee applies for lost-card replacement.
      condition: 'session.card_replace.replacement_reason == "lost"'
    - text: No fee for cards reported stolen.
      condition: 'session.card_replace.replacement_reason == "stolen"'
```

### How a variant is selected

When a response is delivered, the engine evaluates variants **in YAML order**:

1. Skip variants with no `condition` during this pass.
2. For each conditioned variant, evaluate its `condition` against readable
   memory. The **first** variant whose condition is true is delivered.
3. If none match, deliver the **default** variant — the one that omits
   `condition`.
4. If every variant is unconditioned, deliver the first variant.

If evaluating a condition raises an error at delivery time (for example a
comparison the current memory type cannot satisfy), that variant is skipped and
evaluation continues. When no conditioned variant matches, the default is used.

If there is no default and nothing can be selected (every variant is conditioned
and none match, or every condition fails evaluation), delivery fails closed the
same way as a missing response name: the engine utters the response name as
literal text and does not rephrase.

`metadata.rephrase` applies to whichever variant is selected, not always the
first variant.

### Default variant rules

When **any** variant on a response has a `condition`, exactly **one** variant
must omit `condition`. That variant is the **fallback** when no condition matches.
It may appear **anywhere** in the YAML list — first, last, or between
conditioned variants. The engine skips default variants while evaluating conditions,
then delivers that single fallback variant.

`rasa train` rejects:

* empty or non-list response entries (must be a non-empty variant list)
* empty or whitespace-only `text` on any variant
* invalid or empty `condition` syntax (must be a string expression)
* memory references in a `condition` that are not declared in skill or project
  `memory.yml`
* conditioned variants with no default, or more than one default

**Train errors during project validation** (`rasa data validate`, packaging):

| Problem | What you see |
| - | - |
| Empty list, mapping, or scalar instead of a variant list | Finding with code `mantle.validation.response.invalid_variant_shape`, plus file path and response name |
| Unknown variant keys (`channel:`, `buttons:`, typos like `conditon:`) | Finding with code `mantle.validation.response.invalid_variant_key`, plus file path, response name, and variant index |
| Empty text, bad conditions, memory refs, default rules | Finding with code `mantle.validation.response.*`, plus file path, response name, and variant index |

All project `responses.yml` files are checked; findings accumulate across files.

**Runtime model load** (packaged agent) still uses strict registry parsing.
Unknown variant keys there raise `ValidationError` with code
`responses.registry.invalid_variant` and stop loading that file.

### Unsupported variant keys

Only `text`, `metadata`, and `condition` are permitted on a variant.
`channel:` and `buttons:` are **not** supported in this release — adding them
is reported at project validation time and causes strict registry load to fail
at runtime.

## Where the file lives

| Location | Scope |
| - | - |
| `skills/<id>/responses.yml` | Declared by that skill |
| `responses.yml` at the agent root | Declared project-wide |

At load, every file is merged into **one flat registry**, later sources
overriding earlier ones on duplicate names:

1. Packaged system defaults
2. Each bundled default skill's `responses.yml`
3. Each project skill's `responses.yml`, in directory order
4. The project-root `responses.yml`

This is how you override a built-in message: declare the same response name in
your own file. Redefining `utter_silence_timeout_check_in`, for example, replaces
the check-in the bundled `default_silence_timeout` skill delivers.

The bundled `default_session_start` skill has no greeting response. To greet,
override the skill as described in
[Start a conversation](https://rasa.com/docs/mantle/orchestration/runtime-loop.md#start-a-conversation).

Because the registry is flat, response names are global rather than scoped to
the skill that declares them. Prefix names with the skill (`utter_card_replace_completed`)
so two skills keep their wording distinct.

## Interpolation

A placeholder in braces is replaced with a memory value at delivery time. Two
forms work, and they resolve differently:

| Placeholder | Resolves against |
| - | - |
| `{session.<namespace>.<entry>}` | Everything the active skill can read: its own fields, other skills' `public` fields, and project memory |
| `{entry}` | The active skill's own schema first, then project memory |

```yaml theme={null}
utter_confirm_order:
  - text: |
      Card: {session.card_disambiguation.selected_card_label}
      Reason: {session.card_replace.replacement_reason}
      Shall I place the order?
```

Use the namespaced form to read another skill's `public` field. The bare form is
convenient for a skill's own entries and follows the same resolution order a
tool's `context.memory.get()` uses.

A placeholder whose value is unset at delivery time is left in the text as
written, so interpolate only values you know are set by the time the response is
sent, typically ones written earlier in the same ordered block.

Interpolation applies to responses. For live values in `skill.md` instruction
prose, use `@memory.…` instead — see [skill.md](https://rasa.com/docs/mantle/reference/skill-md.md). Do not
put bare `session.*` in free prose; train fails and points you at `@memory`.

### `metadata.rephrase`

A response may opt into being reworded by the LLM instead of delivered verbatim:

```yaml theme={null}
responses:
  utter_ask_shipping:
    - text: "Rush or standard shipping?"
      metadata:
        rephrase: true
```

With `rephrase: true` the orchestrator makes a tool-free LLM call to reword the
**selected** variant's text in context, and falls back to the literal text if
that call fails or comes back empty. Leave it off (the default) for anything
compliance-sensitive: that is the entire point of declaring the response.

## How a response is delivered

Four things reference a response by name:

| Reference | Where it is declared | Delivered when |
| - | - | - |
| `utter:` trigger | `skill.md` frontmatter | The skill activates (`on: activate`), or a `when:` condition first becomes true |
| `on_success:` / `on_failure:` | A `tool_constraints` entry | After that tool succeeds or fails |
| `utter_for_confirmation` / `utter_on_user_denial` | A `requires_confirmation:` mapping | When the engine asks for approval, and when the customer declines |
| `action:` / `utterance:` | An ordered-block step | The step runs |

The two step fields differ:

```yaml theme={null}
:::ordered_block id=main
steps:
  - id: present_cards
    action: utter_present_card_list      # deliver the response, then advance
    next: collect_card

  - id: collect_card
    collect: selected_card_label
    utterance: utter_ask_which_card      # the question for a collect step
:::
```

| Step field | Use |
| - | - |
| `action: utter_<name>` | Deliver the response, then advance |
| `utterance: utter_<name>` | On a `collect:` step, the question asked for that value |

`utter:` is accepted as a step-level alias for `action:` and is normalised at
load. Prefer `action:`.

`rasa train` validates every response name referenced from any of the four
places above, and runs per-variant checks on project-authored `responses.yml`
files (non-empty text, valid conditions, default-variant rules). A name that is
not in the registry, or a malformed variant list, is caught before the agent
runs.

## See also

* [Responses concept](https://rasa.com/docs/mantle/concepts/responses.md): when to declare wording
* [skill.md](https://rasa.com/docs/mantle/reference/skill-md.md): the `utter:` trigger and `tool_constraints` shapes
* [Ordered block steps](https://rasa.com/docs/mantle/reference/ordered-block-steps.md): the step fields that deliver responses
* [Conditions](https://rasa.com/docs/mantle/reference/conditions.md): the namespaced reference form


## Related topics

- [Responses](https://rasa.com/docs/mantle/concepts/responses.md)
- [Hooks](https://rasa.com/docs/mantle/reference/hooks.md)
- [skill.md](https://rasa.com/docs/mantle/reference/skill-md.md)
- [Tool Constraints](https://rasa.com/docs/mantle/build-guide/tool-constraints.md)


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