Conversation events in your Teams bot

Important

The code samples in this section are based on version 4.6 and later versions of the Bot Framework SDK. If you are looking for documentation for earlier versions, see the bots - v3 SDK section in the Legacy SDKs folder of the documentation.

When building your conversational bots for Microsoft Teams, you can work with conversation events. Teams sends notifications to your bot for conversation events that happen in scopes where your bot is active. You can capture these events in your code and take the following actions:

  • Trigger a welcome message when your bot is added to a team.
  • Trigger a welcome message when a new team member is added or removed.
  • Trigger a notification when a channel is created, renamed, or deleted.
  • Trigger a notification when a bot message is liked by a user.
  • Identify the default channel for your bot from user input (selection) during installation.

The following video demonstrates how a conversation bot can improve customer engagement through smooth, intelligent interactions:


Conversation update events

You can use conversation update events to provide better notifications and effective bot actions.

Important

  • You can add new events any time and your bot begins to receive them.
  • You must design your bot to receive unexpected events.
  • If you are using the Bot Framework SDK, your bot automatically responds with a 200 - OK to any events you choose not to handle.
  • When an Azure Communication Services (ACS) client joins or leaves the Teams meeting, no conversation update events are triggered.

A bot receives a conversationUpdate event in either of the following cases:

  • When the bot is added to a conversation.
  • Other members are added to or removed from a conversation.
  • Conversation metadata has changed.

The conversationUpdate event is sent to your bot when it receives information on membership updates for teams where it has been added. It also receives an update when it has been added for the first time for personal conversations.

The following table shows a list of Teams conversation update events with more details:

Action taken EventType Method called Description Scope
Channel created channelCreated OnTeamsChannelCreatedAsync A channel is created. Team
Channel renamed channelRenamed OnTeamsChannelRenamedAsync A channel is renamed. Team
Channel deleted channelDeleted OnTeamsChannelDeletedAsync A channel is deleted. Team
Channel restored channelRestored OnTeamsChannelRestoredAsync A channel is restored. Team
Members added membersAdded OnTeamsMembersAddedAsync A member is added. All
Members removed membersRemoved OnTeamsMembersRemovedAsync A member is removed. All
Team renamed teamRenamed OnTeamsTeamRenamedAsync A team is renamed. Team
Team deleted teamDeleted OnTeamsTeamDeletedAsync A team is deleted. Team
Team archived teamArchived OnTeamsTeamArchivedAsync A team is archived. Team
Team unarchived teamUnarchived OnTeamsTeamUnarchivedAsync A team is unarchived. Team
Team restored teamRestored OnTeamsTeamRestoredAsync A team is restored Team

Channel created

The channelCreated event is sent to your bot whenever a new channel is created in a team where your bot is installed.

The following code shows an example of a channel created event:

protected override async Task OnTeamsChannelCreatedAsync(ChannelInfo channelInfo, TeamInfo teamInfo, ITurnContext<IConversationUpdateActivity> turnContext, CancellationToken cancellationToken)
{
    var heroCard = new HeroCard(text: $"{channelInfo.Name} is the Channel created");
    // Sends an activity to the sender of the incoming activity.
    await turnContext.SendActivityAsync(MessageFactory.Attachment(heroCard.ToAttachment()), cancellationToken);
}

Channel renamed

The channelRenamed event is sent to your bot whenever a channel is renamed in a team where your bot is installed.

The following code shows an example of a channel renamed event:

protected override async Task OnTeamsChannelRenamedAsync(ChannelInfo channelInfo, TeamInfo teamInfo, ITurnContext<IConversationUpdateActivity> turnContext, CancellationToken cancellationToken)
{
    var heroCard = new HeroCard(text: $"{channelInfo.Name} is the new Channel name");
    // Sends an activity to the sender of the incoming activity.
    await turnContext.SendActivityAsync(MessageFactory.Attachment(heroCard.ToAttachment()), cancellationToken);
}

Channel deleted

The channelDeleted event is sent to your bot, whenever a channel is deleted in a team where your bot is installed.

The following code shows an example of a channel deleted event:

