Requirements
Before getting started, make sure that you’ve already:What are you building?
In this tutorial, you will build an LLM-powered assistant that can complete a money transfer, reliably executing your business logic while allowing for fluid conversation. Here are some of the conversations your assistant will be able to handle after you define the money transfer process:- Happy path
- All at once
- Change of mind
User: I want to send moneyBot: Who would you like to send money to?User: to JenBot: How much would you like to send?User: $50Bot:Please confirm: you want to transfer $50.0 to Jen?User: yesBot: All done. $50.0 has been sent to Jen.Bot: Is there anything else I can help you with?!happy path
Following This Tutorial
You’ll need a free Rasa Developer Edition license This tutorial contains a mix of explanations and instructions. Whenever there are instructions you need to follow, you’ll see this ‘Action Required’ label: Action Required This assistant is powered by an LLM that we fine-tuned and uploaded to huggingface. For convenience, this tutorial will use a deployment that we host and make available for users working through the tutorial. If you prefer not to use a third-party API, you can run this model yourself. or use another LLMSetup
Action Required For new users, the easiest way to get started is the Developer Quickstart — get a license, install Rasa Pro, and set up MCP in your IDE. You can also install Rasa Pro locally and use your own machine. To code along with this tutorial, navigate to an empty directory in your terminal, and run:- Linux/MacOS
- Windows
your-rasa-license-key with the your actual license key.
Overview
Open up the project folder in your IDE to see the files that make up your new project. In this tutorial you will primarily work with the following files:data/flows.ymldomain.ymlactions/actions.py
Testing your money transfer flow
Action Required Train your assistant by running:When you run the 
rasa inspect command in a GitHub Codespace, you’ll see a notification
that your application is available on port 5005.
Click ‘Open in Browser’ to access the inspector and start chatting.
This template bot responds to chitchat by generating a response.
If you want to disable this, delete the file
data/patterns.yml and re-train.Understanding your money transfer flow
The filedata/flows.yml contains the definition of a flow called transfer_money.
Let’s look at this definition to see what is going on:
flows.yml
transfer_money flow are the description and the steps.
The description is used to help decide when to activate this flow.
But it is also helpful for anyone who inspects your code to understand what is going on.
If a user says “I need to transfer some money”, the description helps Rasa understand that this is the relevant flow.
The steps describe the business logic required to do what the user asked for.
The first step in your flow is a collect step, which is used to fill a slot.
A collect step sends a message to the user requesting information, and waits for an answer.
Collecting Information in Slots
Slots are variables that your assistant can read and write throughout a conversation.
Slots are defined in your domain.yml file. For example, the definition of your recipient slot looks like this:
domain.yml
collect step like the first step in your flow above.
flows.yml
response called utter_ask_recipient in your domain file and use this to
phrase the question to the user.
domain.yml
recipient.
Read about slot validation to learn how you
can run extra checks on the slot values Rasa has extracted.
The diagram below summarizes how slot values are used to collect and store information,
and how they can be used to create branching logic.

Descriptions in collect steps
The secondcollect step includes a description of the information your assistant
will request from the user.
Descriptions are optional, but can help Rasa extract slot values more reliably.
flows.yml
Action Steps
The thirdstep in your transfer_money flow is not a collect step but an action step.
When you reach an action step in a flow, your assistant will execute the corresponding action and then
proceed to the next step.
It will not stop to wait for the user’s next message.
For now, this is the final step in the flow, so there is no next step to execute and the flow completes.
flows.yml
Branching Logic
Slots are also used to build branching logic in flows. Action Required You’re going to introduce an extra step to your flow, asking the user to confirm the amount and the recipient before sending the transfer. Since you are asking a yes/no question, you can store the result in a booleanslot
which you will call final_confirmation.
In your domain file, add the definition of the final_confirmation slot
and the corresponding response: utter_ask_final_confirmation.
Also add a response to confirm the transfer has been cancelled.
domain.yml
domain.yml
{} to include slot values in your response.
Add a collect step to your flow for the slot final_confirmation.
This step includes a next attribute with your branching logic.
The expression after the if key will be evaluated to true or false to determine
the next step in your flow.
The then and else keys can contain either a list of steps or the id of a step
to jump to.
In this case, the then key contains an action step to inform the user their transfer
was cancelled. The else key contains the id transfer_successful.
Notice that you’ve added this id to the final step in your flow.
flows.yml
rasa train, and then rasa inspect to talk to your assistant.
It should now ask you to confirm before completing the transfer.
Integrating an API call
Anaction step in a flow can describe two types of actions.
If the name of the action starts with utter_, then this action sends a message to the user.
The name of the action has to match the name of one of the responses defined in your domain.
The final step in your flow contains the action utter_transfer_complete, and this response is
also defined in your domain. Responses can contain buttons, images, and custom payloads.
You can learn more about everything you can do with responses here.
The second type of action is a custom action. The name of a custom action starts with action_.
You are going to create a custom action, action_check_sufficient_funds, to check whether the
user has enough money to make the transfer, and then add logic to your flow to handle both cases.
Your custom action is defined in the file actions/actions.py.
To learn more about custom actions, go here.
Your actions.py file should look like this:
actions.py
run() method above, you access the value of the amount slot that was set during the conversation,
and you pass information back to the conversation by returning a SlotSet event to update the has_sufficient_funds slot.

domain.yml.
You will add a top-level section listing your custom actions.
You will add the new boolean slot has_sufficient_funds, and you will
add a new response to send to the user in case they do not have sufficient funds.
domain.yml
collect: final_confirmation step now also has an id so that your branching logic
can jump to it.
flows.yml
Testing your Custom Action
Action Required Double check that in the fileendpoints.yml, that the section for your custom action server is uncommented:
endpoints.yml
rasa inspect.
When you reach the "check_funds" step in your flow, Rasa will call the custom action action_check_sufficient_funds.
We have hardcoded the user’s balance to be 1000, so if you try to send more, the assistant will tell you that
you don’t have enough funds in your account.
At this point you have experience using some of the key concepts involved in building with Rasa.
Congratulations!
Adding Voice to Your Assistant
Now that you’ve built a text-based assistant that handles money transfers, let’s expand its capabilities to support voice interactions. Here’s a demo of what you’ll be building,What You’ll Need for Voice
To enable voice capabilities, you’ll need:- An API key from Deepgram for both speech recognition and speech synthesis.
Setting Up Your Voice Assistant
Action Required Configure your speech service API keys:- Linux/MacOS
- Windows
Testing Your Voice Assistant
Action Required To test your voice assistant in the browser, launch the Inspector as usual:Next Steps
Now you are ready to apply what you’ve learned to building your own assistant.- Create a new project by running:
- Choose which LLM you want to use. This tutorial used an LLM that Rasa fine-tuned for this use case.
For new projects created with
rasa init --template calm, Rasa defaults to a general-purpose OpenAI chat model (gpt-5.1-2025-11-13) that doesn’t require fine-tuning. You can configure which LLM to use by editing the config.yml file in your project. When you’re ready, you can fine-tune your own model. - Start writing your own flows and custom actions.