Microsoft Teams(插件)
“进入此地者,放弃一切希望。”更新时间:2026-01-21 状态:支持文本 + 私信附件;频道/群组文件发送需要
sharePointSiteId + Graph 权限(参见在群聊中发送文件)。投票通过 Adaptive Cards 发送。 Polls are sent via Adaptive Cards.
需要插件
Microsoft Teams 作为插件提供,不包含在核心安装中。 破坏性变更(2026.1.15): MS Teams 已从核心移出。如果你使用它,必须安装插件。 If you use it, you must install the plugin. 原因说明:保持核心安装更轻量,并让 MS Teams 依赖项可以独立更新。 通过 CLI 安装(npm 注册表):快速设置(初学者)
- 安装 Microsoft Teams 插件。
- 创建一个 Azure Bot(App ID + 客户端密钥 + 租户 ID)。
- 使用这些凭证配置 OpenClaw。
- 通过公共 URL 或隧道暴露
/api/messages(默认端口 3978)。 - 安装 Teams 应用包并启动 Gateway 网关。
channels.msteams.groupPolicy: "allowlist")。要允许群组回复,请设置 channels.msteams.groupAllowFrom(或使用 groupPolicy: "open" 允许任何成员,需要提及才能触发)。 要允许群聊回复,请设置 channels.msteams.groupAllowFrom(或使用 groupPolicy: "open" 以允许任何成员,但需要提及)。
目标
- 通过 Teams 私信、群聊或频道与 OpenClaw 交流。
- 保持路由确定性:回复始终返回到消息到达的渠道。
- 默认使用安全的渠道行为(除非另有配置,否则需要提及)。
配置写入
默认情况下,Microsoft Teams 允许通过/config set|unset 触发的配置更新写入(需要 commands.config: true)。
禁用方式:
访问控制(私信 + 群组)
私信访问- 默认:
channels.msteams.dmPolicy = "pairing"。未知发送者在获得批准之前将被忽略。 未知发送者在获得批准之前会被忽略。 channels.msteams.allowFrom接受 AAD 对象 ID、UPN 或显示名称。当凭证允许时,向导会通过 Microsoft Graph 将名称解析为 ID。 当凭据允许时,向导会通过 Microsoft Graph 将名称解析为 ID。
channels.msteams.teams.<teamId> .tools:当缺少频道覆盖时使用的默认每团队工具策略覆盖(allow/deny/alsoAllow)。channels.msteams.groupAllowFrom控制哪些发送者可以在群聊/频道中触发(回退到channels.msteams.allowFrom)。- 设置
groupPolicy: "open"允许任何成员(默认仍需提及才能触发)。 - 要不允许任何频道,设置
channels.msteams.groupPolicy: "disabled"。
- 通过在
channels.msteams.teams下列出团队和频道来限定群组/频道回复的范围。 - 键可以是团队 ID 或名称;频道键可以是会话 ID 或名称。
- 当
groupPolicy="allowlist"且存在团队允许列表时,仅接受列出的团队/频道(需要提及才能触发)。 - 配置向导接受
Team/Channel条目并为你存储。 - 启动时,OpenClaw 将团队/频道和用户允许列表名称解析为 ID(当 Graph 权限允许时) 并记录映射;未解析的条目保持原样。
工作原理
- 安装 Microsoft Teams 插件。
- 创建一个 Azure Bot(App ID + 密钥 + 租户 ID)。
- 构建一个引用机器人并包含以下 RSC 权限的 Teams 应用包。
- 将 Teams 应用上传/安装到团队中(或用于私信的个人范围)。
- 在
~/.openclaw/openclaw.json(或环境变量)中配置msteams并启动 Gateway 网关。 - Gateway 网关默认在
/api/messages上监听 Bot Framework webhook 流量。
Azure Bot 设置(前提条件)
在配置 OpenClaw 之前,你需要创建一个 Azure Bot 资源。步骤 1:创建 Azure Bot
- 前往创建 Azure Bot
-
填写基本信息选项卡:
字段 值 机器人句柄 你的机器人名称,例如 openclaw-msteams(必须唯一)订阅 选择你的 Azure 订阅 资源组 新建或使用现有 定价层级 Free 用于开发/测试 应用类型 Single Tenant(推荐 - 见下方说明) 创建类型 创建新的 Microsoft 应用 ID
弃用通知: 2025-07-31 之后已弃用创建新的多租户机器人。新机器人请使用 Single Tenant。 19. 新机器人请使用 Single Tenant。
- 点击 Review + create → Create(等待约 1-2 分钟)
步骤 2:获取凭证
- 前往你的 Azure Bot 资源 → Configuration
- 复制 Microsoft App ID → 这是你的
appId - 点击 Manage Password → 前往应用注册
- 在 Certificates & secrets → New client secret → 复制 Value → 这是你的
appPassword - 前往 Overview → 复制 Directory (tenant) ID → 这是你的
tenantId
步骤 3:配置消息端点
- 在 Azure Bot → Configuration
- 将 Messaging endpoint 设置为你的 webhook URL:
- 生产环境:
https://your-domain.com/api/messages - 本地开发:使用隧道(见下方本地开发)
- 生产环境:
步骤 4:启用 Teams 渠道
- 在 Azure Bot → Channels
- 点击 Microsoft Teams → Configure → Save
- 接受服务条款
本地开发(隧道)
Teams 无法访问localhost。本地开发请使用隧道: 38. 本地开发请使用隧道:
选项 A:ngrok
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 中:Apps → Manage your apps → Upload a custom app → 选择 ZIP
测试机器人
选项 A:Azure Web Chat(先验证 webhook)- 在 Azure 门户 → 你的 Azure Bot 资源 → Test in Web Chat
- 发送一条消息 - 你应该看到响应
- 这确认你的 webhook 端点在 Teams 设置之前正常工作
- 安装 Teams 应用(侧载或组织目录)
- 在 Teams 中找到机器人并发送私信
- 检查 Gateway 网关日志中的传入活动
设置(最小纯文本)
-
安装 Microsoft Teams 插件
- 从 npm:
openclaw plugins install @openclaw/msteams - 从本地检出:
openclaw plugins install ./extensions/msteams
- 从 npm:
-
机器人注册
- 创建一个 Azure Bot(见上文)并记录:
- 应用 ID
- 客户端密钥(App password)
- 租户 ID(单租户)
- 创建一个 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_APP_IDMSTEAMS_APP_PASSWORDMSTEAMS_TENANT_ID
-
机器人端点
- 将 Azure Bot Messaging Endpoint 设置为:
https://<host>:3978/api/messages(或你选择的路径/端口)。
- 将 Azure Bot Messaging Endpoint 设置为:
-
运行 Gateway 网关
- 当插件已安装且
msteams配置存在并有凭证时,Teams 渠道会自动启动。
- 当插件已安装且
39) 历史上下文
channels.msteams.historyLimit控制将多少条最近的频道/群组消息包含到提示中。- 回退到
messages.groupChat.historyLimit。设置0禁用(默认 50)。 42. 设置为0可禁用(默认 50)。 -
- 可通过
channels.msteams.dmHistoryLimit(按用户轮次)限制私信历史。 私信历史可以通过channels.msteams.dmHistoryLimit(用户轮次)限制。每用户覆盖:channels.msteams.dms["<user_id>"].historyLimit。
- 可通过
当前 Teams RSC 权限(清单)
这些是我们 Teams 应用清单中现有的 resourceSpecific 权限。它们仅适用于安装了应用的团队/聊天内部。 47. 它们仅适用于安装了该应用的团队/聊天内部。 对于频道(团队范围):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 清单示例(已脱敏)
包含必需字段的最小有效示例。请替换 ID 和 URL。 替换 ID 和 URL。清单注意事项(必填字段)
bots[].botId必须与 Azure Bot App ID 匹配。webApplicationInfo.id必须与 Azure Bot App ID 匹配。bots[].scopes必须包含你计划使用的界面(personal、team、groupChat)。bots[].supportsFiles: true是个人范围文件处理所需的。authorization.permissions.resourceSpecific如果你需要频道流量,必须包含频道读取/发送权限。
更新现有应用
要更新已安装的 Teams 应用(例如,添加 RSC 权限):- 使用新设置更新你的
manifest.json - 增加
version字段(例如,1.0.0→1.1.0) - 重新打包清单和图标(
manifest.json、outline.png、color.png) - 上传新的 zip:
- 选项 A(Teams 管理中心): Teams 管理中心 → Teams apps → Manage apps → 找到你的应用 → Upload new version
- 选项 B(侧载): 在 Teams 中 → Apps → Manage your apps → Upload a custom app
- 对于团队频道: 在每个团队中重新安装应用以使新权限生效
- 完全退出并重新启动 Teams(不仅仅是关闭窗口)以清除缓存的应用元数据
功能:仅 RSC 与 Graph
仅使用 Teams RSC(应用已安装,无 Graph API 权限)
可用:- 读取频道消息文本内容。
- 发送频道消息文本内容。
- 接收**个人(私信)**文件附件。
- 频道/群组图片或文件内容(负载仅包含 HTML 存根)。
- 下载存储在 SharePoint/OneDrive 中的附件。
- 读取消息历史(超出实时 webhook 事件)。
使用 Teams RSC + Microsoft Graph Application 权限
增加:- 下载托管内容(粘贴到消息中的图片)。
- 下载存储在 SharePoint/OneDrive 中的文件附件。
- 通过 Graph 读取频道/聊天消息历史。
RSC 与 Graph API 对比
| 功能 | RSC 权限 | Graph API |
|---|---|---|
| 实时消息 | 是(通过 webhook) | 否(仅轮询) |
| 历史消息 | 否 | 是(可查询历史) |
| 设置复杂度 | 仅应用清单 | 需要管理员同意 + 令牌流程 |
| 离线工作 | 否(必须运行) | 是(随时查询) |
ChannelMessage.Read.All 的 Graph API(需要管理员同意)。 For catching up on missed messages while offline, you need Graph API with ChannelMessage.Read.All (requires admin consent).
启用 Graph 的媒体 + 历史(频道所需)
如果你需要频道中的图片/文件或想要获取消息历史,你必须启用 Microsoft Graph 权限并授予管理员同意。- 在 Entra ID(Azure AD)App Registration 中,添加 Microsoft Graph Application 权限:
ChannelMessage.Read.All(频道附件 + 历史)Chat.Read.All或ChatMessage.Read.All(群聊)
- 为租户授予管理员同意。
- 提升 Teams 应用清单版本,重新上传,并在 Teams 中重新安装应用。
- 完全退出并重新启动 Teams 以清除缓存的应用元数据。
User.Read.All(应用程序)权限并授予管理员同意。
已知限制
Webhook 超时
Teams 通过 HTTP webhook 传递消息。如果处理时间过长(例如,LLM 响应缓慢),你可能会看到: If processing takes too long (e.g., slow LLM responses), you may see:- Gateway 网关超时
- Teams 重试消息(导致重复)
- 丢失的回复
格式化
Teams markdown 比 Slack 或 Discord 更有限:- 基本格式化有效:粗体、斜体、
代码、链接 - 复杂的 markdown(表格、嵌套列表)可能无法正确渲染
- 支持 Adaptive Cards 用于投票和任意卡片发送(见下文)
配置
关键设置(共享渠道模式见/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。 The wizard resolves names to IDs during setup when Graph access is available.channels.msteams.textChunkLimit:出站文本分块大小。channels.msteams.chunkMode:length(默认)或newline在长度分块之前按空行(段落边界)分割。channels.msteams.mediaAllowHosts:入站附件主机允许列表(默认为 Microsoft/Teams 域名)。channels.msteams.mediaAuthAllowHosts:在媒体重试时附加 Authorization 头的允许列表(默认为 Graph + Bot Framework 主机)。channels.msteams.requireMention:在频道/群组中需要 @提及(默认 true)。channels.msteams.replyStyle:thread | top-level(见回复样式)。channels.msteams.teams.<teamId>.replyStyle:每团队覆盖。channels.msteams.teams.<teamId>.requireMention:每团队覆盖。channels.msteams.teams.<teamId>默认:channels.msteams.groupPolicy = “allowlist”(除非添加groupAllowFrom,否则被阻止)。使用channels.defaults.groupPolicy` 在未设置时覆盖默认值。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(见在群聊中发送文件)。
路由和会话
- 会话键遵循标准智能体格式(见 /concepts/session):
- 私信共享主会话(
agent:<agentId>:<mainKey>)。 - 频道/群组消息使用会话 ID:
agent:<agentId>:msteams:channel:<conversationId>agent:<agentId>:msteams:group:<conversationId>
- 私信共享主会话(
回复样式:话题 vs 帖子
Teams 最近在相同的底层数据模型上引入了两种频道 UI 样式:| 样式 | 描述 | 推荐的 replyStyle |
|---|---|---|
| Posts(经典) | 消息显示为卡片,下方有话题回复 | thread(默认) |
| Threads(类 Slack) | 消息线性流动,更像 Slack | top-level |
replyStyle: If you use the wrong replyStyle:
- 在 Threads 样式频道中使用
thread→ 回复嵌套显示很别扭 - 在 Posts 样式频道中使用
top-level→ 回复显示为单独的顶级帖子而不是在话题中
replyStyle:
附件和图片
当前限制:- 私信: 图片和文件附件通过 Teams bot file API 工作。
- 频道/群组: 附件存储在 M365 存储(SharePoint/OneDrive)中。webhook 负载仅包含 HTML 存根,而非实际文件字节。需要 Graph API 权限才能下载频道附件。 The webhook payload only includes an HTML stub, not the actual file bytes. Graph API permissions are required to download channel attachments.
channels.msteams.mediaAllowHosts 覆盖(使用 ["*"] 允许任何主机)。
Authorization 头仅附加到 channels.msteams.mediaAuthAllowHosts 中的主机(默认为 Graph + Bot Framework 主机)。保持此列表严格(避免多租户后缀)。
By default, OpenClaw only downloads media from Microsoft/Teams hostnames. Override with channels.msteams.mediaAllowHosts (use ["*"] to allow any host).
Authorization headers are only attached for hosts in channels.msteams.mediaAuthAllowHosts (defaults to Graph + Bot Framework hosts). 保持此列表严格(避免多租户后缀)。
在群聊中发送文件
机器人可以在私聊(DM)中使用 FileConsentCard 流程(内置)发送文件。 但是,在群聊/频道中发送文件 需要额外配置:| 上下文 | 文件发送方式 | 所需设置 |
|---|---|---|
| 私信 | FileConsentCard → 用户接受 → 机器人上传 | 开箱即用 |
| 群聊/频道 | 上传到 SharePoint → 共享链接 | 需要 sharePointSiteId + Graph 权限 |
| 图片(任何上下文) | Base64 编码内联 | 开箱即用 |
为什么群聊需要 SharePoint
机器人没有个人 OneDrive 驱动器(/me/drive Graph API 端点对应用程序身份不起作用)。要在群聊/频道中发送文件,机器人上传到 SharePoint 站点并创建共享链接。 要在群聊/频道中发送文件,机器人会上传到 SharePoint 站点 并创建共享链接。
设置
-
在 Entra ID(Azure AD)→ App Registration 中添加 Graph API 权限:
Sites.ReadWrite.All(Application)- 上传文件到 SharePointChat.Read.All(Application)- 可选,启用每用户共享链接
- 为租户授予管理员同意。
-
获取你的 SharePoint 站点 ID:
-
配置 OpenClaw:
共享行为
| 权限 | 共享行为 |
|---|---|
仅 Sites.ReadWrite.All | 组织范围共享链接(组织中任何人都可以访问) |
Sites.ReadWrite.All + Chat.Read.All | 每用户共享链接(仅聊天成员可以访问) |
Chat.Read.All 权限,机器人回退到组织范围共享。 如果缺少 Chat.Read.All 权限,机器人将回退到组织范围共享。
回退行为
| 场景 | 结果 |
|---|---|
群聊 + 文件 + 已配置 sharePointSiteId | 上传到 SharePoint,发送共享链接 |
群聊 + 文件 + 无 sharePointSiteId | 尝试 OneDrive 上传(可能失败),仅发送文本 |
| 个人聊天 + 文件 | FileConsentCard 流程(无需 SharePoint 即可工作) |
| 任何上下文 + 图片 | Base64 编码内联(无需 SharePoint 即可工作) |
文件存储位置
上传的文件存储在配置的 SharePoint 站点默认文档库中的/OpenClawShared/ 文件夹中。
投票(Adaptive Cards)
OpenClaw 将 Teams 投票作为 Adaptive Cards 发送(没有原生 Teams 投票 API)。- CLI:
openclaw message poll --channel msteams --target conversation:<id> ... - 投票由 Gateway 网关记录在
~/.openclaw/msteams-polls.json中。 - Gateway 网关必须保持在线才能记录投票。
- 投票尚不自动发布结果摘要(如需要请检查存储文件)。
Adaptive Cards(任意)
使用message 工具或 CLI 向 Teams 用户或会话发送任意 Adaptive Card JSON。
card 参数接受 Adaptive Card JSON 对象。当提供 card 时,消息文本是可选的。 10. 提供 card 时,消息文本是可选的。
智能体工具:
目标格式
MSTeams 目标使用前缀来区分用户和会话:| 目标类型 | 格式 | 示例 |
|---|---|---|
| 用户(按 ID) | user:<aad-object-id> | user:40a1a0ed-4ff2-4164-a219-55518990c197 |
| 用户(按名称) | user:<display-name> | user:John Smith(需要 Graph API) |
| 群组/频道 | conversation:<conversation-id> | conversation:19:[email protected] |
| 群组/频道(原始) | <conversation-id> | 19:[email protected](如果包含 @thread) |
user: 前缀时,名称默认解析为群组/团队。按显示名称定位人员时始终使用 user:。 40. 通过显示名称定位人员时,始终使用 user:。
主动消息
- 主动消息仅在用户交互之后才可能,因为我们在那时存储会话引用。
- 有关
dmPolicy和允许列表控制,请参见/gateway/configuration。
团队和频道 ID(常见陷阱)
Teams URL 中的groupId 查询参数不是用于配置的团队 ID。请从 URL 路径中提取 ID: 46. 请改为从 URL 路径中提取 ID:
团队 URL:
- 团队 ID =
/team/后的路径段(URL 解码,例如19:[email protected]) - 频道 ID =
/channel/后的路径段(URL 解码) - 忽略
groupId查询参数
Private Channels
机器人在私有频道中的支持有限:| 功能 | 标准频道 | Private Channels |
|---|---|---|
| 机器人安装 | 是 | 有限 |
| 实时消息(webhook) | 是 | 可能不工作 |
| RSC 权限 | 是 | 行为可能不同 |
| @提及 | 是 | 如果机器人可访问 |
| Graph API 历史 | 是 | 是(有权限) |
- 使用标准频道进行机器人交互
- 使用私信 - 用户始终可以直接给机器人发消息
- 使用 Graph API 进行历史访问(需要
ChannelMessage.Read.All)
故障排除
常见问题
- 频道中图片不显示: 缺少 Graph 权限或管理员同意。重新安装 Teams 应用并完全退出/重新打开 Teams。 Reinstall the Teams app and fully quit/reopen Teams.
- 频道中无响应: 默认需要提及;设置
channels.msteams.requireMention=false或按团队/频道配置。 - 版本不匹配(Teams 仍显示旧清单): 移除 + 重新添加应用并完全退出 Teams 以刷新。
- 来自 webhook 的 401 Unauthorized: 在没有 Azure JWT 的情况下手动测试时属于预期情况 - 意味着端点可达但认证失败。使用 Azure Web Chat 正确测试。 Use Azure Web Chat to test properly.
清单上传错误
- “Icon file cannot be empty”: 清单引用的图标文件为 0 字节。创建有效的 PNG 图标(
outline.png为 32x32,color.png为 192x192)。 Create valid PNG icons (32x32 foroutline.png, 192x192 forcolor.png). - “webApplicationInfo.Id already in use”: 应用仍安装在另一个团队/聊天中。先找到并卸载它,或等待 5-10 分钟让其传播。 Find and uninstall it first, or wait 5-10 minutes for propagation.
- 上传时”Something went wrong”: 改为通过 https://admin.teams.microsoft.com 上传,打开浏览器 DevTools(F12)→ Network 选项卡,检查响应正文中的实际错误。
- 侧载失败: 尝试”Upload an app to your org’s app catalog”而不是”Upload a custom app” - 这通常可以绕过侧载限制。
RSC 权限不工作
- 验证
webApplicationInfo.id与你的机器人 App ID 完全匹配 - 重新上传应用并在团队/聊天中重新安装
- 检查你的组织管理员是否阻止了 RSC 权限
- 确认你使用的是正确的范围:团队使用
ChannelMessage.Read.Group,群聊使用ChatMessage.Read.Chat
参考资料
- 创建 Azure Bot - Azure Bot 设置指南
- Teams 开发者门户 - 创建/管理 Teams 应用
- Teams 应用清单模式
- 使用 RSC 接收频道消息
- RSC 权限参考
- Teams 机器人文件处理(频道/群组需要 Graph)
- 主动消息