This article introduces the Live Assist for Microsoft Dynamics 365 Bot as an Enabler Bot C# SDK, running within the Azure Function Bot Framework.
The examples contained here do not provide a detailed guide for developing bots within the Microsoft Azure framework. We assume that the developer has experience of C# and the Microsoft Azure Framework, and that they are able to use this quick start guide as a starting point to become familiar with the Live Assist SDK.
Note: The Microsoft Function Bot Framework is currently in development. You may need to make some changes in the steps, or the code, for your development effort.
The C# code shown here, is almost identical to that shown in the Web App Bot Article, only the Framework is different.
This bot receives chats initiated with Microsoft Function Bot Service. The bot echoes any messages that a vistor sends, sending their original message back to them. When the visitor sends a message containing 'help', the Live Assist Bot SDK is invoked to escalate the call to a Live Assist Skill Group for processing.
The bot, by using the Live Assist SDK, proxies messages between the Azure Web Chat service and the Agent using Live Assist.
Step 1—Creating a C# basic Function Bot
- In Azure, create a new C# Function Bot.
- Set the appropriate Storage and Billing requirements for your application (F0 is adequate for Development).
The significant parts of this process are:- Selecting a name which is unique within Azure
- Selecting the C# (Basic) Application
This process may take Azure a few minutes to build.
Step 2—Opening the Bot in Azure Functions
- When the Function Bot has been created, you can Build and Open the 'Azure Functions' to manage it.
Step 3—Import The Live Assist Dependency
- Click messages and View Files and select the project.json
- Add "LiveAssistBotSDK": "1.0.1" (or copy/paste the following text):
{
"frameworks": {
"net46":{
"dependencies": {
"Microsoft.Bot.Builder.Azure": "3.2.5",
"LiveAssistBotSDK": "1.0.1"
}
}
}
} - The dependency will be imported next time the project is saved.
Step 4—Edit the EchoDialog.csx
Click messages and View Files and select the EchoDialog.csx
Based on the Microsoft SimpleEchoBot sample bot, make the following changes to the EchoDialog.csx file (or copy/paste the text from the completed example EchoDialog.csx from our Git Hub Repository):
- Managing Imports:
The following packages are required:using Microsoft.Bot.Builder.ConnectorEx; using Newtonsoft.Json; using System.Timers; using Cafex.LiveAssist.Bot;
- Declaring your static variables of the EchoDialog:
private static Sdk sdk; private static ChatContext chatContext; private static string conversationRef; private static Timer timer;
- Load the SDK in the StartAsync method
Specify your Account Number.sdk = sdk ?? new Sdk(new SdkConfiguration() { AccountNumber = "__CHANGE_ME__" });
- The beginning of the if block needs to check if the chat has already been escalated, so the echo doesn't occur
if (chatContext != null) { // As chatContext is not null we already have an escalated chat. // Post the incoming message line to the escalated chat await sdk.PostLine(activity.Text, chatContext); } else if (activity.Text == "help")
- Add an extra trigger to handle 'help' in the MessageReceivedAsyc method
else if (activity.Text.Contains("help")) { // "help" within the message is our escalation trigger. await context.PostAsync("Escalating to agent"); await Escalate(activity); // Implemented in next step. }
- Define the Escalate method
Specify the Agent Skill group to target.private async Task Escalate(Activity activity) { // This is our reference to the upstream conversation conversationRef = JsonConvert.SerializeObject(activity.ToConversationReference()); var chatSpec = new ChatSpec() { // Set Agent skill to target Skill = "__CHANGE_ME__", VisitorName = activity.From.Name }; // Start timer to poll for Live Assist chat events if (timer == null) { timer = timer ?? new Timer(5000); // OnTimedEvent is implemented in the next step timer.Elapsed += (sender, e) => OnTimedEvent(sender, e); timer.Start(); } // Request a chat via the Sdk chatContext = await sdk.RequestChat(chatSpec); }
- Define the Enabler Logic
When the OnTimedEvent fires, the messages are passed between the Visitor and the Bot, and the Agent and the Bot.async void OnTimedEvent(Object source, ElapsedEventArgs eea) { if (chatContext != null) { // Create an upstream reply var reply = JsonConvert.DeserializeObject<ConversationReference>(conversationRef) .GetPostToBotMessage().CreateReply(); // Create upstream connection on which to send reply var client = new ConnectorClient(new Uri(reply.ServiceUrl)); // Poll Live Assist for events var chatInfo = await sdk.Poll(chatContext); if (chatInfo != null) { // ChatInfo.ChatEvents will contain events since last call to poll. if (chatInfo.ChatEvents != null && chatInfo.ChatEvents.Count > 0) { foreach (ChatEvent e in chatInfo.ChatEvents) { switch (e.Type) { // type is either "state" or "line". case "line": // Source is either: "system", "agent" or "visitor" if (e.Source.Equals("system")) { reply.From.Name = "system"; } else if (e.Source.Equals("agent")) { reply.From.Name = chatInfo.AgentName; } else { break; } reply.Type = "message"; reply.Text = e.Text; client.Conversations.ReplyToActivity(reply); break; case "state": // State changes // Valid values: "waiting", "chatting", "ended" if (chatInfo.State.Equals("ended")) { chatContext = null; } break; } } } } } }
Step 5—Save and Run your bot
- Once the code is ready, you can Save and Run the bot. Compilation Errors are shown in the Error/Warning Log at the bottom of the screen. Also, Function Bots record invocation logs under the Monitor window. From here can get status of any messages sent to the bot:
Step 6—Testing your bot
- When you have published your bot, you can quickly test the new Chat Bot from Microsoft Azure > Test Web Chat tab.
Important: You need an Agent logged into LiveAssist for Microsoft Dynamics 365, under the correct skill group, to receive the escalated chat.
Step 7—Debugging your bot
There are numerous ways to debug your bot application. Bot logs can be retrieved through the Advanced Debugging options under Kudu: