Skip to content

tutorial

Chapter 5 of 5

Chapter 5 — Control levers, and upgrading to 3.20

by Rod Rivera Published

Why these techniques beat plain prose instructions, plus the two-line migration to the renamed Mantle engine package.

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