Skip to content

Support for bots and agents in shared channels #179

@arocc

Description

@arocc

We are working on bringing apps to shared channels, including bots and agents. Unlike standard channels, shared channels allow adding members from outside of the host team. More information on shared channels can be found here: Shared channels in Microsoft Teams.

As part of this work, new events are needed to notify developers that a channel has been shared or unshared with another team and existing events should also include updated information. Additionally, since members can belong to multiple teams, an additional optional property is needed in the ChannelAccount class to specify the "source" team.

New events

  1. A shared channel is shared with a team
  2. A shared channel is unshared with a team

Updates to existing events

  1. Bot is allowed in a shared channel - bots/agents are installed at the team level and then are "allowed"/"disallowed" at the shared channel level. For allowing a bot, this will be a membersAdded event.
  2. Bot is disallowed in a shared channel - similar to (1), disallowing a bot/agent will be a membersRemoved event
  3. Rename shared channel
  4. Delete shared channel
  5. Restore shared channel
  6. User member is added to shared channel
  7. User member is removed from a shared channel

API response updates

  • GetConversationMember - indicate the teams and/or shared channel that a member belongs to
  • GetConversationMembers - distinguish duplicate members who have access via more than one team or the shared channel itself

Example payloads - New Events

1. A shared channel is shared with a team

{
    **"type": "conversationUpdate",**
    "timestamp": "2025-05-07T06:01:00.1524479Z",
    "id": "f:ac6b6978-89f4-47f4-a2d0-816b8c7cc578",
    "channelId": "msteams",
    "serviceUrl": "",
    "from": {
        "id": "29:id",
        "aadObjectId": "9da619c7-3645-413e-ab27-75baef969048"
    },
    "conversation": {
        "isGroup": true,
        "conversationType": "channel",
        "tenantId": "476ca735-cce2-462b-b69e-f7284b54fab0",
        "id": "19:[email protected]"
    },
    "recipient": {
        "id": "28:id",
        "name": "Test Bot"
    },
    **"channelData": {
        "channel": {
            "name": "Shared Channel",
            "id": "19:[email protected]",
            “type”: “shared”
        },
        "team": {
            "id": "19:[email protected]"                                    //host team
        },
        "eventType": "**channelShared**",
        **"sharedWithTeams": [{
            "id": "19:[email protected]",                                   //member team
            "tenantId": "5fe39b5d-6cfe-44dd-ad5c-b5cab4f0a2e2"
        }]**,
        "tenant": {
            "id": "476ca735-cce2-462b-b69e-f7284b54fab0"
        }
    }**
}

2. A shared channel is unshared with a team

{
    **"type": "conversationUpdate",**
    "timestamp": "2025-05-07T06:01:00.1524479Z",
    "id": "f:ac6b6978-89f4-47f4-a2d0-816b8c7cc578",
    "channelId": "msteams",
    "serviceUrl": "",
    "from": {
        "id": "29:id",
        "aadObjectId": "9da619c7-3645-413e-ab27-75baef969048"
    },
    "conversation": {
        "isGroup": true,
        "conversationType": "channel",
        "tenantId": "476ca735-cce2-462b-b69e-f7284b54fab0",
        "id": "19:[email protected]"
    },
    "recipient": {
        "id": "28:id",
        "name": "Test Bot"
    },
    **"channelData": {
        "channel": {
            "name": "Shared Channel",
            "id": "19:[email protected]",
            “type”: “shared”
        },
        "team": {
            "id": "19:[email protected]"
        },
        "eventType": "**channelUnshared**”,
        **"unsharedFromTeams": [{
            "id": "19:[email protected]",                                   //member team
            "tenantId": "5fe39b5d-6cfe-44dd-ad5c-b5cab4f0a2e2"
        }]**,
        "tenant": {
            "id": "476ca735-cce2-462b-b69e-f7284b54fab0"
        }
    }**
}

Example payloads - Existing Events

1. Bot is allowed in a shared channel