protected override async Task OnTeamsChannelDeletedAsync(ChannelInfo channelInfo, TeamInfo teamInfo, ITurnContext<IConversationUpdateActivity> turnContext, CancellationToken cancellationToken)
{
    var heroCard = new HeroCard(text: $"{channelInfo.Name} is the Channel deleted");
    await turnContext.SendActivityAsync(MessageFactory.Attachment(heroCard.ToAttachment()), cancellationToken);
}

Channel restored

The channelRestored event is sent to your bot, whenever a channel that was previously deleted is restored in a team where your bot is already installed.

The following code shows an example of a channel restored event:

protected override async Task OnTeamsChannelRestoredAsync(ChannelInfo channelInfo, TeamInfo teamInfo, ITurnContext<IConversationUpdateActivity> turnContext, CancellationToken cancellationToken)
{
    var heroCard = new HeroCard(text: $"{channelInfo.Name} is the Channel restored.");
    await turnContext.SendActivityAsync(MessageFactory.Attachment(heroCard.ToAttachment()), cancellationToken);
}

Members added

A member added event is sent to your bot in the following scenarios:

  1. When the bot, itself, is installed and added to a conversation

    In team context, the activity's conversation.id is set to the id of the channel selected by the user during app installation or the channel where the bot was installed.

  2. When a user is added to a conversation where the bot is installed

    User ids received in the event payload are unique to the bot and can be cached for future use, such as directly messaging a user.

The member added activity eventType is set to teamMemberAdded when the event is sent from a team context. To determine if the new member added was the bot itself or a user, check the Activity object of the turnContext. If the MembersAdded list contains an object where id is the same as the id field of the Recipient object, then the member added is the bot, else it's a user. The bot's id is formatted as 28:<MicrosoftAppId>.

Tip

Use the InstallationUpdate event to determine when your bot is added or removed from a conversation.

The following code shows an example of a team members added event:

protected override async Task OnTeamsMembersAddedAsync(IList<TeamsChannelAccount> teamsMembersAdded , TeamInfo teamInfo, ITurnContext<IConversationUpdateActivity> turnContext, CancellationToken cancellationToken)
{
    foreach (TeamsChannelAccount member in teamsMembersAdded)
    {
        if (member.Id == turnContext.Activity.Recipient.Id)
        {
            // Send a message to introduce the bot to the team.
            var heroCard = new HeroCard(text: $"The {member.Name} bot has joined {teamInfo.Name}");
            // Sends an activity to the sender of the incoming activity.
            await turnContext.SendActivityAsync(MessageFactory.Attachment(heroCard.ToAttachment()), cancellationToken);
        }
        else
        {
            var heroCard = new HeroCard(text: $"{member.Name} joined {teamInfo.Name}");
            // Sends an activity to the sender of the incoming activity.
            await turnContext.SendActivityAsync(MessageFactory.Attachment(heroCard.ToAttachment()), cancellationToken);
        }
    }
}

Members removed

A member removed event is sent to your bot in the following scenarios:

  1. When the bot, itself, is uninstalled and removed from a conversation.
  2. When a user is removed from a conversation where the bot is installed.

The member removed activity eventType is set to teamMemberRemoved when the event is sent from a team context. To determine if the new member removed was the bot itself or a user, check the Activity object of the turnContext. If the MembersRemoved list contains an object where id is the same as the id field of the Recipient object, then the member added is the bot, else it's a user. The bot's id is formatted as 28:<MicrosoftAppId>.

Note

When a user is permanently deleted from a tenant, membersRemoved conversationUpdate event is triggered.

The following code shows an example of a team members removed event:

protected override async Task OnTeamsMembersRemovedAsync(IList<ChannelAccount> membersRemoved, TeamInfo teamInfo, ITurnContext<IConversationUpdateActivity> turnContext, CancellationToken cancellationToken)
{
    foreach (TeamsChannelAccount member in membersRemoved)
    {
        if (member.Id == turnContext.Activity.Recipient.Id)
        {
            // The bot was removed.
            // You should clear any cached data you have for this team.
        }
        else
        {
            var heroCard = new HeroCard(text: $"{member.Name} was removed from {teamInfo.Name}");
            // Sends an activity to the sender of the incoming activity.
            await turnContext.SendActivityAsync(MessageFactory.Attachment(heroCard.ToAttachment()), cancellationToken);
        }
    }
}

Team renamed

