n
nNow this sounds like a very straight forward and quite common requirement as possibility of having this capability in bots opens a gateway to number of opportunities in an enterprise environment e.g. sharing live information analytics to power users, sharing caution / warnings to system administrators based on past data etc. however there is a serious limited documentation available on achieving these real-world scenarios specifically with Bot framework SDK v4.
n
nIn this post, I am going to share the experience I had while developing a proactive bot and challenges which I faced, approach I took by referring several links and will also share what I learned.
n
n
Hitting the road block
nTo start with, at the time of writing this article – the only documentation and an official sample available from Microsoft is as mentioned below. Please go through these links and understand the essentials involved in getting a proactive bot design working.
n
n
“If the user has previously asked the bot to monitor the price of a product, the bot can alert the user if the price of the product has dropped by 20%”
But the big question was – how exactly do you do that?
n
n
Understanding basics
Approach
- Record conversation reference of each user / desired users
- Used Azure table storage to store these records
- Introduce api to fetch stored record from storage and generate ProactiveMessage
- Introduce / Integrate ProactiveController from this post
- Trigger post call to ProactiveController’s method with payload generated from step 3 and send a message from bot to a specified user
n
n
n
n
n
Step 1 and 2:
n
n
n
Instance of this class needs to be initiated from the incoming first user request which you would find in the OnTurnAsync method
n
n
n
Step 3:
n
n
nE.g. if I am storing user name in FromId property, then I would need the api to generate Activity Payload for that specific user so that we can send it further to the ProactiveController which takes care of beginning the proactive conversation with that user.
n
nI have added a controller in the same bot project which returns the collection of ProactiveMessages
nHere my definition of ProactiveMessage
n
n
nAnd ActivityGeneratorController in short
n
n
nAnd here is the sample output it generates
n
n
nIMPORTANT NOTE:
nThis took a while for me to understand and hence sharing. The botId and needs to be the Microsoft App Id of your bot and then only it works.
Step 4 and 5:
Validation:
Update
nThe approach mentioned above stopped working in specific scenarios e.g. when the user to which message needs to be sent becomes idle on channel then proactive messaging started throwing exception below
n
nMicrosoft.Bot.Schema.ErrorResponseException: Operation returned an invalid status code ‘Unauthorized’
n at Microsoft.Bot.Connector.Conversations.ReplyToActivityWithHttpMessagesAsync(String conversationId, String activityId, Activity activity, Dictionary`2 customHeaders, CancellationToken cancellationToken)
n at Microsoft.Bot.Connector.ConversationsExtensions.ReplyToActivityAsync(IConversations operations, String conversationId, String activityId, Activity activity, CancellationToken cancellationToken)
n at Microsoft.Bot.Builder.BotFrameworkAdapter.SendActivitiesAsync(ITurnContext turnContext, Activity[] activities, CancellationToken cancellationToken)
n at Microsoft.Bot.Builder.TurnContext.<>c__DisplayClass22_0.<<SendActivitiesAsync>g__SendActivitiesThroughAdapter|1>d.MoveNext()
n
nand this puzzled us, again there is a lack of documentation and information is scattered around different links and blogs. We came across one helpful link which gave some hints and then we had to make changes in out ProactiveMessagingController logic which now looks like this
n
n
n
nNote that we are now creating channel account and initialing an instance of MicrosoftAppCredentials with bot’s app Id and secret (typically you would find this in .bot file in your solution, if not you can always get it from bot registration portal) and then with the help of ConnectorClient we are not beginning conversations with specific user.