{
    **"membersAdded": [
        {
            "id": "28:id"
        }
    ],
    "type": "conversationUpdate",**
    "timestamp": "2025-05-07T05:29:08.2280646Z",
    "id": "f:ac6b6978-89f4-47f4-a2d0-816b8c7cc578",
    "channelId": "msteams",
    "serviceUrl": "https://....",
    "from": {
        "id": "29:id"
    },
    "conversation": {
        "isGroup": true,
        "conversationType": "channel",
        "tenantId": "476ca735-cce2-462b-b69e-f7284b54fab0",
        "id": "19:[email protected]"
    },
    "recipient": {
        "id": "28:id",
        "name": "Test Bot"
    },
    **"channelData": {
        "channel": {
            "type": "shared",
            "name": "Shared Channel Rename",
            "id": "19:[email protected]"
        },
        "team": {
            "id": "19:[email protected]"
        },
        **"eventType": "channelMemberAdded",**
        "tenant": {
            "id": "476ca735-cce2-462b-b69e-f7284b54fab0"
        }
    }**
}

2. Bot is disallowed in a shared channel

{
    **"membersRemoved": [
        {
            "id": "28:id"
        }
    ],
    "type": "conversationUpdate",**
    "timestamp": "2025-05-07T05:29:02.0744219Z",
    "id": "f:ac6b6978-89f4-47f4-a2d0-816b8c7cc578",
    "channelId": "msteams",
    "serviceUrl": "https://....",
    "from": {
        "id": "29:id",
        "aadObjectId": "9da619c7-3645-413e-ab27-75baef969048"
    },
    "conversation": {
        "isGroup": true,
        "conversationType": "channel",
        "tenantId": "476ca735-cce2-462b-b69e-f7284b54fab0",
        "id": "19:[email protected]"
    },
    "recipient": {
        "id": "28:id",
        "name": "Test Bot"
    },
    **"channelData": {
        "channel": {
            "type": "shared",
            "name": "Shared Channel",
            "id": "19:[email protected]"
        },
        "team": {
            "id": "19:[email protected]"
        },
        **"eventType": "channelMemberRemoved",**
        "tenant": {
            "id": "476ca735-cce2-462b-b69e-f7284b54fab0"
        }
    }**
}

3. Rename shared channel

{
    **"type": "conversationUpdate",**
    "timestamp": "2025-05-07T06:18:45.3313237Z",
    "id": "f:ac6b6978-89f4-47f4-a2d0-816b8c7cc578",
    "channelId": "msteams",
    "serviceUrl": "https://....",
    "from": {
        "id": "29:id",
        "aadObjectId": "9da619c7-3645-413e-ab27-75baef969048"
    },
    "conversation": {
        "isGroup": true,
        "conversationType": "channel",
        "tenantId": "476ca735-cce2-462b-b69e-f7284b54fab0",
        "id": "19:[email protected]"
    },
    "recipient": {
        "id": "28:id",
        "name": "Test Bot"
    },
    **"channelData": {
        "channel": {
            "type": "shared",
            "name": "Shared Channel Rename",
            "id": "19:[email protected]"
        },
        "team": {
            "id": "19:[email protected]"
        },
        "eventType": "channelRenamed",
        "tenant": {
            "id": "476ca735-cce2-462b-b69e-f7284b54fab0"
        }
    }**
}

4. Delete shared channel

{
    **"type": "conversationUpdate",**
    "timestamp": "2025-05-07T07:18:38.382751Z",
    "id": "f:ac6b6978-89f4-47f4-a2d0-816b8c7cc578",
    "channelId": "msteams",
    "serviceUrl": "https://.....",
    "from": {
        "id": "29:id",
        "aadObjectId": "9da619c7-3645-413e-ab27-75baef969048"
    },
    "conversation": {
        "isGroup": true,
        "conversationType": "channel",
        "tenantId": "476ca735-cce2-462b-b69e-f7284b54fab0",
        "id": "19:[email protected]"
    },
    "recipient": {
        "id": "28:id",
        "name": "Test Bot"
    },
    **"channelData": {
        "channel": {
            "name": "Shared Channel",
            "id": "19:[email protected]",
            “type”: “shared”
        },
        "team": {
            "id": "19:[email protected]"
        },
        "eventType": "channelDeleted",
        "tenant": {
            "id": "476ca735-cce2-462b-b69e-f7284b54fab0"
        }
    }**
}