Your bot is notified when the team is renamed. It receives a conversationUpdate event with eventType.teamRenamed in the channelData object.

The following code shows an example of a team renamed event:

protected override async Task OnTeamsTeamRenamedAsync(TeamInfo teamInfo, ITurnContext<IConversationUpdateActivity> turnContext, CancellationToken cancellationToken)
{
    var heroCard = new HeroCard(text: $"{teamInfo.Name} is the new Team name");
    // Sends an activity to the sender of the incoming activity.
    await turnContext.SendActivityAsync(MessageFactory.Attachment(heroCard.ToAttachment()), cancellationToken);
}

Team deleted

The bot receives a notification when the team is deleted. It receives a conversationUpdate event with eventType.teamDeleted in the channelData object.

The following code shows an example of a team deleted event:

protected override async Task OnTeamsTeamDeletedAsync(TeamInfo teamInfo, ITurnContext<IConversationUpdateActivity> turnContext, CancellationToken cancellationToken)
{
    // Handle delete event.
}

Team restored

The bot receives a notification when a team is restored after being deleted. It receives a conversationUpdate event with eventType.teamrestored in the channelData object.

The following code shows an example of a team restored event:

protected override async Task OnTeamsTeamrestoredAsync(TeamInfo teamInfo, ITurnContext<IConversationUpdateActivity> turnContext, CancellationToken cancellationToken)
{
    var heroCard = new HeroCard(text: $"{teamInfo.Name} is the team name");
    // Sends an activity to the sender of the incoming activity.
    await turnContext.SendActivityAsync(MessageFactory.Attachment(heroCard.ToAttachment()), cancellationToken);
}

Team archived

The bot receives a notification when the team is installed and archived. It receives a conversationUpdate event with eventType.teamarchived in the channelData object.

The following code shows an example of team archived event:

protected override async Task OnTeamsTeamArchivedAsync(TeamInfo teamInfo, ITurnContext<IConversationUpdateActivity> turnContext, CancellationToken cancellationToken)
{
    var heroCard = new HeroCard(text: $"{teamInfo.Name} is the team name");
     // Sends an activity to the sender of the incoming activity.
    await turnContext.SendActivityAsync(MessageFactory.Attachment(heroCard.ToAttachment()), cancellationToken);
}

Team unarchived

The bot receives a notification when the team is installed and unarchived. It receives a conversationUpdate event with eventType.teamUnarchived in the channelData object.

The following code shows an example of a team unarchived event:

protected override async Task OnTeamsTeamUnarchivedAsync(TeamInfo teamInfo, ITurnContext<IConversationUpdateActivity> turnContext, CancellationToken cancellationToken)
{
    var heroCard = new HeroCard(text: $"{teamInfo.Name} is the team name");
    // Sends an activity to the sender of the incoming activity.
    await turnContext.SendActivityAsync(MessageFactory.Attachment(heroCard.ToAttachment()), cancellationToken);
}

Now that you've worked with the conversation update events, you can understand the message reaction events that occur for different reactions to a message.

Message reaction events

The messageReaction event is sent when a user adds or removes reactions to a message, which was sent by your bot. The replyToId contains the ID of the message, and the Type is the type of reaction in text format. The types of reactions include angry, heart, laugh, like, sad, and surprised. This event doesn't contain the contents of the original message. If processing reactions to your messages is important for your bot, you must store the messages when you send them. The following table provides more information about the event type and payload objects:

EventType Payload object Description Scope
messageReaction reactionsAdded Reactions added to bot message. All
messageReaction reactionsRemoved Reactions removed from bot message. All

Reactions added to bot message

The following code shows an example of reactions to a bot message:

protected override async Task OnReactionsAddedAsync(IList<MessageReaction> messageReactions, ITurnContext<IMessageReactionActivity> turnContext, CancellationToken cancellationToken)
{
    foreach (var reaction in messageReactions)
    {
      var newReaction = $"You reacted with '{reaction.Type}' to the following message: '{turnContext.Activity.ReplyToId}'";
      var replyActivity = MessageFactory.Text(newReaction);
      // Sends an activity to the sender of the incoming activity.
      var resourceResponse = await turnContext.SendActivityAsync(replyActivity, cancellationToken);
    }
}

Reactions removed from bot message

