Handle bot events in Microsoft Teams
Important
This article is based on the v3 Bot Framework SDK. If you are looking for current documentation version 4.6 or later of the SDK, see the conversational bots section.
Microsoft Teams sends notifications to your bot for changes or events that happen in scopes where your bot is active. The following list provides events to trigger service logic:
- Trigger a welcome message when your bot is added to a team.
- Query and cache group information when the bot is added to a group chat.
- Update cached information on team membership or channel information.
- Remove cached information for a team if the bot is removed.
- When a bot message is liked by a user.
Each bot event is sent as an Activity
object in which messageType
defines what information is in the object. For messages of type message
, see Sending and receiving messages.
Teams and group events, triggered off the conversationUpdate
type, have more Teams event information passed as part of the channelData
object, and therefore your event handler must query the channelData
payload for the Teams eventType
and more event-specific metadata.
The following table lists the events that your bot can receive and take action on.
Type | Payload object | Teams eventType | Description | Scope |
---|---|---|---|---|
conversationUpdate |
membersAdded |
teamMemberAdded |
Member added to team | all |
conversationUpdate |
membersRemoved |
teamMemberRemoved |
Member was removed from team | groupChat & team |
conversationUpdate |
teamRenamed |
Team was renamed | team |
|
conversationUpdate |
channelCreated |
A channel was created | team |
|
conversationUpdate |
channelRenamed |
A channel was renamed | team |
|
conversationUpdate |
channelDeleted |
A channel was deleted | team |
|
messageReaction |
reactionsAdded |
Reaction to bot message | all | |
messageReaction |
reactionsRemoved |
Reaction removed from bot message | all |
Team member or bot addition
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 specifically for personal conversations. The user information (Id
) is unique for your bot and can be cached for future use by your service, such as, sending a message to a specific user.
Bot or user added to a team
The conversationUpdate
event with the membersAdded
object in the payload is sent when either a bot is added to a team or a new user is added to a team where a bot has been added. Teams also adds eventType.teamMemberAdded
in the channelData
object.
Because this event is sent in both cases, you should parse the membersAdded
object to determine whether the addition was a user or the bot itself. For the latter, a best practice is to send a welcome message to the channel so users can understand the features your bot provides.
Example code: Checking whether bot was the added member
.NET
for (int i = 0; i < sourceMessage.MembersAdded.Count; i++)
{
if (sourceMessage.MembersAdded[i].Id == sourceMessage.Recipient.Id)
{
addedBot = true;
break;
}
}
Node.js
const builder = require('botbuilder');
var c = new builder.ChatConnector({appId: BOT_APP_ID, appPassword: .BOT_SECRET});
var bot = new builder.UniversalBot(c);
bot.on('conversationUpdate', (msg) => {
var members = msg.membersAdded;
// Loop through all members that were just added to the team
for (var i = 0; i < members.length; i++) {
// See if the member added was our bot
if (members[i].id.includes(BOT_APP_ID)) {
var botmessage = new builder.Message()
.address(msg.address)
.text('Hello World!');
bot.send(botmessage, function(err) {});
}
}
});
Schema example: Bot added to team
{
"membersAdded":[
{
"id":"28:f5d48856-5b42-41a0-8c3a-c5f944b679b0"
}
],
"type":"conversationUpdate",
"timestamp":"2017-02-23T19:38:35.312Z",
"localTimestamp":"2017-02-23T12:38:35.312-07:00",
"id":"f:5f85c2ad",
"channelId":"msteams",
"serviceUrl":"https://smba.trafficmanager.net/amer-client-ss.msg/",
"from":{
"id":"29:1I9Is_Sx0OIy2rQ7Xz1lcaPKlO9eqmBRTBuW6XzkFtcjqxTjPaCMij8BVMdBcL9L_RwWNJyAHFQb0TRzXgyQvA"
},
"conversation":{
"isGroup":true,
"conversationType":"channel",
"id":"19:efa9296d959346209fea44151c742e73@thread.skype"
},
"recipient":{
"id":"28:f5d48856-5b42-41a0-8c3a-c5f944b679b0",
"name":"SongsuggesterBot"
},
"channelData":{
"team":{
"id":"19:efa9296d959346209fea44151c742e73@thread.skype"
},
"eventType":"teamMemberAdded",
"tenant":{
"id":"72f988bf-86f1-41af-91ab-2d7cd011db47"
}
}
}
User Added to a meeting
The conversationUpdate
event with the membersAdded
object in the payload is sent when a user is added to a private scheduled meeting. The event details are sent even when anonymous users join the meeting.
Note
- When an anonymous user is added to a meeting, membersAdded payload object does not have
aadObjectId
field. - When an anonymous user is added to a meeting,
from
object in the payload always have the id of the meeting organizer, even if the anonymous user was added by another presenter.
Schema example: User added to meeting
{
"membersAdded":[
{
"id":"229:1Z_XHWBMhDuehhDBYoPQD6Y1DSFsTtqOZx-SA5Jh9Y4zHKm4VbFGRn7-rK7SWiW1JECwxkMdrWpHoBut2sSyQPA"
}
],
"type":"conversationUpdate",
"timestamp":"2017-02-23T19:38:35.312Z",
"localTimestamp":"2020-09-29T21:11:38.6542339Z",
"id":"f:a8cd1b51-9ddb-bd35-624b-7f7474165df8",
"channelId":"msteams",
"serviceUrl":"https://canary.botapi.skype.com/amer/",
"from":{
"id":"29:1siKxZhSoTapsXvI0gyf7Gywm_HM-4kEQW4BJnWuFYVIVu87xCNP99nidgQRCcwD3L3p_schiMShzx8IDRzf8mw",
"aadObjectId":"f30ba569-abef-4e97-8762-35f85cbae706"
},
"conversation":{
"isGroup":true,
"tenantId":"e15762ef-a8d8-416b-871c-25516354f1fe",
"id":"19:meeting_MWJlNGViOTgtMGExYi00NDA3LWExODgtOTZhMWNlYjM4ZTRj@thread.v2"
},
"recipient":{
"id":"28:3af3604a-d4fc-486b-911e-86fab41aa91c",
"name":"EchoBot1_Rename"
},
"channelData":{
"tenant":{
"id":"e15762ef-a8d8-416b-871c-25516354f1fe"
},
"source":null,
"meeting":{
"id":"MCMxOTptZWV0aW5nX01XSmxOR1ZpT1RndE1HRXhZaTAwTkRBM0xXRXhPRGd0T1RaaE1XTmxZak00WlRSakB0aHJlYWQudjIjMA=="
}
}
}
Bot added for personal context only
Your bot receives a conversationUpdate
with membersAdded
when a user adds it directly for personal chat. In this case, the payload that your bot receives doesn't contain the channelData.team
object. You should use this as a filter in case you want your bot to offer a different welcome message depending on scope.
Note
For personal scoped bots, your bot will receive the conversationUpdate
event multiple times, even if the bot is removed and re-added. For development and testing you may find it useful to add a helper function that will allow you to reset your bot completely. For more information, see Node.js example or C# example for more details on implementing this.
Schema example: bot added to personal context
{
"membersAdded": [{
"id": "28:f5d48856-5b42-41a0-8c3a-c5f944b679b0"
},
{
"id": "29:<userID>",
"aadObjectId": "***"
}
],
"type": "conversationUpdate",
"timestamp": "2019-04-23T10:17:44.349Z",
"id": "f:5f85c2ad",
"channelId": "msteams",
"serviceUrl": "https://smba.trafficmanager.net/amer-client-ss.msg/",
"from": {
"id": "29:<USERID>",
"aadObjectId": "***"
},
"conversation": {
"conversationType": "personal",
"id": "***"
},
"recipient": {
"id": "28:<BOT ID>",
"name": "<BOT NAME>"
},
"channelData": {
"tenant": {
"id": "<TENANT ID>"
}
}
}
Team member or bot removed
The conversationUpdate
event with the membersRemoved
object in the payload is sent when either your bot is removed from a team, or a user is removed from a team where a bot has been added. Teams also adds eventType.teamMemberRemoved
in the channelData
object. As with the membersAdded
object, you should parse the membersRemoved
object for your bot's App ID to determine who was removed.
Schema example: Team member removed
{
"membersRemoved": [
{
"id": "29:1_LCi5Up14pAy65yZuaJzG1uIT7ujYhjjSTsUNqjORsZHjLHKiQIBJa4cX2XsAsRoaY7va2w6ZymA9-1VtSY_g"
}
],
"type": "conversationUpdate",
"timestamp": "2017-02-23T19:37:06.96Z",
"localTimestamp": "2017-02-23T12:37:06.96-07:00",
"id": "f:d8a6a4aa",
"channelId": "msteams",
"serviceUrl": "https://smba.trafficmanager.net/amer-client-ss.msg/",
"from": {
"id": "29:1I9Is_Sx0OIy2rQ7Xz1lcaPKlO9eqmBRTBuW6XzkFtcjqxTjPaCMij8BVMdBcL9L_RwWNJyAHFQb0TRzXgyQvA"
},
"conversation": {
"isGroup": true,
"conversationType": "channel",
"id": "19:efa9296d959346209fea44151c742e73@thread.skype"
},
"recipient":
{
"id": "28:f5d48856-5b42-41a0-8c3a-c5f944b679b0",
"name": "SongsuggesterBot"
},
"channelData": {
"team": {
"id": "19:efa9296d959346209fea44151c742e73@thread.skype"
},
"eventType": "teamMemberRemoved",
"tenant": {
"id": "72f988bf-86f1-41af-91ab-2d7cd011db47"
}
}
}
User removed from a meeting
The conversationUpdate
event with the membersRemoved
object in the payload is sent when a user is removed from a private scheduled meeting. The event details are sent even when anonymous users join the meeting.
Note
- When an anonymous user is removed from a meeting, membersRemoved payload object does not have
aadObjectId
field. - When an anonymous user is removed from a meeting,
from
object in the payload always have the id of the meeting organizer, even if the anonymous user was removed by another presenter.
Schema example: User removed from meeting
{
"membersRemoved":
{
"id": "29:1Z_XHWBMhDuehhDBYoPQD6Y1DSFsTtqOZx-SA5Jh9Y4zHKm4VbFGRn7-rK7SWiW1JECwxkMdrWpHoBut2sSyQPA"
}
],
"type": "conversationUpdate",
"timestamp": "2020-09-29T21:15:08.6391139Z",
"id": "f:ee8dfdf3-54ac-51de-05da-9d49514974bb",
"channelId": "msteams",
"serviceUrl": "https://canary.botapi.skype.com/amer/",
"from": {
"id": "29:1siKxZhSoTapsXvI0gyf7Gywm_HM-4kEQW4BJnWuFYVIVu87xCNP99nidgQRCcwD3L3p_schiMShzx8IDRzf8mw",
"aadObjectId": "f30ba569-abef-4e97-8762-35f85cbae706"
},
"conversation": {
"isGroup": true,
"tenantId": "e15762ef-a8d8-416b-871c-25516354f1fe",
"id": "19:meeting_MWJlNGViOTgtMGExYi00NDA3LWExODgtOTZhMWNlYjM4ZTRj@thread.v2"
},
"recipient": {
"id": "28:3af3604a-d4fc-486b-911e-86fab41aa91c",
"name": "EchoBot1_Rename"
},
"channelData": {
"tenant": {
"id": "e15762ef-a8d8-416b-871c-25516354f1fe"
},
"source": null,
"meeting": {
"id": "MCMxOTptZWV0aW5nX01XSmxOR1ZpT1RndE1HRXhZaTAwTkRBM0xXRXhPRGd0T1RaaE1XTmxZak00WlRSakB0aHJlYWQudjIjMA=="
}
}
}
Team name updates
Note
There is no functionality to query all team names, and team name is not returned in payloads from other events.
Your bot is notified when the team it is in has been renamed. It receives a conversationUpdate
event with eventType.teamRenamed
in the channelData
object. There are no notifications for team creation or deletion, because bots exist only as part of teams and have no visibility outside the scope in which they've been added.
Schema example: Team renamed
{
"type": "conversationUpdate",
"timestamp": "2017-02-23T19:35:56.825Z",
"localTimestamp": "2017-02-23T12:35:56.825-07:00",
"id": "f:1406033e",
"channelId": "msteams",
"serviceUrl": "https://smba.trafficmanager.net/amer-client-ss.msg/",
"from": {
"id": "29:1I9Is_Sx0O-Iy2rQ7Xz1lcaPKlO9eqmBRTBuW6XzkFtcjqxTjPaCMij8BVMdBcL9L_RwWNJyAHFQb0TRzXgyQvA"
},
"conversation": {
"isGroup": true,
"conversationType": "channel",
"id": "19:efa9296d959346209fea44151c742e73@thread.skype"
},
"recipient": {
"id": "28:f5d48856-5b42-41a0-8c3a-c5f944b679b0",
"name": "SongsuggesterLocal"
},
"channelData": {
"team": {
"id": "19:efa9296d959346209fea44151c742e73@thread.skype",
"name": "New Team Name"
},
"eventType": "teamRenamed",
"tenant": {
"id": "72f988bf-86f1-41af-91ab-2d7cd011db47"
}
}
}
Channel updates
Your bot is notified when a channel is created, renamed, or deleted in a team where it has been added. Again, the conversationUpdate
event is received, and a Teams-specific event identifier is sent as part of the channelData.eventType
object, where the channel data's channel.id
is the GUID for the channel, and channel.name
contains the channel name itself.
The channel events are as follows:
- channelCreated A user adds a new channel to the team.
- channelRenamed A user renames an existing channel.
- channelDeleted A user removes a channel.
Full schema example: channelCreated
{
"type": "conversationUpdate",
"timestamp": "2017-02-23T19:34:07.478Z",
"localTimestamp": "2017-02-23T12:34:07.478-07:00",
"id": "f:dd6ec311",
"channelId": "msteams",
"serviceUrl": "https://smba.trafficmanager.net/amer-client-ss.msg/",
"from": {
"id": "29:1wR7IdIRIoerMIWbewMi75JA3scaMuxvFon9eRQW2Nix5loMDo0362st2IaRVRirPZBv1WdXT8TIFWWmlQCizZQ"
},
"conversation": {
"isGroup": true,
"conversationType": "channel",
"id": "19:efa9296d959346209fea44151c742e73@thread.skype"
},
"recipient": {
"id": "28:f5d48856-5b42-41a0-8c3a-c5f944b679b0",
"name": "SongsuggesterBot"
},
"channelData": {
"channel": {
"id": "19:6d97d816470f481dbcda38244b98689a@thread.skype",
"name": "FunDiscussions"
},
"team": {
"id": "19:efa9296d959346209fea44151c742e73@thread.skype"
},
"eventType": "channelCreated",
"tenant": {
"id": "72f988bf-86f1-41af-91ab-2d7cd011db47"
}
}
}
Schema excerpt: channelData for channelRenamed
⋮
"channelData": {
"channel": {
"id": "19:6d97d816470f481dbcda38244b98689a@thread.skype",
"name": "PhotographyUpdates"
},
"team": {
"id": "19:efa9296d959346209fea44151c742e73@thread.skype"
},
"eventType": "channelRenamed",
"tenant": {
"id": "72f988bf-86f1-41af-91ab-2d7cd011db47"
}
}
⋮
Schema excerpt: channelData for channelDeleted
⋮
"channelData": {
"channel": {
"id": "19:6d97d816470f481dbcda38244b98689a@thread.skype",
"name": "PhotographyUpdates"
},
"team": {
"id": "19:efa9296d959346209fea44151c742e73@thread.skype"
},
"eventType": "channelDeleted",
"tenant": {
"id": "72f988bf-86f1-41af-91ab-2d7cd011db47"
}
}
⋮
Reactions
The messageReaction
event is sent when a user adds or removes their reaction to a message, which was originally sent by your bot. replyToId
contains the ID of the specific message.
Schema example: A user likes a message
{
"reactionsAdded": [
{
"type": "like"
}
],
"type": "messageReaction",
"timestamp": "2017-10-16T18:45:41.943Z",
"id": "f:9f78d1f3",
"channelId": "msteams",
"serviceUrl": "https://smba.trafficmanager.net/amer-client-ss.msg/",
"from": {
"id": "29:1I9Is_Sx0O-Iy2rQ7Xz1lcaPKlO9eqmBRTBuW6XzkFtcjqxTjPaCMij8BVMdBcL9L_RwWNJyAHFQb0TRzXgyQvA",
"aadObjectId": "c33aafc4-646d-4543-9d4c-abd28e4d2110"
},
"conversation": {
"isGroup": true,
"conversationType": "channel",
"id": "19:3629591d4b774aa08cb0887902eee7c1@thread.skype"
},
"recipient": {
"id": "28:f5d48856-5b42-41a0-8c3a-c5f944b679b0",
"name": "SongsuggesterLocal"
},
"channelData": {
"channel": {
"id": "19:3629591d4b774aa08cb0887902eee7c1@thread.skype"
},
"team": {
"id": "19:efa9296d959346209fea44151c742e73@thread.skype"
},
"tenant": {
"id": "72f988bf-86f1-41af-91ab-2d7cd011db47"
}
},
"replyToId": "1575667808184"
}
Schema example: A user unlikes a message
{
"reactionsRemoved": [
{
"type": "like"
}
],
"type": "messageReaction",
"timestamp": "2017-10-16T18:45:41.943Z",
"id": "f:9f78d1f3",
"channelId": "msteams",
"serviceUrl": "https://smba.trafficmanager.net/amer-client-ss.msg/",
"from": {
"id": "29:1I9Is_Sx0O-Iy2rQ7Xz1lcaPKlO9eqmBRTBuW6XzkFtcjqxTjPaCMij8BVMdBcL9L_RwWNJyAHFQb0TRzXgyQvA",
"aadObjectId": "c33aafc4-646d-4543-9d4c-abd28e4d2110"
},
"conversation": {
"isGroup": true,
"conversationType": "channel",
"id": "19:3629591d4b774aa08cb0887902eee7c1@thread.skype"
},
"recipient": {
"id": "28:f5d48856-5b42-41a0-8c3a-c5f944b679b0",
"name": "SongsuggesterLocal"
},
"channelData": {
"channel": {
"id": "19:3629591d4b774aa08cb0887902eee7c1@thread.skype"
},
"team": {
"id": "19:efa9296d959346209fea44151c742e73@thread.skype"
},
"tenant": {
"id": "72f988bf-86f1-41af-91ab-2d7cd011db47"
}
},
"replyToId": "1575667808184"
}