5. Restore shared channel

{
    **"type": "conversationUpdate",**
    "timestamp": "2025-05-07T07:22:01.5677871Z",
    "id": "f:ac6b6978-89f4-47f4-a2d0-816b8c7cc578",
    "channelId": "msteams",
    "serviceUrl": "https://...",
    "from": {
        "id": "29:id",
        "aadObjectId": "9da619c7-3645-413e-ab27-75baef969048"
    },
    "conversation": {
        "isGroup": true,
        "conversationType": "channel",
        "tenantId": "476ca735-cce2-462b-b69e-f7284b54fab0",
        "id": "19:[email protected]"
    },
    "recipient": {
        "id": "28:id",
        "name": "Test Bot"
    },
    **"channelData": {
        "channel": {
            "type": "shared",
            "name": "Shared Channel",
            "id": "19:[email protected]"
        },
        "team": {
            "id": "19:[email protected]"
        },
        "eventType": "channelRestored",
        "tenant": {
            "id": "476ca735-cce2-462b-b69e-f7284b54fab0"
        }
    }**
}

6. User member is added to shared channel (direct)

{
  **"type": "conversationUpdate",**
 "id": "",
  "timestamp": "2025-05-29T21:55:47.9785441+00:00",
  "serviceUrl": "",
  "channelId": "msteams",
  "from": {
    "id": "29:id",
    "aadObjectId": ""
  },
  "conversation": { //shared channel
    "isGroup": true,
    "conversationType": "channel",
    "id": "19:id",
    "tenantId": ""
  },
  "recipient": { //receive bot
    "id": "28:id",
    "name": "Test Bot"
  },
  **"membersAdded": [
    {
      "id": "29:id",
      "aadObjectId": ""
    },
     }],**
  "channelData": {
    "channel": {                                   //shared channel
      **"type": "shared",**
      "name": "SCTest",
      "id": "19:[email protected]"
    },
    **"team": {**                                    //host team
      "id": "19:[email protected]",
},
// direct member in shared channel
   **“membershipSource”: {**  
      **"sourceType": "channel",**
        **"id": "19:[email protected]",**
      **“membershipType”: “direct”,**
      **“tenantId”:”3fee1829-7ae5-45d0-a29d-0c924adb25f1”**
     }** 
   **"eventType": "channelMemberAdded",**
   **"tenant": { "id": "3fee1829-7ae5-45d0-a29d-0c924adb25f1" } //Shared channel tenant**
  }
}

7. User member is added to shared channel (transitive)

{
  **"type": "conversationUpdate",**
 "id": "",
  "timestamp": "2025-05-29T21:55:47.9785441+00:00",
  "serviceUrl": "",
  "channelId": "msteams",
  "from": {
    "id": "29:id",
    "aadObjectId": ""
  },
  "conversation": { //shared channel
    "isGroup": true,
    "conversationType": "channel",
    "id": "19:id",
    "tenantId": ""
  },
  "recipient": { //receive bot
    "id": "28:id",
    "name": "Test Bot"
  },
  **"membersAdded": [
    {
      "id": "29:id",
      "aadObjectId": ""
    },
     }],**
  "channelData": {
    "channel": {                                   //shared channel
      **"type": "shared",**
      "name": "SCTest",
      "id": "19:[email protected]"
    },
    **"team": {**                                    //host team
      "id": "19:[email protected]",
},
// transitive member in shared channel   
   **“membershipSource”: {**  
      **"sourceType": "team",**
        **"id": "19:[email protected]",**
      **“membershipType”: “transitive”,**                         
      **“tenantId”:” 0f8276ea-111b-46af-9512-79ce81d5dea1”** 
     }** 
   **"eventType": "channelMemberAdded",**
   **"tenant": { "id": "3fee1829-7ae5-45d0-a29d-0c924adb25f1" } //Shared channel tenant**
  }
}

8. User member is removed from a shared channel (direct)

