0

I want to build a Teams bot that can send proactive messages, including creating conversations even if the user has never had a conversation with the bot.

I followed the proactive sample and adapted it to send a notification as POST in the notify controller. I am able to continue a conversation, but when I try to create one, the user does not get any messages.

Here is my code to create a conversation from the notify controller:

// I got the following 4 values logging them on the bot in a conversation started by a user
const string botAppId = "<MicrosoftApptId GUID>";
const string serviceUrl = "<my service URL>";
const string tenantId = "<my tenant ID>";
const string recipientId = "<recipient ID xy:GUID>";

var title = "test title";
var activity = Activity.CreateMessageActivity();
activity.Type = ActivityTypes.Message;
activity.Text = "test message";

await ((BotAdapter)_adapter).CreateConversationAsync(
    botAppId: botAppId, 
    channelId: Microsoft.Bot.Connector.Channels.Msteams, 
    serviceUrl: serviceUrl, 
    audience: null, 
    conversationParameters: new ConversationParameters
    {
        Activity = (Activity)activity,
        Bot = new ChannelAccount(botAppId),
        IsGroup = false,
        Members = new List<ChannelAccount> { new ChannelAccount(recipientId) },
        TopicName = title,
        TenantId = tenantId
    },
    callback: (turnContext, cancellationToken) => Task.CompletedTask,
    cancellationToken: default(CancellationToken));

What am I doing wrong here? Am I missing things in the conversation parameters? Should I populate the audience? How?

Thanks for any help!

Note that this is a new post based on my comment on https://stackoverflow.com/a/60024372/1322336

laurian
  • 739
  • 6
  • 18

2 Answers2

3

Martin's answer covers things nicely, but I want to add a few more relevant points:

  1. The sample you've linked to works fine, but in truth there are actually a few ways to call the bot framework service in order to do this, and some of them can be a bit confusing because of that. To help with this, I put together a sample that shows some minimal info you need, and how to get it. It also shows, incidentally, that you proactive message code doesn't need to live in the same place as the code for your bot itself. For instance, you bot would be a web service of some sort, but your proactive messaging sending code could be in an Azure Function or AWS Lambda or something like that. It will still appear to come "from" your bot to the end user's perspective.

Here's a video where I talk through this in a bit more detail, in case it helps: https://www.youtube.com/watch?v=mM7-fYdcJhw&t=1398s

  1. It is essential, as Martin says, that you have the conversation already exist in Teams between the user and the bot - the bot can't be the first to ever connect to the user - the user basically needs to be provide 'permission' to the bot to have a conversation with him/her, which is done by installing the bot/app. There are actually several ways to do this. The easiest is to get your app pre-installed by a Teams administrator in your org. That way, for instance, it can be pre-installed to every user in your company, and even for all -future- users automatically. The Teams admin would do this in the "policies" section in the Teams admin site. Another option is to do it programmatically, using Graph, using this endpoint.
Hilton Giesenow
  • 9,809
  • 2
  • 10
  • 24
  • Thanks, that's a very useful sample, exactly what I need! – laurian Jan 07 '22 at 15:06
  • Actually I have one more question: can the bot create a group conversation with users that have installed the bot? If so, how? – laurian Jan 07 '22 at 15:08
  • So it's a similar problem there - the bot can't entirely message to a conversation it's not part of, so you need to (a) have the conversation exist already and (b) have the bot (i.e. app) be part of it. It's possible to do these via Graph though I think. See https://learn.microsoft.com/en-us/graph/api/chat-post?view=graph-rest-1.0&tabs=http and https://learn.microsoft.com/en-us/graph/api/chat-post-installedapps?view=graph-rest-1.0&tabs=http – Hilton Giesenow Jan 08 '22 at 18:17
1

You can't start a conversation with a user that has never talked to your bot and when they did that you stored a conversation reference somewhere to use it when sending the proactive message.

What the proactive sample does is precisely that, store in memory the references to the conversations.

Teams assigns a user id that's unique to the bot-user relationship, so there's no way you can start a conversation even if you knew the user's active directory object id. Or at least not without using it to create the conversation reference.

Following the Proactive Sample

https://github.com/microsoft/BotBuilder-Samples/blob/95f2fa8440b4cf3f984c3f1cb82966b8b45d71e8/samples/csharp_dotnetcore/16.proactive-messages/Bots/ProactiveBot.cs#L26 That method is the one storing the conversation reference. Then the notify endpoint loops through the stored conversation references and send notifications. If your user didn't trigger that method ever, then the notify endpoint won't do anything with that user. I see that you modified the notify controller, but I'm not sure how you are getting the recipientId for a user that never talked to you.

Talking to a user for the first time, Microsoft Graph Approach.

To do that you'll need access to the Microsoft Graph API in the AAD tenant and use it to:

  1. Get the user
  2. Get the AppInstallationId if the user has installed your bot or potentially force the installation
  3. Use that to get the ChatId between the bot and that AppInstallation
  4. Use that ChatId to create the conversation reference for that user.
  5. Optionally store somewhere the reference to the user id and the conversation reference you created so you don't have to do all the previous steps for that user again.

Check this project out: https://github.com/microsoft/microsoft-teams-apps-company-communicator

Martín La Rosa
  • 790
  • 4
  • 17
  • 1
    Are you sure you cannot start a conversation with a user that has never talked to your bot? I thought the only requirement was that the bot was installed. If creating a conversation was not allowed, what would be the point of the CreateConversationAsync function? – laurian Jan 06 '22 at 17:42
  • well if you handled the event when the user added the bot and stored the conversation reference, then yes, you can. The question is if you are doing so. If you are following the proactive sample, see https://github.com/microsoft/BotBuilder-Samples/blob/95f2fa8440b4cf3f984c3f1cb82966b8b45d71e8/samples/csharp_dotnetcore/16.proactive-messages/Bots/ProactiveBot.cs#L26. That's where the conversation reference is being stored. Does your user trigger that method? See that it stores this in memory, so even if adding the bot triggered it restarting the bot will forget the reference – Martín La Rosa Jan 06 '22 at 18:10
  • OK, thanks, I have a better understanding of it now. If someone else has the same questions, do check also Hilton's answer: it links to a very useful example. – laurian Jan 07 '22 at 15:06