Channels

How to Connect OpenClaw to Microsoft Teams

5 min read

Browse more in Channels.

All channels guides →

This guide walks you through connecting OpenClaw to Microsoft Teams using the built-in Microsoft Teams channel. You will create an Azure Bot, wire it to OpenClaw’s `/api/messages` webhook, and install a Teams app so your agents can respond in DMs, group chats, and channels.

By the end, you will have OpenClaw replying to Teams messages with text and DM attachments, with routing and access control configured safely.

Setup flow

Prerequisites

  • An existing OpenClaw installation with access to install and configure plugins.
  • An Azure subscription where you can create an Azure Bot resource.
  • Permissions in Microsoft Teams to upload a custom app package (sideload or via org catalog).
  • Ability to expose a public HTTPS URL for OpenClaw (for example a domain or a tunnel) so Azure Bot can reach `/api/messages` on port 3978.
  • Basic access to Microsoft Graph and Teams RSC permissions if you plan to use channels, group chats, or member info actions.

Steps

  1. 1

    Ensure the Microsoft Teams plugin is available

    First confirm that the Microsoft Teams plugin is present so OpenClaw can speak Bot Framework. Current packaged OpenClaw releases already bundle it, but older or custom builds may not.

    If you are on an older build or running from a local checkout, install the plugin explicitly.

    bash
    openclaw plugins install @openclaw/msteams
  2. 2

    Install the Teams plugin from a local checkout when developing from source

    If you run OpenClaw from a git repo and are iterating on the Teams plugin itself, point the plugin install at your local path. This keeps your OpenClaw instance in sync with local changes to the plugin code.

    bash
    openclaw plugins install ./path/to/local/msteams-plugin
  3. 3

    Create an Azure Bot for OpenClaw

    You need an Azure Bot resource to bridge Teams traffic into OpenClaw. This step gives you the App ID, client secret, and tenant ID that OpenClaw uses to authenticate with Microsoft’s Bot Framework.

    Use a Single Tenant bot to match the current recommendations.

    text
    Go to https://portal.azure.com/#create/Microsoft.AzureBot
    
    Fill in the Basics tab:
    
    | Field | Value |
    | --- | --- |
    | Bot handle | Your bot name, e.g., `openclaw-msteams` (must be unique) |
    | Subscription | Select your Azure subscription |
    | Resource group | Create new or use existing |
    | Pricing tier | Free for dev/testing |
    | Type of App | Single Tenant |
    | Creation type | Create new Microsoft App ID |
  4. 4

    Get the Azure Bot credentials

    Once the bot exists, you need to pull out the identifiers OpenClaw will use. These map directly to `appId`, `appPassword`, and `tenantId` in your OpenClaw config.

    Keep the client secret safe; you will paste it into your config or environment variables.

    text
    1. Go to your Azure Bot resource → Configuration
    2. Copy Microsoft App ID → this is your `appId`
    3. Click Manage Password → go to the App Registration
    4. Under Certificates & secrets → New client secret → copy the Value → this is your `appPassword`
    5. Go to Overview → copy Directory (tenant) ID → this is your `tenantId`
  5. 5

    Configure the Azure Bot messaging endpoint

    Point the Azure Bot at your OpenClaw webhook so Teams messages actually reach your gateway. In production this is your public domain; for local development you’ll use a tunnel.

    Make sure the path and port match what you configure in OpenClaw.

    text
    Production: https://your-domain.com/api/messages
    Local dev: Use a tunnel (see Local Development) such as https://abc123.ngrok.io/api/messages
  6. 6

    Expose OpenClaw locally with a tunnel for development

    Teams cannot call localhost directly, so for local testing you need a tunnel that exposes port 3978 over HTTPS. ngrok and Tailscale Funnel are both supported options.

    After starting the tunnel, paste the generated URL into the Azure Bot messaging endpoint.

    bash
    ngrok http 3978
    # Copy the https URL, e.g., https://abc123.ngrok.io
    # Set messaging endpoint to: https://abc123.ngrok.io/api/messages
  7. 7

    Configure the Microsoft Teams channel in OpenClaw

    Now wire the Azure Bot credentials into OpenClaw so the msteams channel can authenticate and listen on `/api/messages`. This minimal config enables the channel, sets the webhook port and path, and is enough to handle text and DM attachments.

    You can later tighten access control and group policies.

    json
    {
      channels: {
        msteams: {
          enabled: true,
          appId: "<APP_ID>",
          appPassword: "<APP_PASSWORD>",
          tenantId: "<TENANT_ID>",
          webhook: { port: 3978, path: "/api/messages" },
        },
      },
    }
  8. 8

    Optionally configure Teams access control and allowlists

    Before you roll this out broadly, decide who can trigger the bot in DMs and groups. The default DM policy requires pairing, and group chats are blocked unless you add allowlists.

    You can also scope replies to specific teams and channels using stable IDs.

    json
    {
      channels: {
        msteams: {
          groupPolicy: "allowlist",
          groupAllowFrom: ["user@org.com"],
        },
      },
    }
    
    {
      channels: {
        msteams: {
          groupPolicy: "allowlist",
          teams: {
            "My Team": {
              channels: {
                General: { requireMention: true },
              },
            },
          },
        },
      },
    }
  9. 9

    Build a Teams app manifest that references your bot

    Teams needs an app package that declares your bot, scopes, and RSC permissions. json` like the example, add icons, and zip them together.

    id match your Azure Bot App ID or Teams will reject the app.

    json
    {
      $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" },
          ],
        },
      },
    }
  10. 10

    Generate and upload the Teams app package

    Once the manifest is ready, package it with the required icons and upload it into Teams. You can either hand-zip the files or use the Teams Developer Portal to generate the package for you.

    After upload, install the app in personal, team, or group chat scopes where you want OpenClaw to respond.

    text
    Zip all three files together: manifest.json, outline.png, color.png.
    
    Or use the Teams Developer Portal:
    1. Click + New app
    2. Fill in basic info (name, description, developer info)
    3. Go to App features → Bot
    4. Select Enter a bot ID manually and paste your Azure Bot App ID
    5. Check scopes: Personal, Team, Group Chat
    6. Click Distribute → Download app package
    7. In Teams: Apps → Manage your apps → Upload a custom app → select the ZIP
  11. 11

    Run the OpenClaw gateway and test the bot

    With config and Teams app in place, start your OpenClaw gateway so the msteams channel can bind to the webhook. Use Azure Web Chat first to confirm the endpoint works, then send a DM in Teams and watch the gateway logs.

    This helps you distinguish Teams manifest issues from webhook or auth problems.

    text
    In Azure Portal → your Azure Bot resource → Test in Web Chat
    1. Send a message - you should see a response
    2. This confirms your webhook endpoint works before Teams setup
    
    In Teams (after app installation):
    1. Install the Teams app (sideload or org catalog)
    2. Find the bot in Teams and send a DM
    3. Check gateway logs for incoming activity

Configuration

OptionDescriptionExample
channels.msteams.enabledTurns the Microsoft Teams channel on so OpenClaw starts the Teams plugin and webhook listener.
channels.msteams.appIdThe Microsoft App ID from your Azure Bot resource used to authenticate with Bot Framework.11111111-1111-1111-1111-111111111111
channels.msteams.appPasswordThe client secret (App password) from your Azure App Registration used as the bot credential.super-long-client-secret-value
channels.msteams.tenantIdThe Directory (tenant) ID for your Azure AD tenant, required for single-tenant bots.22222222-2222-2222-2222-222222222222
channels.msteams.webhook.portThe local port where OpenClaw listens for Bot Framework webhook traffic.
channels.msteams.webhook.pathThe HTTP path that receives Teams webhook requests from Azure Bot./api/messages
channels.msteams.configWritesControls whether Teams messages can update OpenClaw config via `/config set|unset` when commands.config is enabled.
channels.msteams.dmPolicyDefines how DM access is handled; by default unknown senders are ignored until approved.pairing
channels.msteams.allowFromList of allowed sender IDs for DMs, typically stable AAD object IDs.
channels.msteams.dangerouslyAllowNameMatchingEnables matching on UPNs/display names instead of stable IDs, which is disabled by default.
channels.msteams.groupPolicyControls whether group chats and channels are open, allowlisted, or disabled.allowlist
channels.msteams.groupAllowFromControls which senders can trigger in group chats and channels, falling back to allowFrom when unset.
channels.msteams.teamsOptional allowlist of teams and channels where the bot can respond, keyed by team and channel identifiers.
channels.msteams.historyLimitNumber of recent channel/group messages to include as context in prompts (default 50, 0 disables).
channels.msteams.dmHistoryLimitNumber of recent user turns in DMs to include as context.
channels.msteams.actions.memberInfoEnables the Graph-backed member-info action when Graph credentials are available.
MSTEAMS_APP_IDEnvironment variable alternative for channels.msteams.appId.11111111-1111-1111-1111-111111111111
MSTEAMS_APP_PASSWORDEnvironment variable alternative for channels.msteams.appPassword.super-long-client-secret-value
MSTEAMS_TENANT_IDEnvironment variable alternative for channels.msteams.tenantId.22222222-2222-2222-2222-222222222222

Troubleshooting

Teams app upload fails with manifest errors or the bot does not appear in the client.

This usually means required manifest fields do not match your Azure Bot. resourceSpecific` block includes the channel read/send permissions you need.

