I've made a chat bot using Microsoft Bot Framework which answers a user's questions. When the bot is unable to answer the user's questions, I want to be able to redirect the user question to a customer rep on Skype.
The person on Skype will see the messages posted by the user, and his answers will be sent to the user.
I need some advice on how to achieve this connection (from user<->chatbot<->SkypecustomerRep)
Edit:
I'm toying with the idea of using the commands in http://docs.botframework.com/connector/new-conversations/#navtitle
I figured when the LuisIntent would turn out to be None, I'd message a skype id with:
var connector = new ConnectorClient();
var message = new Message
{
From = new ChannelAccount(channelId: ""),
To = new ChannelAccount() {ChannelId = "Skype", Address = "xyz#abc.com"},
Text = result.Query,
Language = "en"
};
where the email is the Skype id. I'm not able to figure out what should be in the From field (what's the channelId, Address of my bot)
EDIT:
I'm able to pass one message to Skype now, but when the Skype user replies, I observe that the reply is not immediately presented to the bot framework user. In other words, when the user types something into the chat window, he gets a response from the bot (as expected) and the skype user's delayed message.
If you want the customer support representative to have sufficient context (i.e. see more than just the most recent text posted by the user) you are going to need to build your own customer support interface to both record conversations as well as highlight those that need attention from a human. Usually folks do this building their own client with DirectLine or connecting up their existing customer support client (also with DirectLine). The bot then directly passes the support reps replies back to the end users.
Some additional detail can be seen in this previous answer.
Related
We have a Teams bot that posts messages in MS Teams. The first activity of a new conversation is always an adaptive card and once in a while, we update that with a new card. This worked OK until I made a new Team with this bot.
The update we are trying with UpdateActivityAsync, return NotFound.
After some troubleshooting, I noticed the following:
The new team has a different name: 19:...#thread.tacv2 as opposed to 19:...#thread.skype.
When I use an older team, it works as expected.
When I update the activity with text only (so no adaptive card as attachment) it will always update as expected.
After an update with a text, we are able to update with an adaptive card ONCE. After one update with an adaptive card, any subsequent updates with adaptive cards will return NotFound.
So, as a workaround, I now first update with text and immediately after that I send the update with the card. Which is a bad UI thing (flickering) but it works for now.
We use the old bot framework version 3, which I know is not maintained anymore, but as far as I can find, it should still work (no plans to discontinue operation). Also given the above points (specifically point 4) I would expect it uses the same calls under the hood.
So, this works for older teams, but not for a team with #thread.tacv2
await connector.Conversations.UpdateActivityAsync(
teamsConversationId,
activityId,
(Activity)messageWithCard);
And for teams with #thread.tacv2 we now have to use this
var messageWithText = Activity.CreateMessageActivity();
messageWithText.ChannelId = teamsConversationId;
messageWithText.Id = activityId;
messageWithText.Type = ActivityTypes.Message;
messageWithText.Text = "Updated";
await connector.Conversations.UpdateActivityAsync(
teamsConversationId,
activityId,
(Activity)messageWithText);
await connector.Conversations.UpdateActivityAsync(
teamsConversationId,
activityId,
(Activity)messageWithCard);
The exception does not provide too many details:
Operation returned an invalid status code 'NotFound'
Conversation not found.
Does anyone know how to avoid this change between teams and allow updates of activity with cards?
Also (and this is much less important, but I think it's useful to add) I noticed that sometimes (I've seen it twice now) Teams seems unable to render the adaptive card and displays URIObject XML instead, containing error: cards.unsupported. However, if I exit the client and restart it, it renders fine... I have never seen this so far in the old channels.
Teams client version 1.3.00.362 (64-bit) (no dev mode).
Normal Azure tenant (no preview/trial)
EDIT 11/05/2020 It seems that this also happens on teams with the 'old' name (#thread.skype). So the '#thread.tacv2' seems unrelated.
We weren't able to find logs at the exact timestamps that you provided, but did find logs for the conversation ids on those dates and see 404s with the same minute and seconds in UTC. We assume the time stamps that were provided are represented in a different timezone.
From the logs we are seeing the following pattern:
Bot sends PUT activity with card - 404 returned
Bot sends PUT activity with text - 200 returned
Bot sends PUT activity with card - 200 returned
This looks like the same pattern that you shared in your original post.
There is a scenario that's causing 404s to be returned on PUTS whenever the bot tries to update an existing card message with the exact same card after new messages have been sent to a reply chain
These are the repo steps:
Bot send card to reply chain (can be root message or reply message)
Any user sends a message to the chain
Bot attempts to update message with the exact same card
Is it possible that your bot is encountering this? Is there a way to check whether the card your bot is sending in the first PUT request is the same card that is already in the original message
I have written a small chat bot using the MS bot framework. I added the Skype and Web channels, and host the bot on Azure with the smallest pay-as-you-go plan. The bot itself is working nicely, both through the web chat and in Skype conversations, both directly (1on1 chat) as well as in groups, when I'm using the Skype desktop app.
Unfortunately, when using the Skype app installed from the Microsoft store, nothing works anymore... Sending a message to the bot (in direct chats and groups) always produces HTTP 500 responses from my bot. Digging into it a bit releaved a simple NullReferenceException being thrown, apparently in the very first line in my dialog handler (see below): The call stack pointed at this line, but the error happened later, see below:
namespace MyBot.Dialogs {
[Serializable]
public class RootDialog: IDialog<IMessageActivity> {
public Task StartAsync(IDialogContext context) {
context.Wait(MessageReceivedAsync);
return Task.CompletedTask;
}
private async Task MessageReceivedAsync(IDialogContext context, IAwaitable<IMessageActivity> result) {
// call stack pointed to next line
Activity activity = await result as Activity;
//... some unproblematic stuff
string username = activity.From.Name;
// the next line was the actual problem:
if(username.Contains(" "))
//...
}
}
}
This part of the code, as well as the full MessagesController are taken without changed from the bot framework examples, and as mentioned before, the bot is working fine from web chat and the "regular" Skype desktop app. Even in a group chat with some users on the desktop app and some on the store app, the users with the desktop app can interact with the bot as expected, while the store app users only trigger errors.
The obvious questions here are of course: how (and why) do the two Skype apps differ from a bot perspective, and how can I handle this?
Edit: As it turns out, the Skype desktop app sets the activity.From.Name property to the user's name, while the Skype store app does not. The mean part is, the channelid's for both are the same ("skype", obviously).
Thanks to the comment of #EricDahlvang, I noticed that the error was not the line mentioned above at first, despite the call stack specifically giving this line number. The error happened later, when I tried to work with "activity.From.Name". As it turns out, the regular Skype sets this property to match the users display name, while the Skype store app does not, and returns null.
I have used the Microsoft Bot Framework Proactive Message samples which are great but I have one issue.
In the simple message example (https://github.com/Microsoft/BotBuilder-Samples/tree/master/CSharp/core-proactiveMessages/simpleSendMessage) the messages send but in Facebook Messenger I don't get a notification on my phone. However, adding in this simple bit of code fixes that perfectly:
message.ChannelData = JObject.FromObject(new { notification_type = "REGULAR" });
I'm now using the Start New Dialog example (https://github.com/Microsoft/BotBuilder-Samples/tree/master/CSharp/core-proactiveMessages/startNewDialog) and want to do the same thing but the dialog messages do not cause a notification. I've tried setting the notification_type in as above in various places in my code but nothing seems to work.
Any help / pointers would be greatly appreciated.
Thanks
Stu
I've found the notifications work just fine without any code changes to the Start New Dialog example sample since making my Messenger Bot Public. I don't understand why some notifications work / don't work when the bot is not public.
i've another strange question on BOT Framework and Bot Account.
View image.
Why in simple welcome message bot answer with my custom bot account,
new ChannelAccount(id: "test.id", name: "testBot");
but in
[Microsoft.Bot.Builder.Dialogs] PromptDialog.Choice
the from name and id is different?
My example code is:
public virtual async Task MessageReceivedAsync(IDialogContext context, IAwaitable<IMessageActivity> result)
{
var message = await result;
message.From = new ChannelAccount(id: "id-bot", name: "BotName");
PromptDialog.Choice(context, this.OnOptionSelected, new List<string>() { FlightsOption, HotelsOption }, "Are you looking for a flight or a hotel?", "Not a valid option", 3);
}
My questions are:
It's possible custom PromptDialog.Choice From Name and Id?
It's possible set bot account globally (for any reply message)?
Based on your screenshot, it looks like you're running your bot locally from Visual Studio and then using the Bot Channel Emulator tool to test your bot.
The bot's actual name is automatically set for you when you have deployed your bot into a real environment (not your dev), based what you have registered in the Bot Framework Portal. In dev, when using the emulator, it's simply always displayed as "Bot".
So don't bother trying to set your bot's name in code as you are doing now because it's unnecessary. And as a result, there is no need for you to customise PromptDialog.Choice either.
I have a workflow activity which I use to send out e-mails to suppliers on a regular basis and scheduling follow-up phone calls etc if there is no reply. However my problem is that I somehow need to retrieve the e-mail for each supplier before sending the message.
How can I go about retrieving the value in a specific field from a specific entity in CRM 2011?
Here is the pseudo-code:
For each supplier entity in the system {
if (sendSalesRequest) {
Send Initial E-mail
- wait 21 days
if (noReply) {
Send Follow up e-mail
- wait 7 days
if (noFollowupReply) {
schedule phone call activity everyday until reply
}
}
}
}
However, I need a way of retrieving the e-mail address from the suppler entity.
I'm not looking for a worked solution (though I wouldn't turn it down!), just guidelines on how to go about this task as I'm brand new to CRM development.
Thanks,
Tysin
If your new to 2011 I would suggest reading about the SDK. In particular you need to look at custom workflow activity development. It has a number of samples which should help you along the way.
I would suggest having:
A master workflow, that has a single step to call your custom workflow activity which processes the suppliers. You start this workflow whenever you want to process all the suppliers.
An on-demand workflow that sends the initial email
An on-demand workflow that sends the follow up email
An on-demand workflow that schedules the phone call
The reason I suggest this is that means you keep the creation of data in workflows where is it easier to manage and handle. E.g. you could change the email message without recompiling your custom workflow activity.
So first step in your master custom workflow activity, is to query Crm, I would suggest a QueryExpression to start with. That way you can get the data to base you logic on.
Then you need some code to start a workflow against a record, to send the email and phones calls. There is an example for this here.
Then you code would look a little like this:
QueryExpression query = new QueryExpression("supplier");
query.ColumnSet = new ColumnSet("sendsalesrequest", "noreply", "nofollowupreply");
EntityCollection entities = service.RetrieveMultiple(query);
entities.Entities.ToList().ForEach(entity =>
{
if(entity["sendsalesrequest"] == "Yes")
{
StartWorkflow(entity.Id, "Send Initial E Mail Workflow Name");
}
//etc
}
This is quite high level but should hopefully get you going in the right direction.