Using Custom Channel Data in Bot Framework v4
Problem statement
Imagine this: You are working on a Bot Framework bot and want to implement human handoff to give users the option to have a conversation with another human being if the bot is not able to answer the user’s questions. Now there are many good samples out there for channels like Microsoft Teams for example which demonstrate how to bring in a human into the loop. But I was trying to find a way to tell the webchat control (via DirectLine) that a given point in the conversation it should do something (escalate to an agent).
Now there was one thing I found which could do the trick for me: Custom Channel Data Property (you can find out what that is in detail here ). The article basically describes it as follows:
Some channels provide features that cannot be implemented by using only message text and attachments. To implement channel-specific functionality, you can pass native metadata to a channel in the activity object’s channel data property. For example, your bot can use the channel data property to instruct Telegram to send a sticker or to instruct Office365 to send an email.
As you can already see in that description, you can tell your bot’s channel that it should do something for you. And that’s the thing I needed. So I went for the docs to see on how to implement it in my .NET Echo Bot for testing purposes and found this article by the Microsoft Bot Framework Team instructing on how to send such a custom channel data object (it was written for Facebook but I surely can use it for my webchat scenario as well I thought). But upon reading this article I recognized something was odd: this article was written in March 2017 and used Bot Framework v3 instead of v4. This means that I cannot re-use that code as I would like because the majority of the implementation has changed.
So I had to look further and googled a couple of hours without any helpful results. My problem was that I needed a way to create a message and add the channel data property to that message before sending it to the channel.
Normally, you would create a message like this in your .NET bot:
await turnContext.SendActivityAsync(MessageFactory.Text($"Echo: {turnContext.Activity.Text}"), cancellationToken);
But the problem with this is that I have no option to add any properties to my MessageFactory.Text attribute here. Next thing I tried was to create a Json object which actually represented my channel data property and sent that via the exact same message as above to the webchat channel. And it got rendered as exactly that: a Json string containing my information which was provided to the user - not what I wanted, so I needed to look further. The docs also said nothing about the actual implementation in either .NET or JS the only thing they mention is how the format should look like. But this was not everything I needed to know…
Solution
And after researching many Google pages, I suddenly found this issue on Github, which was exactly what I needed. I needed the following line as a starting point to get down the road I wanted to end:
IMessageActivity message = Activity.CreateMessageActivity();
Now I could finally add the custom channel data property to my message before sending it out to the webchat channel using the following lines:
message.Text = $"Trying to connect to an agent";
message.TextFormat = "plain";
message.ChannelData = new Dictionary<string, object>
{
["type"] = "connectAgent",
["Data"] = new Dictionary<string, string> { { "AgentSkill", "ChatBot" } }
};
await turnContext.SendActivityAsync(message, cancellationToken);
And now that was what I needed. Now I could talk to my bot and whenever he is not able to give me an appropriate answer I can send the channel data property saying it should connect me to an agent:
Conclusion
After many hours of research I finally found a way on how to add custom channel properties to messages before sending them to a BFv4 channel. The code above is not only working for the webchat channel but for any other channel, just stick to the channel’s required format descibed here and you should be able to send your channel custom metadata to trigger certain actions (for exampling sending an automated email after the user has left the conversation with the chat transcript attached for further storing or analytics purposes - which may be the topic of my next post 😉)