bash
{
  bots: [
    {
      botId: "11111111-1111-1111-1111-111111111111",
      scopes: ["personal", "team", "groupChat"],
      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: "ChatMessage.Read.Chat", type: "Application" },
      ],
    },
  },
}

The bot installs in Teams but never responds to messages in channels or group chats.

groupPolicy` is `allowlist`, group chats and channels are blocked unless you configure `groupAllowFrom` or a teams allowlist. Add the appropriate users or teams to the allowlist, or set `groupPolicy: "open"` if you want any member to trigger the bot (still mention-gated by default).

bash
{
  channels: {
    msteams: {
      groupPolicy: "allowlist",
      groupAllowFrom: ["user@org.com"],
    },
  },
}

DMs to the bot are ignored even though the app is installed.

dmPolicy = "pairing"`, which ignores unknown senders until they are approved. allowFrom` or adjust your DM policy, and avoid relying on display names unless you explicitly enable `dangerouslyAllowNameMatching`.

bash
{
  channels: {
    msteams: {
      dmPolicy: "pairing",
      allowFrom: ["user-aad-object-id-1"],
    },
  },
}

Channel or group file uploads do not work, but DM attachments are fine.

Current status is that text and DM attachments are supported, while channel/group file sending requires `sharePointSiteId` and Graph permissions. If you only configured Teams RSC and not the additional Graph permissions and SharePoint settings, channel/group file contents will not be available.

bash
Status: text + DM attachments are supported; channel/group file sending requires `sharePointSiteId` + Graph permissions (see Sending files in group chats).

Frequently asked questions

Powered by Mem0

Add persistent memory to OpenClaw

Official Mem0 plugin for OpenClaw keeps context across chats and tools. Smaller prompts, lower cost, better continuity for your agents.

More in Channels