OpenClaw

OpenClaw Microsoft Teams Channel

Enterprise
Medium

Connect OpenClaw to Microsoft Teams using the Bot Framework via an Azure Bot Resource. This plugin-based integration lets your AI assistant operate in Teams — handling personal DMs, group chats, and channel conversations. OpenClaw receives webhook events from the Bot Framework at /api/messages and responds through the Teams messaging API, supporting threaded replies, Adaptive Cards, reactions, file sharing via SharePoint, and per-team/per-channel configuration overrides.

Quick Info
DifficultyMedium
CategoryEnterprise
Features Supported5 / 6

Microsoft Teams Supported Features

Text Messages

Supported

Media & Files

Supported

Reactions

Supported

Threads

Supported

Voice Messages

Not Supported

Group Chat

Supported

Microsoft Teams Prerequisites

  • An Azure account with permissions to create an Azure Bot resource
  • A registered Azure Bot with App ID, App Password (client secret), and Tenant ID (single-tenant recommended)
  • A Teams App Manifest (manifest.json) with bot configuration, scopes, and icons (outline.png 32×32, color.png 192×192)
  • OpenClaw Gateway running and accessible via a public HTTPS URL or tunnel (default webhook port 3978)
  • The Teams plugin installed: openclaw plugins install @openclaw/msteams

Microsoft Teams Quick Setup

1

Create an Azure Bot resource

Go to the Azure Portal → Create a resource → Search 'Azure Bot'. Create with Single Tenant type. In the App Registration, generate a client secret. Copy the App ID, client secret, and Tenant ID — you'll need all three for OpenClaw configuration.

2

Install the Teams plugin and configure

Run 'openclaw plugins install @openclaw/msteams' to install the plugin. Add the Teams channel configuration to your openclaw.json with appId, appPassword, and tenantId. You can also use environment variables MSTEAMS_APP_ID, MSTEAMS_APP_PASSWORD, and MSTEAMS_TENANT_ID.

3

Set the messaging endpoint and enable Teams channel

In the Azure Portal, navigate to your Bot resource → Configuration. Set the messaging endpoint to 'https://<your-domain>/api/messages'. Then go to Channels → Add Microsoft Teams → Configure. For local development, use a tunnel (ngrok or Tailscale Funnel) to expose port 3978.

4

Create and install the Teams App

Create a manifest.json with your bot's App ID as botId, scopes (personal, team, groupChat), and RSC permissions. Zip it with outline.png and color.png. Upload via Teams Developer Portal or Teams Admin Center. For testing, sideload the app package.

5

Test the bot

Find your bot in Teams and send it a direct message. If using the default pairing policy, approve the sender via 'openclaw pairing approve msteams <code>' in your terminal. The bot should respond with AI-generated replies.

Microsoft Teams Configuration Example

config.json
{
  "channels": {
    "msteams": {
      "enabled": true,
      "appId": "YOUR_APP_ID",
      "appPassword": "YOUR_APP_PASSWORD",
      "tenantId": "YOUR_TENANT_ID",
      "webhook": {
        "port": 3978,
        "path": "/api/messages"
      }
    }
  }
}

Microsoft Teams Deep Dive

Architecture Overview

OpenClaw integrates with Microsoft Teams through the Azure Bot Framework — a webhook-based architecture where Teams routes messages to your Gateway's /api/messages endpoint, and OpenClaw replies through the Bot Framework REST API. The flow is: User sends message in Teams → Bot Framework Service → webhook POST to your Gateway (port 3978) → OpenClaw processes with AI → reply via Bot Framework API → Teams delivers response. The Teams plugin is installed separately via 'openclaw plugins install @openclaw/msteams'. This modular approach keeps the core Gateway lightweight while allowing Teams-specific features (Adaptive Cards, SharePoint file uploads, RSC permissions) to be maintained independently. Authentication uses Azure AD: the Bot Framework validates JWT tokens on incoming webhook requests, and OpenClaw authenticates outbound API calls using your App ID and App Password. Single-tenant configuration is recommended for security, restricting the bot to your organization's Azure AD directory.
Your Gateway must be accessible via a public HTTPS URL. For local development, use ngrok or Tailscale Funnel to tunnel to port 3978.
Single-tenant bots are recommended over multi-tenant for organizational security — they only accept tokens from your Azure AD directory.

Azure Bot Setup & App Registration