{
  "type": "conversationUpdate",
 "id": "",
  "timestamp": "2025-05-29T21:55:47.9785441+00:00",
  "serviceUrl": "",
  "channelId": "msteams",
  "from": {
    "id": "29:id",
    "aadObjectId": ""
  },
  "conversation": { //shared channel
    "isGroup": true,
    "conversationType": "channel",
    "id": "19:id",
    "tenantId": ""
  },
  "recipient": { //receive bot
    "id": "28:id",
    "name": "Test Bot"
  },
  "membersRemoved": [
    {
      "id": "29:id",
      "aadObjectId": ""
    },
     }],
  "channelData": {
    "channel": {                                   //shared channel
      "type": "shared",
      "name": "SCTest",
      "id": "19:[email protected]"
    },
    "team": {                                    //host team
      "id": "19:[email protected]",
},
// direct member in shared channel
   **“membershipSource”: {
      "sourceType": "team",
        "id": "19:[email protected]",
      “membershipType”: “direct”, // direct
      “tenantId”:”3fee1829-7ae5-45d0-a29d-0c924adb25f1”
     }** 
   "eventType": "channelMemberRemoved",
   "tenant": { "id": "3fee1829-7ae5-45d0-a29d-0c924adb25f1" } //Shared channel tenant
  }
}

9. User member is removed from a shared channel (transitive)

{
  "type": "conversationUpdate",
 "id": "",
  "timestamp": "2025-05-29T21:55:47.9785441+00:00",
  "serviceUrl": "",
  "channelId": "msteams",
  "from": {
    "id": "29:id",
    "aadObjectId": ""
  },
  "conversation": { //shared channel
    "isGroup": true,
    "conversationType": "channel",
    "id": "19:id",
    "tenantId": ""
  },
  "recipient": { //receive bot
    "id": "28:id",
    "name": "Test Bot"
  },
  "membersRemoved": [
    {
      "id": "29:id",
      "aadObjectId": ""
    },
     }],
  "channelData": {
    "channel": {                                   //shared channel
      "type": "shared",
      "name": "SCTest",
      "id": "19:[email protected]"
    },
    "team": {                                    //host team
      "id": "19:[email protected]",
},
// transitive member in shared channel   
   “membershipSource”: {  
      "sourceType": "team",
        "id": "19:[email protected]",
      “membershipType”: “transitive”,                                
      “tenantId”:” 0f8276ea-111b-46af-9512-79ce81d5dea1” 
     } 
   "eventType": "channelMemberRemoved",
   "tenant": { "id": "3fee1829-7ae5-45d0-a29d-0c924adb25f1" } //Shared channel tenant
  }
}

Example payloads - Existing API responses

1. GetConversationMember

{
  "givenName": "Adele",
  "surname": "Vance",
  "email": "",
  "userPrincipalName": "",
  "userRole": "user",
  "tenantId": "",
  "objectId": "",
  "id": "29:id",
  "name": "Adele Vance",
  "aadObjectId": "",
  “membershipSources”: [
      {
	“id”: "19:[email protected]",
	“aadGroupId”: “19:id@tacv2"
	“sourceType”: “team”,
	“membershipType”: “transitive”
     },
      {
	“id”: "19:id",
	“sourceType”: “channel”,
	“membershipType”: “direct”
     },
}]

2. GetConversationMembers

{
  "members": [
    {
      "givenName": "Adele",
      "surname": "Vance",
      "email": "",
      "userPrincipalName": "",
      "userRole": "user",
      "tenantId": "",
      "objectId": "",
      "id": "29:id",
      "name": "Adele Vance",
      "aadObjectId": "",
      "membershipSources": [
           {
                “id”: "19:[email protected]",	    //direct membership
                “sourceType”: “channel”,
                “membershipType”: “direct”
          },
        ]
    },
    {
      "givenName": "Adele",
      "surname": "Vance",
      "email": "",
      "userPrincipalName": "",
      "userRole": "user",
      "tenantId": "",
      "objectId": "",
      "id": "29:id",
      "name": "Adele Vance",
      "aadObjectId": "",
      "membershipSources": [
           {
	“id”: "19:[email protected],"	      // transitive membership
	“aadGroupId”: “”, 
	“sourceType”: “team”,
	“membershipType”: “transitive”
          }
      ]
      }

References

Sub-issues

Metadata

Metadata

Assignees

Labels

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions