跳到正文
FunCoding

搜索

搜索文档、文章、Skill 和 MCP

Microsoft Teams configuration

Microsoft Teams configuration keys, environment variables, and history limits

The channels.msteams settings, the environment variables that stand in for the auth keys, and the history context rules.

Multiple bot accounts

Use channels.msteams.accounts.<id> for each Teams bot registration, then route that account with bindings[].match.accountId. Root settings are shared defaults; account settings override them.

{
  bindings: [
    { agentId: "main", match: { channel: "msteams", accountId: "default" } },
    { agentId: "support", match: { channel: "msteams", accountId: "support" } },
  ],
  channels: {
    msteams: {
      enabled: true,
      tenantId: "<TENANT_ID>",
      webhook: { path: "/api/messages" },
      dmPolicy: "allowlist",
      allowFrom: ["00000000-0000-0000-0000-000000000000"],
      defaultAccount: "default",
      accounts: {
        default: {
          appId: "<PRIMARY_CLIENT_ID>",
          appPassword: "<PRIMARY_CLIENT_SECRET>",
        },
        support: {
          appId: "<SUPPORT_CLIENT_ID>",
          appPassword: "<SUPPORT_CLIENT_SECRET>",
          webhook: { path: "/api/messages/support" },
          allowFrom: ["11111111-1111-1111-1111-111111111111"],
        },
      },
    },
  },
}
  • Enabled accounts must use unique appId values and webhook paths. All bots receive callbacks on gateway.port; separate listener ports are not required.
  • The default account uses the root webhook path (/api/messages when omitted). A named account without an explicit path appends its normalized account ID: support uses /api/messages/support. Set each Azure Bot messaging endpoint to its own path, for example https://gateway.example.com/api/messages/support.
  • Named accounts must define their own appId and appPassword for secret authentication. Those fields do not inherit from the root.
  • tenantId, federated-auth settings, access policy, team/channel allowlists, streaming, SSO, delegated auth, and delivery settings inherit from the root unless an account overrides them. legacyWebhook never inherits into named accounts; keep compatibility listeners explicit and give each a unique port.
  • Existing root-level single-bot credentials remain the default account for compatibility. Configure either that root identity or accounts.default, not both.

Environment variables

These auth-related config keys can be set via environment variables instead of openclaw.json for the default account only. Named accounts must define their bot identity in config (other keys, such as groupPolicy or historyLimit, are config-only):

Env varConfig keyNotes
MSTEAMS_APP_IDappId
MSTEAMS_APP_PASSWORDappPassword
MSTEAMS_TENANT_IDtenantId
MSTEAMS_AUTH_TYPEauthType"secret" or "federated"
MSTEAMS_CERTIFICATE_PATHcertificatePathfederated + certificate
MSTEAMS_CERTIFICATE_THUMBPRINTcertificateThumbprintaccepted, not required for auth
MSTEAMS_USE_MANAGED_IDENTITYuseManagedIdentityfederated + managed identity
MSTEAMS_MANAGED_IDENTITY_CLIENT_IDmanagedIdentityClientIduser-assigned managed identity only

History context

  • channels.msteams.historyLimit controls how many recent channel/group messages are wrapped into the prompt. Falls back to messages.groupChat.historyLimit, then defaults to 50. Set 0 to disable.
  • Graph thread context adds the parent and up to the oldest 50 replies alongside recent channel history. It excludes the triggering message and keeps history separate from the sender's command text, so commands quoted in history do not execute. Long fetched messages retain their beginning and end within the prompt's per-message limit.
  • Thread and quoted attachment context follow channels.msteams.contextVisibility, falling back to channels.defaults.contextVisibility, then all. Use allowlist to filter both by sender allowlists (allowFrom / groupAllowFrom), or allowlist_quote to filter thread history while permitting quoted context.
  • DM history can be limited with channels.msteams.dmHistoryLimit (user turns). Per-user overrides: channels.msteams.dms["<user_id>"].historyLimit.

Configuration

