Six changes, and every one of them was a place where the framework enforces something rather than asking the model nicely.
| Technique | What it guarantees |
|---|---|
| Override a bundled skill | your version wins, by id |
| Ordered block | lookup runs before the greeting |
| Project memory, not LLM-settable | facts come from the tool, never invented |
| Private skill memory | the model cannot see it at all |
| Response template | you choose what is said |
rephrase: true |
the model improves wording, not facts |
| Scoped instruction | only the relevant branch is visible |
These are control levers. The alternative — describing all of it in natural language and trusting the model — reads beautifully and works most of the time, which is the problem. “Most of the time” is not a property you can put in front of customers.
Rasa ran the same agent two ways over roughly 100 simulated conversations: once written entirely as prose, once with the levers. The version with levers completed about 30% more tasks. That report is not published yet, so treat the number as directional rather than as a citation — but the direction matches what the technique is for.
A cheaper habit
From the same session, and it costs nothing: number your steps.
A numbered list reads to a model as a sequence that cannot be skipped. The same content as a paragraph reads as advice. When you have not yet reached for a control lever, numbering is the smallest thing that improves reliability.
Evaluating this yourself
rasa init drops six agent-building skills into your project, one of which is
mantle_simulating_and_evaluating. Point a coding agent at it, ask for
simulation scenarios, run them, and judge the transcripts with an LLM. That loop
— build, simulate, evaluate, fix — is how you find out whether a change helped
rather than assuming it did.
If you are coming from 3.19
This tutorial is written against 3.20.0.dev1, where the engine package is
rasa.mantle. On 3.19.x it was rasa.calm_v2, and the old path is now gone
rather than aliased — a breaking change for any custom tool.
For this pattern the migration is exactly two edits:
# 1. the pin
rasa-pro==3.19.0.dev7 → rasa-pro==3.20.0.dev1 # rasa-version-ignore: upgrade target
# 2. the imports, in every tools.py
from rasa.calm_v2.tools.decorator import ToolContext, tool
from rasa.calm_v2.tools.result import ToolResult
↓
from rasa.mantle.tools.decorator import ToolContext, tool
from rasa.mantle.tools.result import ToolResult
One more thing that is easy to miss: 3.20.0.dev1 also raises the Python
floor from 3.10 to 3.11. A pyproject.toml that still says
requires-python = ">=3.10,…" fails uv lock with a resolver error that never
mentions Python.
Nothing else changes. Not the ordered block, not the response template, not the scoped instructions. The pattern trains and greets identically on both releases.
If you have a larger agent, point a coding agent at the Mantle change log and let it do the rename — that is what the Rasa team recommends, and it is a mechanical change.
Where to go next
- Tool scope and memory scope — when a tool should be local to a skill and when it should be global, and the public and private halves of skill memory
- The session-start personalization pattern in the community resources repository, with a guided walkthrough alongside it
- Rasa community office hours, weekly — this tutorial came out of one