Setting up the Teams bot requires creating resources in the Azure Portal: 1. Create an Azure Bot resource — Search 'Azure Bot' in the marketplace. Select Single Tenant as the bot type. This creates both the Bot resource and an App Registration. 2. Generate a client secret — In App Registrations → your bot app → Certificates & secrets, create a new client secret. Copy the value immediately (it's only shown once). 3. Note the credentials — App (client) ID from the Overview page, the client secret value, and Directory (tenant) ID. These three values are your bot's authentication credentials. 4. Set the messaging endpoint — In the Bot resource → Configuration, set the endpoint to 'https://<your-domain>/api/messages'. This is where Teams sends webhook events. 5. Enable the Teams channel — Go to Channels → Add channel → Microsoft Teams. Configure and save. Environment variables can be used instead of config file values: MSTEAMS_APP_ID, MSTEAMS_APP_PASSWORD, MSTEAMS_TENANT_ID.
openclaw.json
{
  "channels": {
    "msteams": {
      "appId": "<APP_ID>",
      "appPassword": "<APP_PASSWORD>",
      "tenantId": "<TENANT_ID>"
    }
  }
}
Keep your App Password secure. Never commit it to version control. Use environment variables (MSTEAMS_APP_PASSWORD) for production deployments. Rotate the client secret periodically in the Azure Portal.

Teams App Manifest & RSC Permissions

The Teams App Manifest (manifest.json) defines your bot's identity, scopes, and permissions. It's packaged with two icons into a .zip file for installation. Manifest essentials: • botId — Your Azure Bot's App ID • Scopes — personal (DMs), team (channels), groupChat (group conversations) • supportsFiles: true — Enable file consent cards in personal chat • Resource-Specific Consent (RSC) permissions — Allow the bot to receive messages without @mention RSC Permissions for channels (team scope): • ChannelMessage.Read.Group — Receive channel messages without @mention • ChannelMessage.Send.Group — Send messages to channels • TeamMember.Read.Group, TeamSettings.Read.Group — Read team metadata RSC Permissions for group chats: • ChatMessage.Read.Chat — Receive group chat messages without @mention Icons required: • outline.png — 32×32 pixels, transparent background • color.png — 192×192 pixels, full-color app icon Zip manifest.json + both icons together, then upload via Teams Developer Portal, Teams Admin Center, or sideload for testing.
When updating an installed app (e.g., adding RSC permissions), increment the version field in manifest.json, re-zip, re-upload, and reinstall in each team.
After installing or updating the app, fully quit and relaunch the Teams client to ensure the new permissions take effect.

DM Policies

DM (Direct Message) policies control who can interact with your bot in personal chat. OpenClaw supports four policies: • pairing (default) — New users who message the bot receive a random pairing code. Approve via 'openclaw pairing approve msteams <code>' in your terminal. Once approved, they can chat freely. • allowlist — Only users listed in allowFrom can message the bot. Supports AAD object IDs, UPNs (user@org.com), or display names. • open — Any Teams user in your tenant can message the bot. Requires adding '*' to allowFrom as a safety confirmation. • disabled — DM functionality is completely turned off. Teams identifies users by AAD (Azure AD) object IDs, UPNs, or display names. You can find these in Gateway logs when users send messages, or look them up in the Azure Portal under Azure Active Directory → Users.
openclaw.json
{
  "channels": {
    "msteams": {
      "dmPolicy": "allowlist",
      "allowFrom": [
        "user@org.com",
        "40a1a0ed-4ff2-4164-a219-55518990c197"
      ]
    }
  }
}
UPN format (user@org.com) is usually the most convenient for allowlists. AAD object IDs are more stable if users might change their email addresses.
Use 'openclaw pairing list msteams' to see all pending pairing requests and their codes.

Group Chat & Channel Management

OpenClaw supports both Teams channels (within a Team) and group chats, each with configurable access control: • disabled (default for groups) — Ignore all group/channel messages • allowlist — Only approved senders (via groupAllowFrom) can trigger the bot • open — Respond to messages from all group members or channel participants By default, the bot requires an @mention in channels and group chats (requireMention: true). Set requireMention to false to have the bot respond to all messages, or configure RSC permissions to receive messages without being mentioned. Teams channels and group chats maintain separate conversation contexts. Each conversation has its own session and history, isolated from DMs and other conversations. Per-team and per-channel overrides allow fine-grained control. You can set different replyStyle, requireMention, and tool configurations for each team or even individual channels within a team.
openclaw.json
{
  "channels": {
    "msteams": {
      "groupPolicy": "allowlist",
      "groupAllowFrom": ["user@org.com"],
      "teams": {
        "My Team": {
          "channels": {
            "General": {
              "requireMention": true
            }
          }
        }
      }
    }
  }
}
Use team and channel display names or conversation IDs (19:...@thread.tacv2) as keys in the teams configuration.
Per-channel overrides inherit from the parent team config, which inherits from the global msteams config.

Reply Styles & Threading

Teams offers two distinct UI layouts for channels, and OpenClaw's reply behavior should match: • Posts (classic layout) — Uses threaded replies under root messages. Set replyStyle to 'thread' (default). The bot's response appears as a reply to the original message card. • Threads (Slack-like layout) — Uses linear message flow. Set replyStyle to 'top-level'. The bot sends a new top-level message instead of threading. The Teams API does not expose which layout a channel uses, so you must configure replyStyle to match. Mismatched settings won't cause errors but may result in suboptimal conversation flow. Reply style can be configured globally, per-team, or per-channel. This allows you to match different layouts across different channels in the same Teams organization.
openclaw.json
{
  "channels": {
    "msteams": {
      "replyStyle": "thread",
      "teams": {
        "19:abc...@thread.tacv2": {
          "channels": {
            "19:xyz...@thread.tacv2": {
              "replyStyle": "top-level"
            }
          }
        }
      }
    }
  }
}

File Handling & SharePoint

OpenClaw supports file sharing in Teams with different behavior based on chat type: Personal chats: • Built-in FileConsentCard flow — no additional setup needed. The bot sends a file consent card, the user approves, and the file is uploaded. Group chats and channels: • Requires Microsoft Graph permission: Sites.ReadWrite.All • Optional: Chat.Read.All for per-user sharing links (restricts access to chat members only) • Configure sharePointSiteId to specify the SharePoint site for file uploads • Files are stored in /OpenClawShared/ folder in the SharePoint document library Without Chat.Read.All, shared file links are organization-wide. With it, sharing is restricted to the current chat's members. Inbound attachments are automatically downloaded and processed by the Gateway. The mediaAllowHosts and mediaAuthAllowHosts configs control which domains are trusted for attachment downloads.
openclaw.json
{
  "channels": {
    "msteams": {
      "sharePointSiteId": "YOUR_SHAREPOINT_SITE_ID",
      "mediaAllowHosts": ["*.microsoft.com", "*.sharepoint.com"],
      "mediaAuthAllowHosts": ["graph.microsoft.com"]
    }
  }
}
Graph API permissions (Sites.ReadWrite.All, Chat.Read.All) require admin consent in your Azure AD tenant. Work with your IT admin to grant these permissions.

Adaptive Cards & Polls

Microsoft Teams supports Adaptive Cards — rich, interactive card-based layouts that go beyond plain text. OpenClaw leverages these for enhanced bot interactions: Polls: • Create polls via 'openclaw message poll --channel msteams --target conversation:<id>' • Votes are collected through Adaptive Card actions and stored locally in ~/.openclaw/msteams-polls.json • The Gateway must remain online to collect votes Custom Adaptive Cards: • Send arbitrary Adaptive Cards via the CLI: openclaw message send --channel msteams --target "conversation:<id>" --card '{...}' • Cards support Adaptive Card schema version 1.5 • Can include text blocks, images, action buttons, input fields, and more Formatting notes: • Basic markdown (bold, italic, code, links) is supported in regular messages • Complex tables and deeply nested lists may not render correctly • For rich layouts, use Adaptive Cards instead of markdown formatting
Use the Adaptive Cards Designer (adaptivecards.io/designer) to build and preview custom card layouts before sending them.
Adaptive Cards actions can trigger postback events that OpenClaw processes as user input.

Teams ID Extraction

Teams URLs contain multiple IDs, but not all are the ones you need for configuration. Here's how to extract the correct IDs: Team ID — Found in the URL path (not the groupId query parameter): https://teams.microsoft.com/l/team/19%3ABk4j...%40thread.tacv2/... → URL-decode '19%3ABk4j...%40thread.tacv2' to get the team ID Channel ID — Also in the URL path: https://teams.microsoft.com/l/channel/19%3A15bc...%40thread.tacv2/... → URL-decode to get the channel conversation ID User targets for CLI commands: • By AAD ID: user:40a1a0ed-4ff2-4164-a219-55518990c197 • By display name: user:John Smith • Conversation: conversation:19:abc...@thread.tacv2 • Raw (if contains @thread): 19:abc...@thread.tacv2
Do NOT use the 'groupId' query parameter from Teams URLs — it's the Microsoft 365 Group ID, not the Teams conversation ID. Always extract IDs from the URL path and URL-decode them.

Microsoft Teams Configuration Reference

enabled
Type: booleanDefault: true

Enable or disable the Microsoft Teams channel

appId
Type: stringDefault: ""

Azure Bot App ID (Microsoft App ID). Can also use MSTEAMS_APP_ID env var

appPassword
Type: stringDefault: ""

Azure Bot client secret. Can also use MSTEAMS_APP_PASSWORD env var

tenantId
Type: stringDefault: ""

Azure AD Tenant ID for single-tenant authentication. Can also use MSTEAMS_TENANT_ID env var

webhook.port
Type: numberDefault: 3978

Port for the webhook listener that receives Bot Framework events

webhook.path
Type: stringDefault: "/api/messages"

Webhook endpoint path for incoming Bot Framework messages

dmPolicy
Type: stringDefault: "pairing"

Controls who can DM the bot. Options: pairing, allowlist, open, disabled

allowFrom
Type: string[]Default: []

AAD object IDs, UPNs, or display names allowed to DM the bot (when dmPolicy is allowlist)

groupPolicy
Type: stringDefault: "allowlist"

Group/channel access control. Options: allowlist, open, disabled

groupAllowFrom
Type: string[]Default: []

Senders permitted in group chats. Falls back to allowFrom if not set

teams
Type: objectDefault: {}

Per-team and per-channel configuration overrides (replyStyle, requireMention, tools)

requireMention
Type: booleanDefault: true

Require @mention in channels and group chats. Set false with RSC permissions to respond to all messages

replyStyle
Type: stringDefault: "thread"

Reply layout style. Options: thread (classic Posts), top-level (Slack-like Threads)

configWrites
Type: booleanDefault: true

Allow /config set|unset commands to modify channel settings at runtime

textChunkLimit
Type: numberDefault:

Maximum characters per outbound message before chunking

chunkMode
Type: stringDefault: "length"

Text chunking strategy. Options: length (hard split), newline (paragraph-aware)

sharePointSiteId
Type: stringDefault: ""

SharePoint site ID for group chat/channel file uploads

mediaAllowHosts
Type: string[]Default: MS/Teams domains

Allowed hosts for downloading media attachments

mediaAuthAllowHosts
Type: string[]Default: Graph + Bot Framework

Hosts that receive Authorization headers when downloading media

dmHistoryLimit
Type: numberDefault: 50

Number of recent DM messages included as AI context per conversation

historyLimit
Type: numberDefault: 50

Maximum channel/group messages included as AI context

Microsoft Teams Frequently Asked Questions

Microsoft Teams Troubleshooting

Images and attachments are missing in channel messages

Graph API permissions have not been granted or admin consent is missing. The bot receives a content stub instead of the actual file.

Ensure your app registration has ChannelMessage.Read.All and Chat.Read.All Graph permissions with admin consent. Reinstall the Teams app after updating permissions. Fully quit and reopen the Teams client to refresh cached permissions.
Bot doesn't respond in channels (only works in DMs)

The bot requires @mention by default in channels and group chats, or RSC permissions are not configured.

Either @mention the bot in channel messages, or set requireMention: false in your config and add the RSC permission ChannelMessage.Read.Group to your app manifest. Reinstall the app in each team after updating the manifest.
Teams App manifest won't update after changes

Teams caches app metadata aggressively. Old manifest is still in use.

Increment the version field in manifest.json (e.g., 1.0.0 → 1.1.0), re-zip the package, remove the old app from Teams, reinstall the updated package, and hard-quit then relaunch the Teams client.
401 Unauthorized errors on the webhook endpoint

The appId, appPassword, or tenantId in OpenClaw config doesn't match the Azure Bot registration, or testing manually without proper Azure JWT tokens.

Verify all three credentials match the Azure Portal values exactly. Test your bot using Azure's built-in Web Chat (in the Bot resource → Test in Web Chat) to confirm the bot works before troubleshooting Teams-specific issues. Ensure your tenantId matches the directory where the bot was registered.
Bot doesn't work in private channels

Microsoft Teams historically had limited bot support in private channels. As of early 2026, Microsoft is rolling out expanded app support for private channels, but it may not yet be available in all tenants.

Check if your tenant has received the private channel app support update. If not yet available, use standard (public) channels, group chats, or DMs instead. Apps must be explicitly added to each private channel — installing at the team level does not automatically apply to private channels.