- Proactive Messaging
The UniversalBot class forms the brains of your bot. It’s responsible for managing all of the conversations your bot has with a user. You first initialize your bot with a connector that connects your bot to either the Bot Framework or the console. Next you can configure your bot with dialogs that implement the actual conversation logic for your bot.
NOTE: For users of Bot Builder v1.x the BotConnectorBot, TextBot, and SkypeBot class have been deprecated. They will continue to function in most cases but developers are encouraged to migrate to the new UniversalBot class at their earliest convenience. The old SlackBot class has been removed from the SDK and unfortunately, at this time the only option is for developers to migrate their native Slack bots to the Bot Framework.
The UniversalBot class supports an extensible connector system the lets you configure the bot to receive messages & events and sources. Out of the box, Bot Builder includes a ChatConnector class for connecting to the Bot Framework and a ConsoleConnector class for interacting with a bot from a console window.
The ChatConnector class configures the UniversalBot to communicate with either the emulator or any of the channels supported by the Bot Framework. Below is an example of a “hello world” bot that’s configured to use the ChatConnector:
The appId & appPassword settings are generally required and will be generated when registering your bot in the developer portal. The one exception to that rule is when running locally against the emulator. When you’re first developing your bot you can leave the “Microsoft App Id” & “Microsoft App Password” blank in the emulator and no security will be enforced between the bot and emulator. When deployed, however, these values are required for proper operation.
The example is coded to retrieve its appId & appPassword settings from environment variables. This sets up the bot to support storing these values in a config file when deployed to a hosting service like Microsoft Azure. When testing your bots security settings locally you’ll need to either manually set the environment variables in the console window you’re using to run your bot or if you’re using VSCode you can add them to the “env” section of your launch.json file.
The ConsoleConnector class configures the UniversalBot to interact with the user via the console window. This connector is primarily useful for quick testing of a bot or for testing on a Mac where you can’t easily run the emulator. Below is an example of a “hello world” bot that’s configured to use the ConsoleConnector:
If you’re debugging your bot using VSCode you’ll want to start your bot using a command similar to node
--debug-brk app.js and then you’ll want to start the debugger using attach mode.
The SDK supports two modes of message delivery.
- Reactive Messages are messages your bot sends in response to a message received from the user. This is the most common message delivery mode and can be achieved using the session.send() method.
- Proactive Messages are messages your bot sends in response to some sort of external event like a timer firing or a notification being triggered. Good examples of proactive messages are a notification that an item has shipped or a daily poll asking team members for their status.
Saving Users Address
UniversalBot class exposes bot.send() and bot.beginDialog() methods for communicating with a user proactively. Before you can use either method you will need to save the address of the user you wish to communicate with. You can do that by serializing the session.message.address property to a string which you then store for future use:
You shouldn’t assume that an
address object for a user will always be valid. Addresses returned by the
ChatConnector class in particular contain a
serviceUrl property which can theoretically change and prevent your bot from contacting the user. Because of that you should consider periodically updating the address object stored for a user.
To proactively send a message to a user you’ll need to first add the web hook or other logic that will trigger your proactive notification. In the example below we’ve added a web hook to our bot that lets us trigger the delivery of a notification message to one of our bots users:
Within this web hook we’re de-serializing the users address which we previously saved. Then we compose a message for the user and deliver it with bot.send(). We can optionally provide a callback to receive the success or failure of the send.
In addition to sending messages proactively you can use bot.beginDialog() to start new conversations with a user. The differences between
bot.beginDialog() are subtle. Calling
bot.send() with a message won’t affect the state of any existing conversation between the bot & user so it’s generally safe to call at any time. Calling
bot.beginDialog() will end any existing conversation between the bot & user and start a new conversation using the specified dialog. As a general rule you should call
bot.send() if you don’t need to wait for a reply from the user and
bot.beginDialog() if you do.
Starting a proactive conversation is very similar to sending a proactive message. In the example below we have a web hook that triggers running a standup with multiple team members. In the web hook we simply loop over all of the team members and call
bot.beginDialog() with the address of each team member. The bot will then ask the team member their status and roll their answer up into a daily status report:
Proactive Messaging and Localization
For bots that support multiple languages you’ll need to always use
bot.beginDialog() to communicate with a user. Thats because the users preferred locale is persisted as part of the Session object which is currently only available within a dialog. Our original notification example can easily be updated to use
bot.beginDialog() instead of
The delivered notification will now use the SDK’s built-in localization support to deliver the user a notification in their preferred language. The one disadvantage of using
bot.send() is that any existing conversation between the bot & user will be ended before sending the user the notification. So for bots that support only a single language, the use of
bot.send() is still preferred.