Mainstream messaging
Microsoft Teams manifest and permissions
The Teams app manifest, the resource-specific consent permissions it declares, and the Microsoft Graph permissions that unlock media and history.
Current Teams RSC permissions (manifest)
These are the existing resourceSpecific permissions in our Teams app manifest. They only apply inside the team/chat where the app is installed.
For channels (team scope):
ChannelMessage.Read.Group(Application) - receive all channel messages without @mentionChannelMessage.Send.Group(Application)Member.Read.Group(Application)Owner.Read.Group(Application)ChannelSettings.Read.Group(Application)TeamMember.Read.Group(Application)TeamSettings.Read.Group(Application)
For group chats:
ChatMessage.Read.Chat(Application) - receive all group chat messages without @mention
Add RSC permissions via the Teams CLI:
teams app rsc add <teamsAppId> ChannelMessage.Read.Group --type ApplicationExample Teams manifest (redacted)
Minimal, valid example with the required fields. Replace IDs and URLs.
{ $schema: "https://developer.microsoft.com/en-us/json-schemas/teams/v1.23/MicrosoftTeams.schema.json", manifestVersion: "1.23", version: "1.0.0", id: "00000000-0000-0000-0000-000000000000", name: { short: "OpenClaw" }, developer: { name: "Your Org", websiteUrl: "https://example.com", privacyUrl: "https://example.com/privacy", termsOfUseUrl: "https://example.com/terms", }, description: { short: "OpenClaw in Teams", full: "OpenClaw in Teams" }, icons: { outline: "outline.png", color: "color.png" }, accentColor: "#5B6DEF", bots: [ { botId: "11111111-1111-1111-1111-111111111111", scopes: ["personal", "team", "groupChat"], isNotificationOnly: false, supportsCalling: false, supportsVideo: false, supportsFiles: true, }, ], webApplicationInfo: { id: "11111111-1111-1111-1111-111111111111", }, authorization: { permissions: { resourceSpecific: [ { name: "ChannelMessage.Read.Group", type: "Application" }, { name: "ChannelMessage.Send.Group", type: "Application" }, { name: "Member.Read.Group", type: "Application" }, { name: "Owner.Read.Group", type: "Application" }, { name: "ChannelSettings.Read.Group", type: "Application" }, { name: "TeamMember.Read.Group", type: "Application" }, { name: "TeamSettings.Read.Group", type: "Application" }, { name: "ChatMessage.Read.Chat", type: "Application" }, ], }, },}Manifest caveats (must-have fields)
bots[].botIdmust match the Azure Bot App ID.webApplicationInfo.idmust match the Azure Bot App ID.bots[].scopesmust include the surfaces you plan to use (personal,team,groupChat).bots[].supportsFiles: trueis required for file handling in personal scope.authorization.permissions.resourceSpecificmust include channel read/send for channel traffic.
Updating an existing app
# Download, edit, and re-upload the manifestteams app manifest download <teamsAppId> manifest.json# Edit manifest.json locally...teams app manifest upload manifest.json <teamsAppId># Version is auto-bumped if content changedAfter updating, reinstall the app in each team, and fully quit and relaunch Teams (not just close the window) to clear cached app metadata.
Manual manifest update (without CLI)
- Update
manifest.jsonwith the new settings. - Increment the
versionfield (e.g.,1.0.0→1.1.0). - Re-zip the manifest with icons (
manifest.json,outline.png,color.png). - Upload the new zip:
- Teams Admin Center: Teams apps → Manage apps → find your app → Upload new version.
- Sideload: Teams → Apps → Manage your apps → Upload a custom app.
Capabilities: RSC only vs Graph
With Teams RSC only (app installed, no Graph API permissions)
Works:
- Read channel message text content.
- Send channel message text content.
- Receive personal (DM) file attachments.
Does NOT work:
- Channel/group image or file contents (payload only includes an HTML stub).
- Downloading attachments stored in SharePoint/OneDrive.
- Reading message history beyond the live webhook event.
With Teams RSC + Microsoft Graph Application permissions
Adds:
- Downloading hosted content (images pasted into messages).
- Downloading file attachments stored in SharePoint/OneDrive.
- Reading channel/chat message history via Graph.
RSC vs Graph API
| Capability | RSC permissions | Graph API |
|---|---|---|
| Real-time messages | Yes (via webhook) | No (polling only) |
| Historical messages | No | Yes (can query history) |
| Setup complexity | App manifest only | Requires admin consent + token flow |
| Works offline | No (must be running) | Yes (query anytime) |
Bottom line: RSC is for real-time listening; Graph API is for historical access. To catch up on missed messages while offline, you need Graph API with ChannelMessage.Read.All (requires admin consent).
Graph-enabled media + history
Enable only the Microsoft Graph application permissions needed for the Teams scopes and data you use:
- Entra ID (Azure AD) App Registration → add Graph Application permissions:
ChannelMessage.Read.Allfor channel attachments and channel history.Chat.Read.Allfor group-chat attachments and group-chat history.Files.Read.Allwhen attachment bytes must be downloaded from SharePoint/OneDrive storage; history-only setups do not need it.
- Grant admin consent for the tenant.
- Bump the Teams app manifest version, re-upload, and reinstall the app in Teams.
- Fully quit and relaunch Teams to clear cached app metadata.
Channel/group file recovery (graphMediaFallback)
Teams can remove file markers from the HTML activity sent to a bot. In that case, the Bot Framework activity is indistinguishable from an ordinary HTML message; the complete attachment reference exists only on the Graph copy of the message.
Enable the fallback after granting the permissions above:
{ channels: { msteams: { graphMediaFallback: true, }, },}This applies to channels and group chats only. It adds one Graph message lookup whenever an HTML activity produced no directly downloadable media, including ordinary or mention-only messages. The default is false so existing installations do not gain extra Graph traffic or permission errors automatically.
User mentions: @mentions work out of the box for users already in the conversation. To dynamically search and mention users not in the current conversation, add User.Read.All (Application) permission and grant admin consent.