Key settings (see /gateway/configuration for shared channel patterns):

  • channels.msteams.enabled: enable/disable the channel.
  • channels.msteams.defaultAccount: account used when accountId is omitted.
  • channels.msteams.accounts.<id>.enabled: enable/disable one Teams bot account.
  • channels.msteams.accounts.<id>.appId, channels.msteams.accounts.<id>.appPassword, channels.msteams.accounts.<id>.webhook.path: per-bot identity, secret, and Gateway callback path.
  • channels.msteams.appId, channels.msteams.appPassword, channels.msteams.tenantId: bot credentials.
  • channels.msteams.cloud: Teams SDK cloud environment (Public, USGov, USGovDoD, or China; default Public). Set with serviceUrl for USGov/DoD SDK clouds; China uses the SDK preset and stored Azure China Bot Framework conversation references, with Graph-backed helpers disabled until Azure China Graph routing ships.
  • channels.msteams.serviceUrl: Bot Connector service URL boundary for SDK proactive operations. Public cloud uses the SDK default; set for GCC (https://smba.infra.gcc.teams.microsoft.com/teams), GCC High, or DoD. China accepts Azure China Bot Framework channel hosts when the stored conversation reference comes from Teams operated by 21Vianet.
  • channels.msteams.webhook.path: Gateway HTTP route (omitted or empty uses /api/messages), served on gateway.port (default 18789).
  • channels.msteams.legacyWebhook: explicit compatibility listener. { port, host? } selects an endpoint, preserving the previous wildcard bind when host is omitted. Omitted or false opens no separate listener.
  • channels.msteams.dmPolicy: pairing | allowlist | open | disabled (default pairing).
  • channels.msteams.allowFrom: DM allowlist (AAD object IDs recommended). Stable AAD object IDs also authorize approval actions. The wizard resolves names to IDs during setup when Graph access is available.
  • channels.msteams.defaultTo: default outbound target; a stable AAD object ID can also authorize approval actions.
  • channels.msteams.dangerouslyAllowNameMatching: break-glass toggle to re-enable mutable UPN/display-name matching and direct team/channel name routing.
  • channels.msteams.textChunkLimit: outbound text chunk size in characters (default 4000, and hard-capped at 4000 regardless of a higher configured value).
  • channels.msteams.streaming.chunkMode: length (default) or newline to split on blank lines (paragraph boundaries) before length chunking.
  • channels.msteams.mediaAllowHosts: allowlist for inbound attachment hosts (defaults to Microsoft/Teams domains: Graph, SharePoint/OneDrive, Teams CDN, Bot Framework, Azure Media Services).
  • channels.msteams.mediaAuthAllowHosts: allowlist for attaching Authorization headers on media retries (defaults to Graph + Bot Framework hosts).
  • channels.msteams.graphMediaFallback: opt into Graph message lookups when channel/group HTML omits file markers (default false; see Channel/group file recovery).
  • channels.msteams.mediaMaxMb: per-channel media size limit override in MB. Falls back to agents.defaults.mediaMaxMb when unset.
  • channels.msteams.requireMention: require @mention in channels/groups (default true).
  • channels.msteams.requireMentionInBotThreads: override mention gating in channel threads rooted at this bot's tracked messages. Omitted preserves current behavior; see Bot-created threads.
  • channels.msteams.replyStyle: thread | top-level (see Reply style).
  • channels.msteams.teams.<teamId>.replyStyle: per-team override.
  • channels.msteams.teams.<teamId>.requireMention: per-team override.
  • channels.msteams.teams.<teamId>.requireMentionInBotThreads: per-team bot-thread override.
  • channels.msteams.teams.<teamId>.tools: default per-team tool policy overrides (allow/deny/alsoAllow) used when a channel override is missing.
  • channels.msteams.teams.<teamId>.toolsBySender: default per-team per-sender tool policy overrides ("*" wildcard supported).
  • channels.msteams.teams.<teamId>.channels.<conversationId>.replyStyle: per-channel override.
  • channels.msteams.teams.<teamId>.channels.<conversationId>.requireMention: per-channel override.
  • channels.msteams.teams.<teamId>.channels.<conversationId>.requireMentionInBotThreads: per-channel bot-thread override.
  • channels.msteams.teams.<teamId>.channels.<conversationId>.tools: per-channel tool policy overrides (allow/deny/alsoAllow).
  • channels.msteams.teams.<teamId>.channels.<conversationId>.toolsBySender: per-channel per-sender tool policy overrides ("*" wildcard supported).
  • toolsBySender keys use explicit prefixes: channel:, id:, e164:, username:, name:. Run openclaw doctor --fix to migrate retired unprefixed keys to id: entries.
  • channels.msteams.authType: authentication type - "secret" (default) or "federated".
  • channels.msteams.certificatePath: path to PEM certificate file (federated + certificate auth).
  • channels.msteams.certificateThumbprint: certificate thumbprint; accepted, not required for auth.
  • channels.msteams.useManagedIdentity: enable managed identity auth (federated mode).
  • channels.msteams.managedIdentityClientId: client ID for user-assigned managed identity.
  • channels.msteams.sharePointSiteId: SharePoint site ID for file uploads in group chats/channels (see Sending files in group chats).
  • channels.msteams.welcomeCard, channels.msteams.groupWelcomeCard, channels.msteams.promptStarters: welcome Adaptive Card shown on first DM/group contact, and its suggested prompt buttons.
  • channels.msteams.responsePrefix: text prefixed to outbound replies.
  • channels.msteams.feedbackEnabled (default true), channels.msteams.feedbackReflection (default true), channels.msteams.feedbackReflectionCooldownMs: thumbs-up/down feedback on replies and the negative-feedback reflection follow-up.
  • channels.msteams.sso, channels.msteams.delegatedAuth: Bot Framework OAuth connection and delegated Graph scopes for SSO-backed flows; sso.enabled: true requires sso.connectionName.

Migrating an existing webhook endpoint

Teams webhooks now share the Gateway HTTP listener. The Teams SDK still verifies Azure JWT signatures; callers do not supply a Gateway token. Keep the public HTTPS messaging endpoint in Azure Bot and change its reverse-proxy upstream to Gateway port 18789 (or your gateway.port), preserving /api/messages or your configured webhook.path. If you expose a port directly, update Azure Bot's messaging endpoint to the public HTTPS URL that reaches this Gateway route.

Doctor pins legacyWebhook: { port: 3978 } once for an enabled Teams channel on an existing installation that relied on the implicit port. Evidence of prior operation is required; fresh installations open no separate listener. An explicitly configured webhook.port moves to legacyWebhook.port through Doctor's normal config backup and write flow. Pinned compatibility listeners forward into the same Gateway route and JWT validation.

The deprecated TypeScript webhook.port input remains source-compatible until the next Plugin SDK major. Runtime config uses legacyWebhook; run openclaw doctor --fix to migrate the old key.

After confirming a delivery through the Gateway port, remove the channels.msteams.legacyWebhook pin and any old firewall or Compose port mapping. Keep meta.migrations.webhookListeners, which Doctor saves with the pin, so later runs do not recreate it. See webhook migrations for included and read-only config sources. Explicit false also disables the listener. Doctor and startup print the Gateway route and the setting to remove.

For an existing installation that supplies Teams credentials only through environment variables, Doctor preserves the endpoint without enabling Teams in the source config. If those credentials are visible only to the Gateway service, Doctor leaves the decision pending until Gateway startup. Continue using gateway run --ambient-channels to activate it. A listener setting alone no longer enables Teams; use enabled: true for a permanent opt-in. Doctor adds that flag to authored listener settings that previously implied activation, including an explicit legacyWebhook: false. It does not add the flag to a generated pin whose migration completion is already recorded.

A custom path also accepts the older /api/messages alias with its existing deprecation warning when that route is available. If another plugin owns the alias, startup logs the conflict and keeps serving the configured path. Update Azure Bot to the configured path.

The Gateway reserves /health, /healthz, /ready, /readyz, /startup, and /startupz for checks, including URLs with query strings. If your former Teams callback uses one of these paths, set webhook.path to /api/messages and update Azure Bot or the proxy upstream to match. Doctor reports this conflict. The compatibility listener keeps the old endpoint working; startup refuses the unusable Gateway route when no explicit legacy listener is configured. Verify the replacement before removing that listener's pin.

Paths under /api/channels require Gateway authentication on the main listener, including encoded spellings. Teams callbacks authenticate with Azure JWTs, so use /api/messages instead. Doctor and startup report the same callback-change action; the compatibility listener continues serving the old path until that cutover is complete.

Express parameter, wildcard, and brace patterns continue working on the legacy port. Gateway route registration uses literal paths. Before disabling the legacy listener for a pattern, change the existing webhook.path to /api/messages and update Azure Bot or your proxy. Doctor and startup identify these patterns; without an explicit legacy listener, startup reports the required change instead of silently dropping callbacks.