May 21st, 2025
Architecting Rasa Assistants: Why Business Logic Should Live in Flows, Not Custom Action
Soham Chatterjee
Marina Ashurkina
In Rasa, flows outline the steps your assistant follows to collect the necessary information from users and APIs to complete a task, including decision points for handling different scenarios.
Flows manage dialogue structure, conditions, and responses (based on user inputs, slots, or other context) using a visual or YAML-based format. Designed for clarity and collaboration, flows are transparent, easy to edit, and accessible to technical and non-technical team members through tools like Rasa Studio.
On the other hand, custom actions are Python functions that allow the assistant to perform operations beyond dialogue management, such as API calls, querying databases, or executing other backend logic. Custom actions are triggered from flows and can set slot values or return other data to the assistant.
Best practice is to keep business logic within flows to ensure the maintainability, scalability, and collaborative development of your Rasa assistant.
Here are a few reasons why logic should be in flows and not custom actions:
-
Single Source of Truth: If business logic is kept in flows, it creates a centralized place for all decision-making processes and makes your assistant easier to understand and maintain. Tracking the overall conversation flow becomes harder when logic is scattered across custom actions.
-
Improved Collaboration: Flow-based logic is more accessible to non-technical team members, especially when conversation designers and testers use Studio. Teammates who work primarily with the Studio UI can understand what's going on and modify it.
-
Visibility and Auditability: Business logic in flows is explicit and auditable, rather than being in the parameters of a model or hidden in custom action code.
-
Maintainability Issues: Some of our customers have said it helps, especially when you have lots of logic for different use cases embedded inside custom actions. Having your logic in flows reduces maintenance challenges.
So, custom actions should primarily:
- Perform operations (DO something/write data)
- Retrieve information from APIs
- Set/return data as slot values
The branching logic based on those slot values should live in your flows, not the custom actions themselves.
For example, instead of having logic in a custom action like:
class MyCustomAction(Action):
def name():
return "my_custom_action"
def run():
if X:
dispatcher.utter("X is true")
else:
dispatcher.utter("X is false")
Move this logic into your flow:
flows:
my_flow:
description: do stuff
steps:
- action: utter_something
next:
- if: slots.X
- action: utter_x_is_true
- else:
- action: utter_x_is_false
Here is what this flow will look like in Rasa Studio:
This approach ensures that technical and non-technical team members working on your assistant can manage your business logic.
To dive deeper into flows, check out the Rasa documentation or watch this video:
Ready to get started?
You can build flows directly in your Rasa project’s YAML files or experiment with creating them visually inside Rasa Studio.
If you want to explore Studio, you can request a free Rasa Studio trial here.