Skip to main content
In this tutorial you build a card replacement skill, talk to it in the Inspector, and then make it sound right on a call. Each step adds one change and explains what the caller hears differently. You start from the project that rasa init --engine mantle creates. If you have not made one yet, follow Getting Started up to step 3, and configure the Inspector’s speech providers as in step 3. Keep the generated model_groups configuration: the speech keys do not replace your LLM provider key or Rasa license. Restart the Inspector after changing integrations.yml or your environment.
The card data and order operation below are mocks. They do not authenticate a caller, lock a real card, or place a real order. Before connecting a card API, add authorization and retry protection in your tools.

What you’ll build

A skill that:
  • greets the caller with a recording notice,
  • finds the card from its last four digits,
  • locks a stolen card straight away,
  • confirms the order out loud before placing it,
  • reads the order number back digit by digit.
The skill also keeps working in chat, unchanged.

1. Write the skill

Create skills/card_replace/ with three files. The instructions are plain prose with no voice-specific wording:
skills/card_replace/skill.md
The memory the skill tracks. The model records the reason and shipping choice; the tools write the rest:
skills/card_replace/memory.yml
And the tools, with mock data in place of a card API:
skills/card_replace/tools.py
Train and open the Inspector:
Select Start voice conversation and say My card was stolen. Give the last four digits as four eight two one. Listen for what Mantle already does on a call. The replies are short and spoken, with no lists or formatting. You hear a brief acknowledgement while find_card runs. If you talk over the agent, it stops and listens. What is still missing: the agent says nothing until you speak, and the order goes through without the caller agreeing to it.

2. Greet the caller

A caller expects to hear the agent first. The bundled session-start skill stays silent, so replace it with one that plays a recording notice and a greeting. Voice channels start every call with /session_start, which runs this skill:
skills/default_session_start/skill.md
skills/default_session_start/responses.yml
The notice is a response, so it is spoken exactly as written every time. See Start a conversation for how session start works.

3. Give the pauses your agent’s voice

The acknowledgement you heard in step 1 is generated by the model. Give it a few examples in your agent’s tone so it sounds like your brand rather than a generic agent. Add a fillers block to agent.yml:
agent.yml
Acknowledgements are on for voice and off for chat by default, so this only changes what callers hear. See fillers.

4. Confirm before placing the order

On chat, the customer can scroll back and check what they agreed to. On a call, they hear it once. Make the engine ask for a spoken yes before the order goes through, and have the question restate what is being ordered. Add tool_constraints to the skill frontmatter, and change step 5 of the prose so the model calls the tool and leaves the asking to the engine:
skills/card_replace/skill.md
Then add the wording:
skills/card_replace/responses.yml
What changed:
  • requires: keeps each tool unavailable until its facts exist, so the model cannot lock a card that was not stolen or order before shipping is chosen.
  • requires_confirmation: pauses the order and asks utter_confirm_order. The tool runs on a yes and is cancelled on a no. See Explicit confirmations.
  • on_success: speaks the lock and order lines exactly as written.
  • complete_when: finishes the skill once an order number exists.

5. Read the order number back clearly

Read aloud, 482193 can come out as “four hundred eighty-two thousand…”. The process_card_replacement tool already stores a second, spaced-out copy in order_reference_spoken (“4 8 2 1 9 3”), and utter_order_placed uses that copy, so the caller hears one digit at a time. The plain order_reference stays available for your systems and for chat. Speech providers differ in how they read numbers, so listen to your own identifiers in the Inspector. For more on exact wording, see Use a response when the words have to be exact.

6. Make the order safe to interrupt

A caller can talk over the agent while process_card_replacement is waiting on your card system. When Mantle accepts the interruption, it ends the turn and cancels the tool at its current await. Check context.is_cancelled right before starting an irreversible step:
skills/card_replace/tools.py
This check does not undo an order that your card system has already accepted. A tool cancelled during an await can run again on the next turn. For a real order API, keep a stable idempotency key for that order attempt and use it to reconcile an uncertain result before retrying. Do not treat a saved key as proof that the order succeeded. See Cancellation.

7. Say goodbye once

When the caller says they are done, the agent should close the call, not ask another question. Add a rule to agent.yml:
agent.yml
If the caller goes quiet instead, the bundled silence-timeout skill checks in three times, then says goodbye and hangs up. See Silence timeout to change that wording.

8. Try it

Train, restart the Inspector, and start a new voice conversation:
  1. You hear the recording notice and the greeting.
  2. Say My card was stolen, then four eight two one. The card is locked and you hear the exact lock message.
  3. Choose rush shipping. The agent restates the card and shipping and asks whether to go ahead.
  4. Say yes. You hear the order number one digit at a time.
  5. Say That’s all, thanks. The agent says goodbye once.
Also try no at the confirmation, an unknown card number, and a correction after you choose shipping. Check the tool events and memory, not only the spoken reply: a denied order must not call process_card_replacement. Repeat yes and no as short answers, then interrupt while the mock order tool is waiting. See Test the speech path separately for a reusable test checklist. Now type the same conversation in the chat box. The skill is unchanged, and the replies take the shape of text instead.

Continue with a community project

To apply these patterns across several skills, follow the Rasa Community travel-agent tutorial. The runnable companion project includes demo data and setup instructions; its chapter snippets show how each step changes the project. These links leave the Mantle docs: the walkthrough is on rasa.community, and the code is in the public rasa-community-resources repository. Check their tested versions before adapting them to your project.

Next steps

Connect a phone line

Put this agent behind a real phone number.

Designing for voice

More patterns: lists, buttons, keypad input, and ending calls.

Speech providers

Change the recognition model, the voice, or the provider.

Test and monitor voice

Check latency and interruptions before and after launch.