Handling interruptions is an important aspect of a robust bot. Users won't always follow your defined conversation flow, step by step. They may try to ask a question in the middle of the process, or simply want to cancel it instead of completing it. This article describes some common ways to handle user interruptions in your bot.
The sample used in this article models a flight booking bot that uses dialogs to get flight information from the user. At any time during the conversation with the bot, the user can issue help or cancel commands to cause an interruption. There are two types of interruptions handled:
To use dialogs, install the Microsoft.Bot.Builder.Dialogs NuGet package.
Dialogs\CancelAndHelpDialog.cs
Implement the CancelAndHelpDialog
class to handle user interruptions. The cancelable dialogs, BookingDialog
and DateResolverDialog
derive from this class.
Warning
It looks like the sample you are looking for has moved! Rest assured we are working on resolving this.
In the CancelAndHelpDialog
class, the OnContinueDialogAsync
method calls the InterruptAsync
method to check if the user has interrupted the normal flow. If the flow is interrupted, base class methods are called; otherwise, the return value from the InterruptAsync
is returned.
Warning
It looks like the sample you are looking for has moved! Rest assured we are working on resolving this.
If the user types "help", the InterruptAsync
method sends a message and then calls DialogTurnResult (DialogTurnStatus.Waiting)
to indicate that the dialog on top is waiting for a response from the user. In this way, the conversation flow is interrupted for a turn only, and the next turn continues from where the conversation left off.
If the user types "cancel", it calls CancelAllDialogsAsync
on its inner dialog context, which clears its dialog stack and causes it to exit with a canceled status and no result value. To the MainDialog
(shown later on), it will appear that the booking dialog ended and returned null, similar to when the user chooses not to confirm their booking.
Warning
It looks like the sample you are looking for has moved! Rest assured we are working on resolving this.
To use dialogs, install the botbuilder-dialogs npm package.
dialogs/cancelAndHelpDialog.js
Implement the CancelAndHelpDialog
class to handle user interruptions. The cancelable dialogs, BookingDialog
and DateResolverDialog
extend this class.
Warning
It looks like the sample you are looking for has moved! Rest assured we are working on resolving this.
In the CancelAndHelpDialog
class, the onContinueDialog
method calls the interrupt
method to check if the user has interrupted the normal flow. If the flow is interrupted, base class methods are called; otherwise, the return value from the interrupt
is returned.
Warning
It looks like the sample you are looking for has moved! Rest assured we are working on resolving this.
If the user types "help", the interrupt
method sends a message and then returns a { status: DialogTurnStatus.waiting }
object to indicate that the dialog on top is waiting for a response from the user. In this way, the conversation flow is interrupted for a turn only, and the next turn continues from where the conversation left off.
If the user types "cancel", it calls cancelAllDialogs
on its inner dialog context, which clears its dialog stack and causes it to exit with a canceled status and no result value. To the MainDialog
(shown later on), it will appear that the booking dialog ended and returned null, similar to when the user chooses not to confirm their booking.
Warning
It looks like the sample you are looking for has moved! Rest assured we are working on resolving this.
CancelAndHelpDialog.java
Implement the CancelAndHelpDialog
class to handle user interruptions. The cancelable dialogs, BookingDialog
and DateResolverDialog
derive from this class.
Warning
It looks like the sample you are looking for has moved! Rest assured we are working on resolving this.
In the CancelAndHelpDialog
class, the onContinueDialog
method calls the interrupt
method to check if the user has interrupted the normal flow. If the flow is interrupted, base class methods are called; otherwise, the return value from the interrupt
is returned.
Warning
It looks like the sample you are looking for has moved! Rest assured we are working on resolving this.
If the user types "help", the interrupt
method sends a message and then calls DialogTurnResult(DialogTurnStatus.WAITING)
to indicate that the dialog on top is waiting for a response from the user. In this way, the conversation flow is interrupted for a turn only, and the next turn continues from where the conversation left off.
If the user types "cancel", it calls cancelAllDialogs
on its inner dialog context, which clears its dialog stack and causes it to exit with a canceled status and no result value. To the MainDialog
(shown later on), it will appear that the booking dialog ended and returned null, similar to when the user chooses not to confirm their booking.
Warning
It looks like the sample you are looking for has moved! Rest assured we are working on resolving this.
To use dialogs, install the botbuilder-dialogs
package and make sure that the sample requirements.txt
file contains the proper reference such as botbuilder-dialogs>=4.5.0
.
For more information, about installing the packages, see the samples repository README file.
Note
Running pip install botbuilder-dialogs
will also install botbuilder-core
, botbuilder-connector
, and botbuilder-schema
.
dialogs/cancel-and-help-dialog.py
Implement the CancelAndHelpDialog
class to handle user interruptions. The cancelable dialogs, BookingDialog
and DateResolverDialog
derive from this class.
Warning
It looks like the sample you are looking for has moved! Rest assured we are working on resolving this.
In the CancelAndHelpDialog
class, the on_continue_dialog
method calls the interrupt
method to check if the user has interrupted the normal flow. If the flow is interrupted, base class methods are called; otherwise, the return value from the interrupt
is returned.
Warning
It looks like the sample you are looking for has moved! Rest assured we are working on resolving this.
If the user types "help" or "?", the interrupt
method sends a message and then calls DialogTurnResult(DialogTurnStatus.Waiting)
to indicate that the dialog on top of the stack is waiting for a response from the user. In this way, the conversation flow is interrupted for a turn only, and the next turn continues from where the conversation left off.
If the user types "cancel" or "quit", it calls cancel_all_dialogs()
on its inner dialog context, which clears its dialog stack and causes it to exit with a canceled status and no result value. To the MainDialog
, shown later, it will appear that the booking dialog ended and returned null, similar to when the user chooses not to confirm their booking.
Warning
It looks like the sample you are looking for has moved! Rest assured we are working on resolving this.
Once the interrupt handling class is implemented, review what happens when this bot receives a new message from the user.
Dialogs\MainDialog.cs
As the new message activity arrives, the bot runs the MainDialog
. The MainDialog
prompts the user for what it can help with. And then it starts the BookingDialog
in the MainDialog.ActStepAsync
method, with a call to BeginDialogAsync
as shown below.
Warning
It looks like the sample you are looking for has moved! Rest assured we are working on resolving this.
Next, in the FinalStepAsync
method of the MainDialog
class, the booking dialog ended and the booking is considered to be complete or canceled.
Warning
It looks like the sample you are looking for has moved! Rest assured we are working on resolving this.
The code in BookingDialog
isn't shown here as it's not directly related to interruption handling. It's used to prompt users for booking details. You can find that code in Dialogs\BookingDialogs.cs.
dialogs/mainDialog.js
As the new message activity arrives, the bot runs the MainDialog
. The MainDialog
prompts the user for what it can help with. And then it starts the bookingDialog
in the MainDialog.actStep
method, with a call to beginDialog
as shown below.
Warning
It looks like the sample you are looking for has moved! Rest assured we are working on resolving this.
Next, in the finalStep
method of the MainDialog
class, the booking dialog ended and the booking is considered to be complete or canceled.
Warning
It looks like the sample you are looking for has moved! Rest assured we are working on resolving this.
The code in BookingDialog
isn't shown here as it's not directly related to interruption handling. It's used to prompt users for booking details. You can find that code in dialogs/bookingDialogs.js.
MainDialog.java
As the new message activity arrives, the bot runs the MainDialog
. The MainDialog
prompts the user for what it can help with. And then, it starts the BookingDialog
in the MainDialog.actStep
method, with a call to beginDialog
as shown below.
Warning
It looks like the sample you are looking for has moved! Rest assured we are working on resolving this.
Next, in the finalStep
method of the MainDialog
class, the booking dialog ended and the booking is considered to be complete or canceled.
Warning
It looks like the sample you are looking for has moved! Rest assured we are working on resolving this.
The code in BookingDialog
isn't shown here as it's not directly related to interruption handling. It's used to prompt users for booking details. You can find that code in BookingDialogs.java.
dialogs/main_dialog.py
As the new message activity arrives, the bot runs the MainDialog
. The MainDialog
prompts the user for what it can help with. And then it starts the bookingDialog
in the act_step
method, with a call to begin_dialog
as shown below.
Warning
It looks like the sample you are looking for has moved! Rest assured we are working on resolving this.
Next, in the final_step
method of the MainDialog
class, the booking dialog ended and the booking is considered to be complete or canceled.
Warning
It looks like the sample you are looking for has moved! Rest assured we are working on resolving this.
The adapter's error handler handles any exceptions that weren't caught in the bot.
AdapterWithErrorHandler.cs
In the sample, the adapter's OnTurnError
handler receives any exceptions thrown by your bot's turn logic. If there's an exception thrown, the handler deletes the conversation state for the current conversation to prevent the bot from getting stuck in an error loop caused by being in a bad state.
Warning
It looks like the sample you are looking for has moved! Rest assured we are working on resolving this.
index.js
In the sample, the adapter's onTurnError
handler receives any exceptions thrown by your bot's turn logic. If there's an exception thrown, the handler deletes the conversation state for the current conversation to prevent the bot from getting stuck in an error loop caused by being in a bad state.
Warning
It looks like the sample you are looking for has moved! Rest assured we are working on resolving this.
By registering an AdapterWithErrorHandler
with the Spring framework in Application.java for the BotFrameworkHttpAdapter
in this sample, the adapter's onTurnError
handler receives any exceptions thrown by your bot's turn logic. If there's an exception thrown, the handler deletes the conversation state for the current conversation to prevent the bot from getting stuck in an error loop caused by being in a bad state. In the Java SDK, the AdapterWithErrorHandler
is implemented as part of the SDK and is included in the com.microsoft.bot.integration package. See the Java SDK source code for details on the implementation of this adapter.
adapter_with_error_handler.py
In the sample, the adapter's on_error
handler receives any exceptions thrown by your bot's turn logic. If there's an exception thrown, the handler deletes the conversation state for the current conversation to prevent the bot from getting stuck in an error loop caused by being in a bad state.
Warning
It looks like the sample you are looking for has moved! Rest assured we are working on resolving this.
Startup.cs
Finally, in Startup.cs
, the bot is created as a transient, and on every turn, a new instance of the bot is created.
Warning
It looks like the sample you are looking for has moved! Rest assured we are working on resolving this.
For reference, here are the class definitions that are used in the call to create the bot above.
Warning
It looks like the sample you are looking for has moved! Rest assured we are working on resolving this.
Warning
It looks like the sample you are looking for has moved! Rest assured we are working on resolving this.
Warning
It looks like the sample you are looking for has moved! Rest assured we are working on resolving this.
index.js
Finally, in index.js
, the bot is created.
Warning
It looks like the sample you are looking for has moved! Rest assured we are working on resolving this.
For reference, here are the class definitions that are used in the call to create the bot above.
Warning
It looks like the sample you are looking for has moved! Rest assured we are working on resolving this.
Warning
It looks like the sample you are looking for has moved! Rest assured we are working on resolving this.
Warning
It looks like the sample you are looking for has moved! Rest assured we are working on resolving this.
Application.java
Finally, in Application.java
, the bot is created.
Warning
It looks like the sample you are looking for has moved! Rest assured we are working on resolving this.
For reference, here are the class definitions that are used in the call to create the bot above.
Warning
It looks like the sample you are looking for has moved! Rest assured we are working on resolving this.
Warning
It looks like the sample you are looking for has moved! Rest assured we are working on resolving this.
Warning
It looks like the sample you are looking for has moved! Rest assured we are working on resolving this.
app.py
Finally, in app.py
, the bot is created.
Warning
It looks like the sample you are looking for has moved! Rest assured we are working on resolving this.
For reference, here are the class definitions that are used in the call to create the bot.
Warning
It looks like the sample you are looking for has moved! Rest assured we are working on resolving this.
Warning
It looks like the sample you are looking for has moved! Rest assured we are working on resolving this.
Warning
It looks like the sample you are looking for has moved! Rest assured we are working on resolving this.