跳到正文
FunCoding

搜索

搜索文档、文章、Skill 和 MCP

Microsoft Teams access control

Microsoft Teams DM and group policy, team and channel allowlists, and conversation IDs

Who may talk to the Teams bot, which teams and channels it answers in, and where the IDs those rules use come from.

Config writes

By default, Microsoft Teams can write config updates triggered by /config set|unset (requires commands.config: true).

Disable with:

{
  channels: { msteams: { configWrites: false } },
}

Access control (DMs + groups)

Set shared policies under channels.msteams, or override them for one bot under channels.msteams.accounts.<id>. Policy changes made through the selected account stay scoped to that account; revoking a sender from one account does not change a sibling account.

DM access

  • Default: channels.msteams.dmPolicy = "pairing". Unknown senders are ignored until approved. Set it at the root to apply to all accounts, or override it at channels.msteams.accounts.<id>.dmPolicy.
  • channels.msteams.allowFrom should use stable AAD object IDs or static sender access groups such as accessGroup:core-team. Set it at the root to share the allowlist, or override it at channels.msteams.accounts.<id>.allowFrom.
  • dmPolicy: "open" requires the effective account allowlist to contain "*"; setup preserves that wildcard while adding or removing account-specific entries.
  • Do not rely on UPN/display-name matching for allowlists; they can change. OpenClaw disables direct name matching by default; opt in with channels.msteams.dangerouslyAllowNameMatching: true.
  • The wizard can resolve names to IDs via Microsoft Graph when credentials allow.

Group access

  • Default: channels.msteams.groupPolicy = "allowlist" (blocked unless you add groupAllowFrom). Set it at the root to apply to all accounts, or override it at channels.msteams.accounts.<id>.groupPolicy; the root schema default takes precedence over channels.defaults.groupPolicy.
  • channels.msteams.groupAllowFrom controls which senders, static sender access groups, or group/channel conversation IDs can trigger in group chats/channels (falls back to channels.msteams.allowFrom). Set it at the root to share it, or override it at channels.msteams.accounts.<id>.groupAllowFrom. Conversation IDs can use 19:[email protected], 19:[email protected], or 19:[email protected]; preserve the exact ID casing. OpenClaw ignores ;messageid=... suffixes. Conversation IDs never grant personal-DM access.
  • Set groupPolicy: "open" to allow any member (still mention-gated by default).
  • To block all channels, set channels.msteams.groupPolicy: "disabled".

Example:

{
  channels: {
    msteams: {
      groupPolicy: "allowlist",
      groupAllowFrom: ["00000000-0000-0000-0000-000000000000", "accessGroup:core-team"],
    },
  },
}

Team + channel allowlist

  • Scope group/channel replies for every account under channels.msteams.teams, or for one bot under channels.msteams.accounts.<id>.teams.
  • Use stable Teams conversation IDs from Teams links as keys, not mutable display names (see Team and Channel IDs).
  • When groupPolicy="allowlist" and a teams allowlist is present, only listed teams/channels are accepted (mention-gated).
  • groupAllowFrom authorizes group senders, not delegated Graph reads of other channels. If an existing configuration only sets groupAllowFrom, keep the default groupPolicy: "allowlist" and configure the target under channels.msteams.teams.<team>.channels.
  • Alternatively, deliberately set groupPolicy: "open" for broader delegated reads. This also admits any group sender (still mention-gated by default), so it is less restrictive than a scoped team/channel route.
  • Direct-operator reads and reads in the current conversation do not require an additional team/channel route.
  • The configure wizard accepts Team/Channel entries and stores them for you.
  • On startup, OpenClaw resolves team/channel and user allowlist names to IDs (when Graph permissions allow) and logs the mapping. Unresolved names are kept as typed but ignored for routing unless channels.msteams.dangerouslyAllowNameMatching: true is set.

With compatible core and Teams versions, verified official npm and ClawHub installations can use the existing read, search, reactions, list-pins, member-info, channel-info, and channel-list actions under these access rules. Agent reads from an installed plugin require trusted current Teams conversation and account context. Listing a team's channels requires access to the whole team; access to one channel does not grant that permission. Member lookups retain their standard-channel and current-requester restrictions. Subsequent Graph requests and results are rejected when the originating call or plugin loses authority.

Example:

{
  channels: {
    msteams: {
      groupPolicy: "allowlist",
      groupAllowFrom: ["00000000-0000-0000-0000-000000000000"],
      teams: {
        "19:[email protected]": {
          channels: {
            "19:[email protected]": { requireMention: true },
          },
        },
      },
    },
  },
}

Mentions in bot-created threads

Set requireMentionInBotThreads: false to answer without an @mention in channel threads whose root message was sent by this bot. Set it to true to require a mention in those threads, including replies that would otherwise count as an implicit mention. Omit it to retain the existing mention behavior.

The setting resolves from channel to team to channels.msteams, independently of requireMention. Parent-channel posts and other people's threads retain their usual mention rules. Group-chat quotes are not channel threads, and sender and team/channel allowlists still apply.

{
  channels: {
    msteams: {
      requireMention: true,
      requireMentionInBotThreads: false,
    },
  },
}

Ownership uses accepted top-level channel posts recorded by the current bot, including proactive messages. Replies inside existing threads do not establish ownership. Tracking lasts up to 24 hours and is bounded; the newest 1,000 send markers survive restarts. Older or untracked roots retain the ordinary mention rules. Teams must grant ChannelMessage.Read.Group in the app manifest to deliver messages without an @mention; see RSC permissions.

Team and Channel IDs (Common Gotcha)

The groupId query parameter in Teams URLs is NOT the team ID used for configuration. Extract IDs from the URL path instead:

Team URL:

https://teams.microsoft.com/l/team/19%3ABk4j...%40thread.tacv2/conversations?groupId=...
                                    └────────────────────────────┘
                                    Team conversation ID (URL-decode this)

Channel URL:

https://teams.microsoft.com/l/channel/19%3A15bc...%40thread.tacv2/ChannelName?groupId=...
                                      └─────────────────────────┘
                                      Channel ID (URL-decode this)

For config:

  • Team key = path segment after /team/ (URL-decoded, e.g., 19:[email protected]; older tenants may show @thread.skype, which is also valid).
  • Channel key = path segment after /channel/ (URL-decoded).
  • Ignore the groupId query parameter for OpenClaw routing. It is the Microsoft Entra group ID, not the Bot Framework conversation ID used in incoming Teams activities.

Private channels

Bots have limited support in private channels:

FeatureStandard channelsPrivate channels
Bot installationYesLimited
Real-time messages (webhook)YesMay not work
RSC permissionsYesMay behave differently
@mentionsYesIf bot is accessible
Graph API historyYesYes (with permissions)

Workarounds if private channels do not work:

  1. Use standard channels for bot interactions.
  2. Use DMs; users can always message the bot directly.
  3. Use Graph API for historical access (requires ChannelMessage.Read.All).