# Microsoft Teams access control

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

- 网址：https://funcoding.ai/agents/openclaw/channels/msteams/access-control/
- 来源：OpenClaw 官方文档原文（英文），MIT 许可，同步于 2026-10-11
- 官方原文：https://docs.openclaw.ai/zh-CN/channels/msteams/access-control

---
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:

```json5
{
  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:...@thread.tacv2`, `19:...@thread.v2`, or `19:...@thread.skype`; 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:

```json5
{
  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](#team-and-channel-ids-common-gotcha)).
- 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](https://funcoding.ai/agents/openclaw/channels/msteams/cards-and-actions/#member-info-action)
retain their standard-channel and current-requester restrictions. Subsequent Graph
requests and results are rejected when the originating call or plugin loses authority.

Example:

```json5
{
  channels: {
    msteams: {
      groupPolicy: "allowlist",
      groupAllowFrom: ["00000000-0000-0000-0000-000000000000"],
      teams: {
        "19:team-id@thread.tacv2": {
          channels: {
            "19:channel-id@thread.tacv2": { 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.

```json5
{
  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](https://funcoding.ai/agents/openclaw/channels/msteams/manifest-and-permissions/#current-teams-rsc-permissions-manifest).

## 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:**

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

**Channel URL:**

```text
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:Bk4j...@thread.tacv2`; 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:

| Feature                      | Standard channels | Private channels       |
| ---------------------------- | ----------------- | ---------------------- |
| Bot installation             | Yes               | Limited                |
| Real-time messages (webhook) | Yes               | May not work           |
| RSC permissions              | Yes               | May behave differently |
| @mentions                    | Yes               | If bot is accessible   |
| Graph API history            | Yes               | Yes (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`).
