5
votes

I am developing a bot for Microsoft Teams using the Bot Framework SDK v4 for NodeJS. Is there a way that the bot can automatically initiate a conversation in a channel, rather than user initiating the conversation? My bot works fine when the user initiates the conversation. Any suggestions on how I can proceed with this?

4

4 Answers

2
votes

MS Teams calls that a "Proactive Message" (note: Bot Framework generally defines a "proactive message" as sending a user a message not related to current conversation, that you have a reference for. Teams lumps a few things into this category). You can read more about how to use proactive messaging from the official Teams docs. Or, more specifically, creating a channel conversation.

The gist of it is that you need to capture a conversationUpdate and check for a new member added to the conversation or fetch the team roster, then you send the proactive message.

Note: For MS Teams, the user or team will have to add the bot first:

Bots can create new conversations with an individual Microsoft Teams user as long as your bot has user information obtained through previous addition in a personal or team scope. This information enables your bot to proactively notify them. For instance, if your bot was added to a team, it could query the team roster and send users individual messages in personal chats, or a user could @mention another user to trigger the bot to send that user a direct message.

Some developers come across 401: Unauthorized errors when using proactive messaging, especially if the bot was restarted for some reason and the bot is attempting to re-initiate a proactive message. You can read more about preventing that by using trustServiceUrl from this Sample (this is my branch, which is being used to submit a Pull Request to update the Proactive Sample with trustServiceUrl info).

0
votes

You can initiate a brand new conversation using the connector Client in the Botframework V4 and the Teams Extensions V4. In nodejs, you will find a solution in one of the comments for this Github Issue. For anyone looking for a solution in C#, here is a detailed blog post about accomplishing this in C# version of the botframework.

in nodejs :

var conversationReference = TurnContext.getConversationReference(context.activity)
connectorClient = await createConnectorClient(context)

var conversationParameters = {
isGroup: true,
bot: conversationReference.bot,
channelData: (await teamsCtx.getTeamsChannelData()),
tenantId: teamsCtx.tenant.id,
activity: MessageFactory.text("Queue Summary Placeholder") as Activity
} as ConversationParameters

await connectorClient.conversations.createConversation(conversationParameters)

In C#

ConnectorClient _client = new ConnectorClient(new Uri(turnContext.Activity.ServiceUrl), await GetMicrosoftAppCredentialsAsync(turnContext), new HttpClient());
            var channelData = turnContext.Activity.GetChannelData<TeamsChannelData>();

            var conversationParameter = new ConversationParameters
            {
                Bot = turnContext.Activity.Recipient,
                IsGroup = true,
                ChannelData = channelData,
                TenantId = channelData.Tenant.Id,
                Activity = MessageFactory.Text(message)
            };
            var response = await _client.Conversations.CreateConversationAsync(conversationParameter);

0
votes

Really we need to know when you want the bot to send the message, the bot framework TeamsActivityHandler class provides multiple methods that you can utilise for example:

  1. onMembersAdded(BotHandler): Registers an activity event handler for the members added event, emitted for any incoming conversation update activity that includes members added to the conversation.

Learn more about the events / methods you can utilise here.

0
votes

I ended up figuring it out and i wrote a bot controller that i can invoke on demand with the following code.

var conversationParameters = new ConversationParameters
            {
                IsGroup = true,
                ChannelData = new TeamsChannelData
                {
                    // this needs to come from the teams context.
                    Channel = new ChannelInfo(channelId),
                },
                Activity = (Activity)MessageFactory.Attachment(attachment)
            };
            // your service url may differ.
            MicrosoftAppCredentials.TrustServiceUrl(String.IsNullOrEmpty(serviceUrl) ? constantServiceUrl : serviceUrl, DateTime.MaxValue);
            var response = connectorClient.Conversations.CreateConversationAsync(conversationParameters).GetAwaiter().GetResult();