The following code shows an example of reactions removed from bot message:

protected override async Task OnReactionsRemovedAsync(IList<MessageReaction> messageReactions, ITurnContext<IMessageReactionActivity> turnContext, CancellationToken cancellationToken)
{
    foreach (var reaction in messageReactions)
    {
      var newReaction = $"You removed the reaction '{reaction.Type}' from the following message: '{turnContext.Activity.ReplyToId}'";

      var replyActivity = MessageFactory.Text(newReaction);
      // Sends an activity to the sender of the incoming activity.
      var resourceResponse = await turnContext.SendActivityAsync(replyActivity, cancellationToken);
    }
}

Installation update event

The bot receives an installationUpdate event when you install a bot to a conversation thread. Uninstallation of the bot from the thread also triggers the event. On installing a bot, the action field in the event is set to add, and when the bot is uninstalled the action field is set to remove.

Note

When you upgrade an application, the bot receives the installationUpdate event only to add or remove a bot from the manifest. For all other cases, the installationUpdate event isn't triggered. The action field is set to add-upgrade if you add a bot or remove-upgrade if you remove a bot.

Install update event

Use the installationUpdate event to send an introductory message from your bot on installation. This event helps you to meet your privacy and data retention requirements. You can also clean up and delete user or thread data when the bot is uninstalled.

Similar to the conversationUpdate event that's sent when bot is added to a team, the conversation.id of the installationUpdate event is set to the id of the channel selected by a user during app installation or the channel where the installation occurred. The id represents the channel where the user intends for the bot to operate and must be used by the bot when sending a welcome message. For scenarios where the ID of the General channel is explicitly required, you can get it from team.id in channelData.

In this example, the conversation.id of the conversationUpdate and installationUpdate activities is set to the ID of the Response channel in the Daves Demo team.

Create a selected channel

Note

The selected channel id is only set on installationUpdate add events that are sent when an app is installed into a team.

protected override async Task OnInstallationUpdateActivityAsync(ITurnContext<IInstallationUpdateActivity> turnContext, CancellationToken cancellationToken)
{
    var activity = turnContext.Activity;
    if (string.Equals(activity.Action, "Add", StringComparison.InvariantCultureIgnoreCase))
    {
        // TO:DO Installation workflow.
    }
    else
    {
        // TO:DO Uninstallation workflow.
    }
    return;
}

You can also use a dedicated handler for add or remove scenarios as an alternative method to capture an event.

protected override async Task OnInstallationUpdateAddAsync(ITurnContext<IInstallationUpdateActivity> turnContext, CancellationToken cancellationToken)
{
    // TO:DO Installation workflow return;
}

Uninstall behavior for personal app with bot

When you uninstall an app, the bot is also uninstalled. When a user sends a message to your app, they receive a 403 response code. Your bot receives a 403 response code for new messages posted by your bot. The post uninstall behavior for bots in the personal scope with the Teams and groupChat scopes are now aligned. You can't send or receive messages after an app has been uninstalled.

Uninstall response code

Event handling for install and uninstall events

When you use the install and uninstall events, there are some instances where bots give exceptions on receiving unexpected events from Teams, which occurs in the following cases:

  • You build your bot without the Microsoft Bot Framework SDK, and as a result the bot gives an exception on receiving an unexpected event.
  • You build your bot with the Microsoft Bot Framework SDK, and you select to alter the default event behavior by overriding the base event handle.

It's important to know that new events can be added anytime in the future and your bot begins to receive them. So you must design for the possibility of receiving unexpected events. If you're using the Bot Framework SDK, your bot automatically responds with a 200 – OK to any events you don't choose to handle.

Handling errors in conversation events

When a bot encounters an error while handling different events or activities, don't send messages that have no meaningful context to the conversation as shown in the following screenshot:

Screenshot shows you the error message response in bot conversation.

In the development phase, it's always helpful to send meaningful messages in conversations, which provide additional details about a specific error for better debugging. However, in the production environment, you must log the errors or events to Azure Application Insights. For more information, see Add telemetry to your bot.

Code sample

Sample Name Description .NET Node.js Python Manifest
Conversation bot This sample shows how to use different bot conversation events available in Bot Framework v4 for personal and teams scope. View View View View

Next step

See also