The Rasa Starter Pack for Retail Banking is an example project that demonstrates how to build a conversational assistant for banking services using Rasa. This assistant can help users transfer money, check balances, manage payees, and block cards. For each agent, Rasa needs to define every variable that needs to be collected, as well as the complete flow process. I will elaborate on this in detail below.
We have successfully implemented the same features of this Rasa example using MICA. You can find the complete implementation here, or use our provided visual interface to load and test it directly. Below, we outline key features from the repository and compare our implementation with MICA, highlighting how MICA simplifies the process compared to Rasa’s more complex setup.
Feature Comparison
1. Money Transfer
This function requires the user to first verify whether the payee exists, then collect a series of variables, and finally complete the transfer. In MICA, you can use the following LLM agent to implement this process. Here is a part of agents.yml
:
transfer_money:
type: llm agent
description: Guides the user through the process of initiating a bank transfer.
prompt: |
1. First, confirm that you understand the user wants to transfer money.
2. Ask for the username. Based on the username, call the function “action_ask_account_from” to display the account name and balance. Ask which account to use and fill in account_from with the corresponding number (do not show the account number to the user, just populate account_from directly).
3. Ask for payee_name. Using account_from and payee_name, call the function “action_check_payee_existence”.
4a. If the payee does not exist, prompt the user to enter the “add payee” agent and exit this agent.
4b. If the payee exists, continue collecting the transfer amount amount. If amount ≤ 0, prompt that the amount is invalid.
5. Once all required details are collected, call “action_check_sufficient_funds”.
6a. If there are sufficient funds, proceed to step 7.
6b. If there are insufficient funds, terminate this agent immediately.
7. Collect the transfer timing timing.
8a. If timing is “now”, confirm whether to proceed with the immediate transfer.
• If confirmed, call “action_process_immediate_payment”, then output “Transfer successful”, and exit this agent.
• If not proceeding immediately, output “Transfer canceled”, and exit this agent.
8b. If timing is not “now”, ask for the specific transfer date, ensuring it is formatted as “DD/MM/YYYY”. Proceed to step 9.
9. Call “action_validate_payment_date”.
• If the date is a future date, confirm whether to schedule the transfer.
• If confirmed, call “action_schedule_payment”, output “Transfer scheduled”, and exit this agent.
• If not scheduling, output “Transfer canceled”, and exit this agent.
args:
- username
- account_from
- payee_name
- amount
- timing
- payment_date
uses:
- action_check_payee_existence
- action_check_sufficient_funds
- action_process_immediate_payment
- action_validate_payment_date
- action_schedule_payment
You also need to implement all the Python functions mentioned in the uses
field in tools.py
. Here, action_check_payee_existence
is used as an example.
def action_check_payee_existence(username, payee_name):
db = Database()
user_query = "SELECT id FROM users WHERE name = ?"
user_result = db.run_query(user_query, (username,), one_record=True)
if user_result is None:
print("The user does not exist.")
return
user_id = user_result[0]
check_payee_query = "SELECT id FROM payees WHERE user_id = ? AND name = ?"
payee_result = db.run_query(
check_payee_query, (user_id, payee_name), one_record=True
)
if payee_result:
print("The payee exists.")
return
print("The payee does not exist.")
return [{"text": f"{payee_name} is not an authorised payee. Let's add them!"}]
Show the RASA Implementation
flows:
transfer_money:
description: Guides the user through the process of initiating a bank transfer.
steps:
- action: utter_transfer_money_understand
- collect: account_from
- collect: payee_name
- action: action_check_payee_existence
next:
- if: not slots.payee_exists
then:
- call: add_payee
next: "get_transfer_amount"
- else: "get_transfer_amount"
- id: "get_transfer_amount"
collect: amount
description: The amount of money to transfer
rejections:
- if: slots.amount <= 0
utter: utter_invalid_amount
- action: action_check_sufficient_funds
next:
- if: slots.sufficient_funds
then: "get_payment_timing"
- else:
- action: utter_insufficient_funds
next: END
- id: "get_payment_timing"
collect: timing
next:
- if: slots.timing == "now"
then: "confirm_immediate_transfer"
- else: "get_payment_date"
- id: "confirm_immediate_transfer"
collect: confirm_immediate_payment
ask_before_filling: true
next:
- if: slots.confirm_immediate_payment
then:
- action: action_process_immediate_payment
- action: utter_transfer_successful
next: END
- else: "transfer_cancelled"
- id: "get_payment_date"
collect: payment_date
description: the future payment date of the money transfer. Convert date to DD/MM/YYYY format
- action: action_validate_payment_date
next:
- if: slots.future_payment_date
then: "confirm_future_payment"
- else:
- action: utter_past_payment_date
- set_slots:
- payment_date: null
next: "get_payment_date"
- id: "confirm_future_payment"
collect: confirm_future_payment
ask_before_filling: true
next:
- if: slots.confirm_future_payment
then:
- action: action_schedule_payment
- action: utter_payment_scheduled
next: END
- else: "transfer_cancelled"
- id: "transfer_cancelled"
action: utter_cancel_transfer
slots:
account_from:
type: text
payee_name:
type: text
payee_exists:
type: bool
amount:
type: float
sufficient_funds:
type: bool
timing:
type: categorical
values:
- now
- future
payment_date:
type: text
confirm_immediate_payment:
type: bool
confirm_future_payment:
type: bool
payment_processed:
type: bool
payment_scheduled:
type: bool
valid_payment_date:
type: bool
future_payment_date:
type: bool
responses:
utter_transfer_money_understand:
- text: "Okay lets transfer money"
metadata:
rephrase: True
utter_ask_payee_name:
- text: "Which payee would you like to send money to?"
utter_ask_amount:
- text: "How much money would you like to transfer?"
utter_insufficient_funds:
- text: "I'm sorry, but you have insufficient funds for this transfer. Please enter a different amount"
utter_ask_timing:
- text: "When would you like this transfer to be made?"
buttons:
- title: Immediate
payload: "/SetSlots(timing=now)"
- title: Future
payload: "/SetSlots(timing=future)"
utter_ask_payment_date:
- text: "On which date would you like this payment to be made?"
utter_ask_confirm_future_payment:
- text: "A payment of ${amount} to {payee_name} will be scheduled for {payment_date}. Is this correct?"
utter_payment_scheduled:
- text: "Your payment of ${amount} to {payee_name} has been successfully scheduled for {payment_date}"
utter_ask_confirm_immediate_payment:
- text: "An immediate payment of ${amount} to {payee_name} will be processed. Is this correct?"
utter_transfer_successful:
- text: "Your transfer of ${amount} to {payee_name} has been successfully processed"
utter_cancel_transfer:
- text: "No problem. I will cancel this transfer"
utter_invalid_amount:
- text: "You have to enter an amount greater than 0"
metadata:
rephrase: True
utter_past_payment_date:
- text: "A future payment date cannot be in the past!"
metadata:
rephrase: True
actions:
- action_ask_account_from
- action_check_payee_existence
- action_check_sufficient_funds
- action_schedule_payment
- action_process_immediate_payment
- action_validate_payment_date
2. Card Blocking
When a user requests to block a card, it is necessary to ask for the reason and adopt different response strategies based on the given reason. Here is our LLM agent design for handling this process.
block_card:
type: llm agent
description: ask for reason and block the card
prompt: |
You are an agent assisting users in blocking their cards.
1. Based on the username, directly call "action_ask_card" to retrieve the user's available cards. Ask the user:
"Select the card you require assistance with:" and fill in the "card" field.
2. Ask the user for the reason they want to block the card (reason_for_blocking):
- The reason should be described as lost, damaged, stolen, suspected of fraud, malfunctioning, or expired.
- The user may also say they are traveling or moving, or that they want to temporarily freeze their card.
- For any other responses, set the "reason_for_blocking" slot to "unknown".
3a. If "reason_for_blocking" is "damaged" or "expired", inform the user:
"Thank you for letting us know. I'm sorry to hear the card was {reason_for_blocking}."
Proceed to Step 4.
3b. If "reason_for_blocking" is "fraud", "stolen", or "lost", inform the user:
"As your card was potentially stolen, it's crucial to report this incident to the authorities. Please contact your local law enforcement agency immediately."
Proceed to Step 4.
3c. If "reason_for_blocking" is "traveling" or "moving", inform the user:
"Thanks for informing us about moving."
Proceed to Step 4.
3d. For all other cases, instruct the user to contact "020 7777 7777" and call the function "action_update_card_status", then end the agent process.
4. Inform the user that their card will be blocked due to the specified reason.
- Confirm whether they want to **issue a new card** or if they prefer to visit the bank themselves.
- If the user confirms they want to issue a new card, proceed to Step 5.
- If the user declines, call "action_update_card_status" and end the agent process.
5. Confirm the user's "physical_address".
- If the user confirms the address is correct, inform them:
"The new card will be sent to this address."
- If the user indicates the address is incorrect, go back to Step 3d.
args:
- username
- card
- physical_address
- reason_for_blocking
uses:
- action_ask_card
- action_update_card_status
Show the RASA Implementation
flows:
block_card:
description: "Block or freeze a user's debit or credit card to prevent unauthorized use, stop transactions, or report it lost, stolen, damaged, or misplaced for added security"
name: block a card
steps:
- action: utter_block_card_understand
- call: select_card
- collect: reason_for_blocking
description: |
The reason for freezing or blocking the card, described as lost, damaged, stolen, suspected of fraud,
malfunctioning, or expired. The user may say they are traveling or moving, or they may say they want to
temporarily freeze their card. For all other responses, set reason_for_blocking slot to 'unknown'.
next:
- if: "slots.reason_for_blocking == 'damaged' or slots.reason_for_blocking == 'expired'"
then: "acknowledge_reason_damaged_expired"
- if: "slots.reason_for_blocking == 'fraud' or slots.reason_for_blocking == 'stolen' or slots.reason_for_blocking == 'lost'"
then:
- set_slots:
- fraud_reported: true
next: "acknowledge_reason_fraud_stolen_lost"
- if: "slots.reason_for_blocking == 'traveling' or slots.reason_for_blocking == 'moving'"
then:
- set_slots:
- temp_block_card: true
next: "acknowledge_reason_travelling_moving"
- else: "contact_support"
- id: acknowledge_reason_damaged_expired
action: utter_acknowledge_reason_damaged_expired
next: "confirm_issue_new_card"
- id: acknowledge_reason_fraud_stolen_lost
action: utter_acknowledge_reason_fraud_stolen_lost
next: "card_blocked"
- id: acknowledge_reason_travelling_moving
action: utter_acknowledge_reason_travelling_moving
next: "card_blocked"
- id: "card_blocked"
action: "utter_card_blocked"
next: "confirm_issue_new_card"
- id: "confirm_issue_new_card"
collect: confirm_issue_new_card
description: |
Confirm if the user wants to be issued a new card. The answer should be an affirmative statement,
such as "yes" or "correct," or a declined statement, such as "no" or "I don't want to"
ask_before_filling: true
next:
- if: "slots.confirm_issue_new_card"
then: "retrieve_user_address"
- else: "update_card_status"
- id: "retrieve_user_address"
collect: address_confirmed
description: |
Confirm if the given address is correct. The answer should be an affirmative statement, such as "yes" or
"correct," or a declined statement, such as "no" or "that's not right."
next:
- if: "slots.address_confirmed"
then: "card_sent"
- else: "contact_support"
- id: "card_sent"
action: utter_confirm_physical_address
next: update_card_status
- id: "contact_support"
action: utter_contact_support
next: update_card_status
- id: "update_card_status"
action: action_update_card_status
next: END
slots:
reason_for_blocking:
type: categorical
values:
- lost
- fraud
- stolen
- damaged
- expired
- traveling
- moving
address_confirmed:
type: bool
fraud_reported:
type: bool
initial_value: false
temp_block_card:
type: bool
initial_value: false
confirm_issue_new_card:
type: bool
address:
type: text
card_status:
type: categorical
values:
- active
- inactive
actions:
- action_update_card_status
responses:
utter_ask_reason_for_blocking:
- text: "Please tell us the reason for blocking"
buttons:
- title: "I lost my card"
payload: "/SetSlots(reason_for_blocking=lost)"
- title: "My card is damaged"
payload: "/SetSlots(reason_for_blocking=damaged)"
- title: "I suspect fraud on my account"
payload: "/SetSlots(reason_for_blocking=fraud)"
- title: "My card has expired"
payload: "/SetSlots(reason_for_blocking=expired)"
- title: "I'm planning to travel soon"
payload: "/SetSlots(reason_for_blocking=traveling)"
- title: "I'm moving to a new address"
payload: "/SetSlots(reason_for_blocking=moving)"
utter_block_card_understand:
- text: "Okay, we can block a card. Let's do it in a few steps"
metadata:
rephrase: True
utter_ask_address_confirmed:
- text: "I have found your address: {physical_address}. Should the new card be delivered there?"
buttons:
- title: "Yes"
payload: "/SetSlots(address_confirmed=True)"
- title: "No"
payload: "/SetSlots(address_confirmed=False)"
utter_confirm_physical_address:
- text: "Your card will be delivered to {physical_address} within 7 business days"
utter_card_blocked:
- condition:
- type: slot
name: fraud_reported
value: true
text: "Since you have reported {reason_for_blocking}, we will block your card"
- condition:
- type: slot
name: temp_block_card
value: true
text: "Since you are {reason_for_blocking}, we will temporarily block your card."
- text: We will block your card.
utter_ask_confirm_issue_new_card:
- text: "Would you like to be issued a new card?"
buttons:
- title: "Yes, send me a new card"
payload: "/SetSlots(confirm_issue_new_card=true)"
- title: "No, just block my card"
payload: "/SetSlots(confirm_issue_new_card=false)"
utter_ask_address:
- text: "Would you like us to deliver your new card to this address: {physical_address}?"
buttons:
- title: "Yes, send a new card"
payload: "/SetSlots(address_confirmed=true)"
- title: "No, I'll go to the bank"
payload: "/SetSlots(address_confirmed=false)"
utter_contact_support:
- text: "Should you require further assistance, please contact our support team at 020 7777 7777. Thank you for being a valued customer."
- text: "If you have any questions or concerns, please don't hesitate to reach out to our support team at 020 7777 7777. We're here to help."
- text: "For additional support, please contact our customer service team at 020 7777 7777. Thank you for being a valued customer."
utter_acknowledge_reason_damaged_expired:
- text: "Thank you for letting us know. I'm sorry to hear the card was {reason_for_blocking}"
metadata:
rephrase: True
utter_acknowledge_reason_fraud_stolen_lost:
- text: "As your card was potentially stolen, it's crucial to report this incident to the authorities. Please contact your local law enforcement agency immediately."
- text: "Given the unfortunate potential theft of your card, please report this incident to your local law enforcement agency. We'll work together to minimize the impact of this situation."
utter_acknowledge_reason_travelling_moving:
- text: Thanks for informing us about moving.
In addition to the LLM agent implementation, MICA also provides the Flow agent, which can achieve the same effect as Rasa. Below is an example of implementing the blocking card feature using the Flow agent.
block_card_flow:
type: flow agent
description: Block or freeze a user's debit or credit card
args:
- reason_for_blocking
- physical_address
- fraud_reported
- temp_block_card
steps:
- begin
- bot: "Okay, we can block a card. Let's do it in a few steps"
- bot: "Please tell us the reason for blocking"
- user
- if: the user claims "My card is damaged", "My card has expired"
then:
- next: acknowledge_reason_damaged_expired
- else if: the user claims "I lost my card", "I suspect fraud on my account"
then:
- next: acknowledge_reason_fraud_stolen_lost
- else if: the user claims "I'm planning to travel soon", "I'm moving to a new address"
then:
- next: acknowledge_reason_travelling_moving
- else:
- next: contact_support
- end
- begin: acknowledge_reason_damaged_expired
- bot: Thank you for letting us know. I'm sorry to hear the card was {reason_for_blocking}
- next: confirm_issue_new_card
- end
- begin: acknowledge_reason_fraud_stolen_lost
- bot: "As your card was potentially stolen, it's crucial to report this incident to the authorities. Please contact your local law enforcement agency immediately."
- set:
fraud_reported: true
- next: card_blocked
- end
- begin: acknowledge_reason_travelling_moving
- bot: "Thanks for informing us about moving."
- set:
temp_block_card: true
- next: card_blocked
- end
- begin: card_blocked
- if: fraud_reported == true
then:
- bot: "Since you have reported {reason_for_blocking}, we will block your card"
- else if: temp_block_card == true
then:
- bot: "Since you are {reason_for_blocking}, we will temporarily block your card."
- next: confirm_issue_new_card
- end
- begin: confirm_issue_new_card
- bot: Would you like to be issued a new card?
- user
- if: the user claims "Yes, send me a new card"
then:
- next: retrieve_user_address
else:
- call: action_update_card_status
- end
- begin: retrieve_user_address
- bot: "I have found your address: {physical_address}. Should the new card be delivered there?"
- user
- if: the user claims "Yes"
then:
- next: card_sent
else:
- next: contact_support
- end
- begin: card_sent
- bot: "Your card will be delivered to {physical_address} within 7 business days"
- call: action_update_card_status
- end
- begin: contact_support
- bot: "Should you require further assistance, please contact our support team at 020 7777 7777. Thank you for being a valued customer."
- call: action_update_card_status
- end
Conclusion
MICA provides an efficient and scalable alternative to the Rasa Starter Pack for Retail Banking. While Rasa requires extensive predefined intents, structured dialogues, and manual configurations, MICA simplifies implementation through its adaptive, context-aware, and streamlined approach. These improvements enable faster development and more natural interactions for customers.