Writing a chatbot with Rasa

Chat bot

Chatbots have seen a massive increase in popularity in the last year or two. One could say that they have grown with the Covid-19 pandemic, but sure enough vaccines will not affect chatbots. Every second user says they enjoy getting quick responses to simple questions from a chatbot. Microsoft Bot Framework by Microsoft, Dialogflow powered by Google, IBM Watson by IBM as some of the frameworks by the Big Tech. Rasa is an open-source framework that enables building of powerful chatbots.

This post is about building a chatbot with Rasa that does a little more than basic interaction covered in most tutorials.

Before this post goes any further here is the Github repo where the code samples are based upon.

Rasa, how it works

A simple Rasa chat bot consists of intents, (custom) actions and stories.

An intent is simply said, what the user might say(write) and the bot understands. There could be multiple phrasings of the same intent. For instance: intent greet can have phrases of: hi; hello; moin;. The intent translate can have phrases of: translate; translate please; can you translate for me this please;…etc. Rasa is smart to recognize typos and correctly user's input to the proper intent.

A action is what the bot is designed to do when a certain intent is recognized. These can be a predefined response, e.g: respond with 'Goodbye!', or in more advanced and complex situations, trigger a custom action that can perform practically anything programmable in Python.

Finally, a story is a sequence of intents and actions, which are called steps, that samples and interaction between the bot and the user. A classic example is the one provided almost in every tutorial. Here a story happy path consists of the given steps. However, Rasa wants to depricate stories altogether, and that would be an exciting upgrade to keep an eye on.

A chat bot, in order to be helpful and relevant, needs to collect pieces of information from the user and perform actions based on/using this information. Rasa has tackled this problem with forms. A form could look like this:

Custom Actions are the space where the chat bot can run any code the developers/team needs to. This could be validation of the input coming from the user, calling an API, or querying a database to name a few options.

Some gotchas that might be helpful are:

  • custom actions need to have the name starting with the keyword action
  • a form validation custom action needs its name to start with validate followed by the forms name

There are also some other framework specifics like this, that can be found in Rasa's documentation.

Note: To use the custom actions defined, make sure to start the action server before with the command $ rasa run actions. To deploy the action server, Github actions can be used as described in Rasa deployment help.

How everything falls in place together

In order to understand how everything falls in place, here is a human-readable explanation.

  1. All the intents the chat bot should be able to recognize (Natural Language Understanding) go into data/nlu.yml file.
  2. All the foreseen interaction between user and chat bot are described as stories in data/stories.yml file.
  3. Base interactions between chat bot and user go into data/rules.yml file. Also rules.yml deals with forms, activating them when user provides the information, and marking them complete when all the information required is filled.
  4. Use actions/actions.py to define custom actions. Add in there validation of form fields, API calls or database queries that the chat bot is expected to perform.
  5. Finally, domain.yml brings everything together. Intents, forms, actions and custom actions, and predefined responses of the chat bot.

The project

The idea of this project is to help users translate a sentence or phrase to another language.

To achieve this goal first two intents are defined in data/nlu.yml. These intents are used to recognize when the user is providing a phrase to translate, and when they are asking for the translation.

- intent: request_translate 
examples: |
— translate
— translate for me please
— can you translate — translate?
— intent: return_translate
examples: |
— give translate
— give translate please

Second in the domain.yml will need to define a form with properties that need to be extracted from the input:

— type: from_text
— type: from_text
— type: from_text
type: text
type: text
type: text

Next in the data/rules.yml will define when to activate the from to fill the data from user's input, and it looks like this:

- rule: Activate translate form
- intent: request_translate
- action: translate_form
- active_loop: translate_form - rule: Submit translate form
- active_loop: translate_form
- action: translate_form
- active_loop: null
- slot_was_set:
- requested_slot: null
- action: utter_slots_values_translate

The first rule is activating the form when intent request_translate is recognized by Rasa NLU, and it start to loop for user input. The second rule, gets triggered to stops the loop of the first rule when all the properties of the form are filled. A fun fact, the chat bot can be instructed on what to ask the user for every property of the form. Check out the code here.

Finally, custom actions are defined to perform the tasks.


In this action, the code is not performing a translation, but instead calling Chuck Norris Api to get a joke and return it to the user. The translation is still a work in progress, as it is part of a larger project.


Overall after putting some effort in creating a chat bot that is a little more advanced than what is explained in basic tutorials, I believe that there is still a lot to be done. It is delightful to see the bot perform the desired actions, but the developer experience still struggles. In the case of Rasa there is quite some 'framework magic' happening, that is hidden behind a black box. E.g: custom actions and form validation.

Also, I gave up on trying to deploy the chatbot in AWS since the amount of resources required is just too much. Rasa team has done an amazing job at creating helm charts that help a lot in this sense 👏, but I struggled to bring everything together and deploy.

I hope you found some value in this post. Feel free to reach out for any question or comment. I would be happy to hear from you!

Happy coding!


Connect with me:

LinkedIn or Github



Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store