Microsoft Teams
Microsoft Teams (插件)
Section titled “Microsoft Teams (插件)”“放弃所有希望,进入此地者。”
更新时间:2026-01-21
状态:支持文本 + 私信附件;频道/群组文件发送需要 sharePointSiteId + Graph 权限(参见 在群聊中发送文件)。投票通过 Adaptive Cards 发送。
Microsoft Teams 作为插件发布,不随核心安装包捆绑。
破坏性变更 (2026.1.15): MS Teams 已移出核心。如果你使用它,必须安装该插件。
原因:保持核心安装更轻量,并允许 MS Teams 依赖项独立更新。
通过 CLI 安装 (npm 注册表):
openclaw plugins install @openclaw/msteams本地检出(从 git 仓库运行时):
openclaw plugins install ./extensions/msteams如果在配置/引导期间选择 Teams 并且检测到 git 检出,OpenClaw 将自动提供本地安装路径。
详情:插件 (Plugins)
快速设置 (初学者)
Section titled “快速设置 (初学者)”- 安装 Microsoft Teams 插件。
- 创建一个 Azure Bot (App ID + client secret + tenant ID)。
- 使用这些凭据配置 OpenClaw。
- 通过公共 URL 或隧道暴露
/api/messages(默认端口 3978)。 - 安装 Teams 应用包并启动网关。
最小配置:
{ channels: { msteams: { enabled: true, appId: "<APP_ID>", appPassword: "<APP_PASSWORD>", tenantId: "<TENANT_ID>", webhook: { port: 3978, path: "/api/messages" } } }}注意:群聊默认被阻止 (channels.msteams.groupPolicy: "allowlist")。要允许群组回复,请设置 channels.msteams.groupAllowFrom(或使用 groupPolicy: "open" 允许任何成员,提及门控)。
- 通过 Teams 私信、群聊或频道与 OpenClaw 对话。
- 保持路由确定性:回复总是回到它们到达的频道。
- 默认为安全频道行为(除非另有配置,否则需要提及)。
默认情况下,允许 Microsoft Teams 写入由 /config set|unset 触发的配置更新(需要 commands.config: true)。
禁用方式:
{ channels: { msteams: { configWrites: false } }}访问控制 (私信 + 群组)
Section titled “访问控制 (私信 + 群组)”私信访问 (DM access)
- 默认:
channels.msteams.dmPolicy = "pairing". 未知发送者被忽略直到获得批准。 channels.msteams.allowFrom接受 AAD 对象 ID、UPN 或显示名称。当凭据允许时,向导会通过 Microsoft Graph 将名称解析为 ID。
群组访问 (Group access)
- 默认:
channels.msteams.groupPolicy = "allowlist"(被阻止,除非你添加groupAllowFrom)。未设置时使用channels.defaults.groupPolicy覆盖默认值。 channels.msteams.groupAllowFrom控制哪些发送者可以在群聊/频道中触发(回退到channels.msteams.allowFrom)。- 设置
groupPolicy: "open"以允许任何成员(默认仍为提及门控)。 - 要允许 无频道,设置
channels.msteams.groupPolicy: "disabled".
示例:
{ channels: { msteams: { groupPolicy: "allowlist", groupAllowFrom: ["user@org.com"] } }}Teams + 频道白名单
- 通过在
channels.msteams.teams下列出团队和频道来限定群组/频道回复的范围。 - 键可以是团队 ID 或名称;频道键可以是会话 ID 或名称。
- 当
groupPolicy="allowlist"且存在 teams 白名单时,仅接受列出的团队/频道(提及门控)。 - 配置向导接受
Team/Channel条目并为你存储它们。 - 启动时,OpenClaw 将团队/频道和用户白名单名称解析为 ID(当 Graph 权限允许时)并记录映射;未解析的条目保持原样。
示例:
{ channels: { msteams: { groupPolicy: "allowlist", teams: { "My Team": { channels: { "General": { requireMention: true } } } } } }}- 安装 Microsoft Teams 插件。
- 创建一个 Azure Bot (App ID + secret + tenant ID)。
- 构建一个 Teams 应用包,引用该机器人并包含下面的 RSC 权限。
- 将 Teams 应用上传/安装到团队(或私信的个人范围)。
- 在
~/.openclaw/openclaw.json(或环境变量) 中配置msteams并启动网关。 - 默认情况下,网关在
/api/messages上监听 Bot Framework webhook 流量。
Azure Bot 设置 (先决条件)
Section titled “Azure Bot 设置 (先决条件)”在配置 OpenClaw 之前,你需要创建一个 Azure Bot 资源。
步骤 1: 创建 Azure Bot
Section titled “步骤 1: 创建 Azure Bot”前往 创建 Azure Bot
填写 基本信息 (Basics) 选项卡:
字段 值 Bot handle 你的机器人名称,例如 openclaw-msteams(必须唯一)Subscription 选择你的 Azure 订阅 Resource group 新建或使用现有的 Pricing tier Free 用于开发/测试 Type of App Single Tenant (推荐 - 见下文注释) Creation type Create new Microsoft App ID
弃用通知: 创建新的多租户机器人已于 2025-07-31 后弃用。新机器人请使用 Single Tenant。
- 点击 Review + create → Create (等待约 1-2 分钟)
步骤 2: 获取凭据
Section titled “步骤 2: 获取凭据”- 前往你的 Azure Bot 资源 → Configuration
- 复制 Microsoft App ID → 这是你的
appId - 点击 Manage Password → 前往应用注册 (App Registration)
- 在 Certificates & secrets 下 → New client secret → 复制 Value → 这是你的
appPassword - 前往 Overview → 复制 Directory (tenant) ID → 这是你的
tenantId
步骤 3: 配置消息端点
Section titled “步骤 3: 配置消息端点”- 在 Azure Bot 中 → Configuration
- 将 Messaging endpoint 设置为你的 webhook URL:
- 生产环境:
https://your-domain.com/api/messages - 本地开发: 使用隧道 (参见下文 本地开发 (隧道))
- 生产环境:
步骤 4: 启用 Teams 通道
Section titled “步骤 4: 启用 Teams 通道”- 在 Azure Bot 中 → Channels
- 点击 Microsoft Teams → Configure → Save
- 接受服务条款
本地开发 (隧道)
Section titled “本地开发 (隧道)”Teams 无法访问 localhost。使用隧道进行本地开发:
选项 A: ngrok
ngrok http 3978# 复制 https URL,例如 https://abc123.ngrok.io# 将 messaging endpoint 设置为: https://abc123.ngrok.io/api/messages选项 B: Tailscale Funnel
tailscale funnel 3978# 使用你的 Tailscale funnel URL 作为 messaging endpointTeams 开发者门户 (替代方案)
Section titled “Teams 开发者门户 (替代方案)”除了手动创建清单 ZIP,你可以使用 Teams 开发者门户:
- 点击 + New app
- 填写基本信息(名称、描述、开发者信息)
- 前往 App features → Bot
- 选择 Enter a bot ID manually 并粘贴你的 Azure Bot App ID
- 检查范围:Personal, Team, Group Chat
- 点击 Distribute → Download app package
- 在 Teams 中:应用 → 管理你的应用 → 上传自定义应用 → 选择 ZIP
这通常比手动编辑 JSON 清单更容易。
选项 A: Azure Web Chat (先验证 webhook)
- 在 Azure Portal 中 → 你的 Azure Bot 资源 → Test in Web Chat
- 发送一条消息 - 你应该能看到回复
- 这在 Teams 设置之前确认你的 webhook 端点工作正常
选项 B: Teams (安装应用后)
- 安装 Teams 应用(侧载或组织目录)
- 在 Teams 中找到机器人并发送私信
- 检查网关日志以获取传入活动
设置 (最小文本版)
Section titled “设置 (最小文本版)”安装 Microsoft Teams 插件
- 从 npm:
openclaw plugins install @openclaw/msteams - 从本地检出:
openclaw plugins install ./extensions/msteams
- 从 npm:
机器人注册
- 创建 Azure Bot (见上文) 并记录:
- App ID
- Client secret (App password)
- Tenant ID (single-tenant)
- 创建 Azure Bot (见上文) 并记录:
Teams 应用清单
- 包含一个
bot条目,其中botId = <App ID>. - 范围:
personal,team,groupChat. supportsFiles: true(个人范围文件处理所需).- 添加 RSC 权限 (见下文).
- 创建图标:
outline.png(32x32) 和color.png(192x192). - 将所有三个文件压缩在一起:
manifest.json,outline.png,color.png.
- 包含一个
配置 OpenClaw
{"msteams": {"enabled": true,"appId": "<APP_ID>","appPassword": "<APP_PASSWORD>","tenantId": "<TENANT_ID>","webhook": { "port": 3978, "path": "/api/messages" }}}你也可以使用环境变量代替配置键:
MSTEAMS_APP_IDMSTEAMS_APP_PASSWORDMSTEAMS_TENANT_ID
机器人端点
- 将 Azure Bot Messaging Endpoint 设置为:
https://<host>:3978/api/messages(或你选择的路径/端口).
- 将 Azure Bot Messaging Endpoint 设置为:
运行网关
- 当插件安装且
msteams配置存在凭据时,Teams 通道会自动启动。
- 当插件安装且
channels.msteams.historyLimit控制有多少最近的频道/群组消息被包装到提示中。- 回退到
messages.groupChat.historyLimit。设置为0以禁用 (默认 50)。 - 私信历史可以通过
channels.msteams.dmHistoryLimit(用户轮次) 进行限制。每用户覆盖:channels.msteams.dms["<user_id>"].historyLimit.
当前 Teams RSC 权限 (清单)
Section titled “当前 Teams RSC 权限 (清单)”这些是我们 Teams 应用清单中 现有的 resourceSpecific 权限。它们仅适用于安装了应用的团队/聊天。
对于频道 (团队范围):
ChannelMessage.Read.Group(Application) - 接收所有频道消息而无需 @提及ChannelMessage.Send.Group(Application)Member.Read.Group(Application)Owner.Read.Group(Application)ChannelSettings.Read.Group(Application)TeamMember.Read.Group(Application)TeamSettings.Read.Group(Application)
对于群聊:
ChatMessage.Read.Chat(Application) - 接收所有群聊消息而无需 @提及
示例 Teams 清单 (已删减)
Section titled “示例 Teams 清单 (已删减)”包含所需字段的最小有效示例。替换 ID 和 URL。
{ "$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" } ] } }}清单注意事项 (必填字段)
Section titled “清单注意事项 (必填字段)”bots[].botId必须 与 Azure Bot App ID 匹配。webApplicationInfo.id必须 与 Azure Bot App ID 匹配。bots[].scopes必须包括你计划使用的界面 (personal,team,groupChat).bots[].supportsFiles: true对于个人范围内的文件处理是必需的。- 如果你想要频道流量,
authorization.permissions.resourceSpecific必须包括频道读取/发送。
更新现有应用
Section titled “更新现有应用”要更新已安装的 Teams 应用(例如,添加 RSC 权限):
- 使用新设置更新你的
manifest.json - 增加
version字段 (例如1.0.0→1.1.0) - 重新压缩 清单和图标 (
manifest.json,outline.png,color.png) - 上传新的 zip:
- 选项 A (Teams Admin Center): Teams Admin Center → Teams apps → Manage apps → find your app → Upload new version
- 选项 B (Sideload): In Teams → Apps → Manage your apps → Upload a custom app
- 对于团队频道: 在每个团队中重新安装应用以使新权限生效
- 完全退出并重新启动 Teams (不仅仅是关闭窗口) 以清除缓存的应用元数据
功能:仅 RSC vs Graph
Section titled “功能:仅 RSC vs Graph”仅 Teams RSC (已安装应用,无 Graph API 权限)
Section titled “仅 Teams RSC (已安装应用,无 Graph API 权限)”工作:
- 读取频道消息 文本 内容。
- 发送频道消息 文本 内容。
- 接收 个人 (DM) 文件附件。
不工作:
- 频道/群组 图像或文件内容 (负载仅包含 HTML 存根)。
- 下载存储在 SharePoint/OneDrive 中的附件。
- 读取消息历史记录(超出实时 webhook 事件)。
Teams RSC + Microsoft Graph Application 权限
Section titled “Teams RSC + Microsoft Graph Application 权限”增加:
- 下载托管内容(粘贴到消息中的图像)。
- 下载存储在 SharePoint/OneDrive 中的文件附件。
- 通过 Graph 读取频道/聊天消息历史记录。
RSC vs Graph API
Section titled “RSC vs Graph API”| 功能 | RSC 权限 | Graph API |
|---|---|---|
| 实时消息 | 是 (通过 webhook) | 否 (仅轮询) |
| 历史消息 | 否 | 是 (可以查询历史) |
| 设置复杂性 | 仅应用清单 | 需要管理员同意 + 令牌流 |
| 离线工作 | 否 (必须运行) | 是 (随时查询) |
底线: RSC 用于实时监听;Graph API 用于历史访问。为了在离线时补上错过的消息,你需要具有 ChannelMessage.Read.All 的 Graph API(需要管理员同意)。
Graph 启用的媒体 + 历史 (频道必需)
Section titled “Graph 启用的媒体 + 历史 (频道必需)”如果你需要 频道 中的图像/文件或想要获取 消息历史记录,必须启用 Microsoft Graph 权限并授予管理员同意。
- 在 Entra ID (Azure AD) App Registration 中,添加 Microsoft Graph Application 权限:
ChannelMessage.Read.All(频道附件 + 历史)Chat.Read.All或ChatMessage.Read.All(群聊)
- 为租户 授予管理员同意。
- 提升 Teams 应用 清单版本,重新上传,并在 Teams 中 重新安装应用。
- 完全退出并重新启动 Teams 以清除缓存的应用元数据。
Webhook 超时
Section titled “Webhook 超时”Teams 通过 HTTP webhook 投递消息。如果处理时间过长(例如,慢速 LLM 响应),你可能会看到:
- 网关超时
- Teams 重试消息(导致重复)
- 丢失回复
OpenClaw 通过快速返回并主动发送回复来处理此问题,但非常慢的响应仍可能导致问题。
Teams markdown 比 Slack 或 Discord 更有限:
- 基本格式工作正常:bold, italic,
code, 链接 - 复杂 markdown (表格, 嵌套列表) 可能无法正确渲染
- 支持 Adaptive Cards 用于投票和任意卡片发送(见下文)
关键设置 (参见 /docs/gateway/configuration 获取共享通道模式):
channels.msteams.enabled: 启用/禁用通道。channels.msteams.appId,channels.msteams.appPassword,channels.msteams.tenantId: 机器人凭据。channels.msteams.webhook.port(默认3978)channels.msteams.webhook.path(默认/api/messages)channels.msteams.dmPolicy:pairing | allowlist | open | disabled(默认: pairing)channels.msteams.allowFrom: 私信白名单(AAD 对象 ID、UPN 或显示名称)。当 Graph 访问可用时,向导会在设置期间将名称解析为 ID。channels.msteams.textChunkLimit: 出站文本块大小。channels.msteams.chunkMode:length(默认) 或newline在长度分块之前先在空行(段落边界)拆分。channels.msteams.mediaAllowHosts: 入站附件主机的白名单(默认为 Microsoft/Teams 域)。channels.msteams.requireMention: 在频道/群组中需要 @提及 (默认 true)。channels.msteams.replyStyle:thread | top-level(参见 回复风格)。channels.msteams.teams.<teamId>.replyStyle: 每团队覆盖。channels.msteams.teams.<teamId>.requireMention: 每团队覆盖。channels.msteams.teams.<teamId>.tools: 默认的每团队工具策略覆盖 (allow/deny/alsoAllow),当缺少频道覆盖时使用。channels.msteams.teams.<teamId>.toolsBySender: 默认的每团队每发送者工具策略覆盖 (支持"*"通配符)。channels.msteams.teams.<teamId>.channels.<conversationId>.replyStyle: 每频道覆盖。channels.msteams.teams.<teamId>.channels.<conversationId>.requireMention: 每频道覆盖。channels.msteams.teams.<teamId>.channels.<conversationId>.tools: 每频道工具策略覆盖 (allow/deny/alsoAllow).channels.msteams.teams.<teamId>.channels.<conversationId>.toolsBySender: 每频道每发送者工具策略覆盖 (支持"*"通配符)。channels.msteams.sharePointSiteId: 用于群聊/频道中文件上传的 SharePoint 站点 ID (参见 在群聊中发送文件)。
- 会话密钥遵循标准 agent 格式 (参见 /docs/concepts/session):
- 私信共享主会话 (
agent:<agentId>:<mainKey>). - 频道/群组消息使用会话 id:
agent:<agentId>:msteams:channel:<conversationId>agent:<agentId>:msteams:group:<conversationId>
- 私信共享主会话 (
回复风格: Threads vs Posts
Section titled “回复风格: Threads vs Posts”Teams 最近在相同的基础数据模型上引入了两种频道 UI 风格:
| 风格 | 描述 | 推荐 replyStyle |
|---|---|---|
| Posts (经典) | 消息显示为卡片,下面有线程回复 | thread (默认) |
| Threads (类 Slack) | 消息线性流动,更像 Slack | top-level |
问题: Teams API 不会暴露频道使用的 UI 风格。如果你使用了错误的 replyStyle:
- 在 Threads 风格频道中使用
thread→ 回复显示为尴尬的嵌套 - 在 Posts 风格频道中使用
top-level→ 回复显示为单独的顶级帖子而不是在线程中
解决方案: 根据频道的设置方式,按频道配置 replyStyle:
{ "msteams": { "replyStyle": "thread", "teams": { "19:abc...@thread.tacv2": { "channels": { "19:xyz...@thread.tacv2": { "replyStyle": "top-level" } } } } }}当前限制:
- 私信: 图像和文件附件通过 Teams bot 文件 API 工作。
- 频道/群组: 附件位于 M365 存储 (SharePoint/OneDrive) 中。Webhook 负载仅包含 HTML 存根,不包含实际文件字节。需要 Graph API 权限 才能下载频道附件。
如果没有 Graph 权限,带有图像的频道消息将仅作为纯文本接收(机器人无法访问图像内容)。 默认情况下,OpenClaw 仅从 Microsoft/Teams 主机名下载媒体。使用 channels.msteams.mediaAllowHosts 覆盖(使用 ["*"] 允许任何主机)。
在群聊中发送文件
Section titled “在群聊中发送文件”机器人可以使用 FileConsentCard 流程(内置)在私信中发送文件。但是,在群聊/频道中发送文件 需要额外的设置:
| 上下文 | 文件发送方式 | 所需设置 |
|---|---|---|
| 私信 | FileConsentCard → 用户接受 → 机器人上传 | 开箱即用 |
| 群聊/频道 | 上传到 SharePoint → 分享链接 | 需要 sharePointSiteId + Graph 权限 |
| 图像 (任何上下文) | Base64 编码内联 | 开箱即用 |