The only way I could do this is to implement everything in a single action, and set this action as an active loop.
async def run(
self,
dispatcher: CollectingDispatcher,
tracker: Tracker,
domain: DomainDict
) -> List[EventType]:
latest_confirmation_status = tracker.get_slot('confirmation_status')
latest_intent = tracker.get_intent_of_latest_message()
latest_entities = tracker.latest_message.get('entities')
logging.debug(f'Latest confirmation status: {latest_confirmation_status}; '
f'Latest intent: {latest_intent}; '
f'Latest entities: {latest_entities}')
if latest_confirmation_status == INACTIVE:
dispatcher.utter_message(response='utter_introduce_slots')
dispatcher.utter_message(format_slot_values(tracker))
dispatcher.utter_message(response='utter_ask_for_confirmation')
return [ActiveLoop(ACTION_NAME), SlotSet("confirmation_status", RUNNING)]
elif latest_confirmation_status == RUNNING:
if latest_entities:
dispatcher.utter_message(format_slot_values(tracker))
dispatcher.utter_message(response='utter_ask_for_confirmation')
return []
elif latest_intent == 'affirm':
dispatcher.utter_message(response='utter_booking_completed')
return [ActiveLoop(None), SlotSet("confirmation_status", COMPLETED)]
elif latest_intent == 'deny':
dispatcher.utter_message(response='utter_ask_for_correction')
return []
else:
logging.warning('Aborted confirmation loop')
return [ActiveLoop(None), SlotSet("confirmation_status", ABORTED)]
else:
raise ValueError(f'Unexpected status: {repr(latest_confirmation_status)}')
- rule: Activate confirmation loop
steps:
- action: book_form
- slot_was_set:
- requested_slot: null
- active_loop: null
- action: action_confirm
- active_loop: action_confirm
- rule: Abort confirmation loop
steps:
- slot_was_set:
- confirmation_status: aborted
- active_loop: null
- rule: Complete confirmation loop
steps:
- slot_was_set:
- confirmation_status: completed
- active_loop: null