Microsoft Teams(插件)
“进入此处者,放弃一切希望。”
更新时间:2026-01-21
状态:支持文本和私信附件;发送频道/群组文件需要 sharePointSiteId + Graph 权限(详见 在群组聊天中发送文件)。投票通过 Adaptive Cards 发送。
需要插件
Microsoft Teams 作为插件提供,不包含在核心安装中。
重大变更(2026.1.15): MS Teams 已从核心组件中移除。如果使用它,必须安装插件。
可解释性:保持核心安装更轻量,并允许 MS Teams 的依赖项独立更新。
通过 CLI 安装(npm 仓库): bash clawdbot plugins install @clawdbot/msteams`````` 本地签出(当从 git 仓库运行时):```bash clawdbot plugins install ./extensions/msteams
如果在配置/引导过程中选择了 Teams,并且检测到 git 检出,
Clawdbot 将会自动提供本地安装路径。
详细信息:[插件](/plugin)
## 快速设置(初学者)
1) 安装 Microsoft Teams 插件。
2) 创建一个 **Azure Bot**(应用 ID + 客户端密钥 + 租户 ID)。
3) 使用这些凭据配置 Clawdbot。
4) 通过公共 URL 或隧道公开 `/api/messages`(默认端口为 3978)。
5) 安装 Teams 应用程序包并启动网关。
最小配置:
json5
{
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 私聊、群组聊天或频道与 Clawdbot 交流。
- 保持路由确定性:回复始终返回到它们到达的频道。
- 默认采用安全的频道行为(除非另行配置,否则需要提及)。
配置写入
默认情况下,Microsoft Teams 允许通过 /config set|unset 触发的配置更新(需要 commands.config: true)。
禁用方式为:```json5 { channels: { msteams: { configWrites: false } } }
## 访问控制(私聊 + 群组)
**私聊访问**
- 默认值:`channels.msteams.dmPolicy = "pairing"`。未知发件人将被忽略,直到获得批准。
- `channels.msteams.allowFrom` 接受 AAD 对象 ID、UPN 或显示名称。当凭证允许时,向导会通过 Microsoft Graph 解析名称为 ID。
**群组访问**
- 默认值:`channels.msteams.groupPolicy = "allowlist"`(除非你添加 `groupAllowFrom`,否则将被阻止)。当未设置时,可以使用 `channels.defaults.groupPolicy` 覆盖默认值。
- `channels.msteams.groupAllowFrom` 控制哪些发件人可以在群组聊天/频道中触发消息(若未设置则回退到 `channels.msteams.allowFrom`)。
- 设置 `groupPolicy: "open"` 以允许任何成员(默认仍受提及限制)。
- 若要允许 **所有频道**,请设置 `channels.msteams.groupPolicy: "disabled"`。
示例:
json5
{
channels: {
msteams: {
groupPolicy: "allowlist",
groupAllowFrom: ["user@org.com"]
}
}
}
Teams + 通道白名单
- 通过在
channels.msteams.teams下列出 Teams 和通道来限制群组/通道的回复范围。 - 键可以是团队 ID 或名称;通道键可以是对话 ID 或名称。
- 当
groupPolicy="allowlist"并且存在 Teams 白名单时,仅接受列出的 Teams/通道(提及限制)。 - 配置向导会接受
团队/通道的条目并为您保存。 - 在启动时,Clawdbot 会将团队/通道和用户白名单的名称解析为 ID(当 Graph 权限允许时), 并记录映射关系;无法解析的条目会以原始输入形式保留。
示例:```json5 { channels: { msteams: { groupPolicy: “allowlist”, teams: { “My Team”: { channels: { “General”: { requireMention: true } } } } } } }
## 它是如何工作的
1. 安装 Microsoft Teams 插件。
2. 创建一个 **Azure Bot**(应用 ID + 密钥 + 租户 ID)。
3. 构建一个 **Teams 应用包**,该包引用 bot 并包含以下 RSC 权限。
4. 将 Teams 应用上传/安装到一个团队(或用于私聊的个人范围)。
5. 在 `~/.clawdbot/clawdbot.json`(或环境变量)中配置 `msteams`,然后启动网关。
6. 网关默认在 `/api/messages` 上监听 Bot Framework 的 webhook 流量。
## Azure Bot 设置(先决条件)
在配置 Clawdbot 之前,你需要创建一个 Azure Bot 资源。
### 步骤 1:创建 Azure Bot
1. 前往 [创建 Azure Bot](https://portal.azure.com/#create/Microsoft.AzureBot)
2. 填写 **基础信息** 选项卡:
| 字段 | 值 |
|-------|-------|
| **Bot 名称** | 你的 bot 名称,例如 `clawdbot-msteams`(必须唯一) |
| **订阅** | 选择你的 Azure 订阅 |
| **资源组** | 创建新组或使用现有组 |
| **定价层级** | **免费**(用于开发和测试) |
| **应用类型** | **单租户**(推荐 - 请参见下面的说明) |
| **创建类型** | **创建新的 Microsoft 应用 ID** |
> **弃用通知:** 从 2025-07-31 起,不再支持创建新的多租户 bot。请为新 bot 使用 **单租户**。
3. 点击 **审核 + 创建** → **创建**(等待约 1-2 分钟)
### 步骤 2:获取凭据
1. 前往你的 Azure Bot 资源 → **配置**
2. 复制 **Microsoft 应用 ID** → 这是你的 `appId`
3. 点击 **管理密码** → 进入应用注册页面
4. 在 **证书与密码** 下 → 点击 **新建客户端密码** → 复制 **值** → 这是你的 `appPassword`
5. 前往 **概览** → 复制 **目录(租户)ID** → 这是你的 `tenantId`
### 步骤 3:配置消息端点
1. 在 Azure Bot 中 → **配置**
2. 将 **消息端点** 设置为你的 webhook URL:
- 生产环境:`https://your-domain.com/api/messages`
- 本地开发:使用隧道(请参见下方的 [本地开发](#local-development) 隧道部分)
### 步骤 4:启用 Teams 渠道
1. 在 Azure Bot 中 → **渠道**
2. 点击 **Microsoft Teams** → 配置 → 保存
3. 接受服务条款
## 本地开发(隧道)
Teams 无法访问 `localhost`。请使用隧道进行本地开发:
**选项 A:ngrok**
bash
ngrok http 3978
# Copy the https URL, e.g., https://abc123.ngrok.io
# Set messaging endpoint to: https://abc123.ngrok.io/api/messages``````
**选项 B:Tailscale Funnel**```bash
tailscale funnel 3978
# Use your Tailscale funnel URL as the messaging endpoint
Teams 开发者门户(替代方法)
除了手动创建清单 ZIP 文件外,您还可以使用 Teams 开发者门户:
- 点击 + 新建应用
- 填写基本信息(名称、描述、开发者信息)
- 进入 应用功能 → Bot
- 选择 手动输入 Bot ID 并粘贴您的 Azure Bot 应用 ID
- 勾选作用域:个人, 团队, 群组聊天
- 点击 分发 → 下载应用包
- 在 Teams 中:应用 → 管理您的应用 → 上传自定义应用 → 选择 ZIP 文件
这种方法通常比手动编辑 JSON 清单更容易。
测试 Bot
选项 A:Azure Web Chat(先验证 Webhook)
- 在 Azure 门户 → 您的 Azure Bot 资源 → 在 Web Chat 中测试
- 发送一条消息 - 您应该会看到回复
- 这可以确认您的 Webhook 端点在 Teams 设置前正常工作
选项 B:Teams(应用安装后)
- 安装 Teams 应用(侧载或组织目录)
- 在 Teams 中找到 Bot 并发送私信
- 检查网关日志以查看传入的活动
设置(最小文本模式)
- 安装 Microsoft Teams 插件
- 从 npm 安装:
clawdbot plugins install @clawdbot/msteams - 从本地检出安装:
clawdbot plugins install ./extensions/msteams
- 从 npm 安装:
- Bot 注册
- 创建 Azure Bot(请参见上文),并记录以下信息:
- 应用 ID
- 客户端密钥(应用密码)
- 租户 ID(单租户)
- 创建 Azure Bot(请参见上文),并记录以下信息:
- Teams 应用清单
- 包含一个
bot条目,其中botId = <应用 ID>。 - 作用域:
personal,team,groupChat。 supportsFiles: true(用于个人作用域的文件处理)。- 添加 RSC 权限(如下所述)。
- 创建图标:
outline.png(32x32)和color.png(192x192)。 - 将三个文件一起压缩:
manifest.json,outline.png,color.png。
- 包含一个
- 配置 Clawdbot
json
{
“msteams”: {
“enabled”: true,
“appId”: “
", "appPassword": " ", "tenantId": " ", "webhook": { "port": 3978, "path": "/api/messages" } } } `````` ``` 您可以使用环境变量代替配置键: MSTEAMS_APP_IDMSTEAMS_APP_PASSWORDMSTEAMS_TENANT_ID
- Bot 端点
- 将 Azure Bot 消息端点设置为:
https://<host>:3978/api/messages(或您选择的路径/端口)。
- 将 Azure Bot 消息端点设置为:
- 运行网关
- 当插件安装并存在
msteams配置及凭证时,Teams 通道会自动启动。
- 当插件安装并存在
历史记录上下文
channels.msteams.historyLimit控制多少条最近的频道/群组消息会被包含到提示中。- 如果未设置,则会回退到
messages.groupChat.historyLimit。设置0表示禁用(默认为 50)。 - 可以通过
channels.msteams.dmHistoryLimit限制私聊历史记录(按用户轮次)。每个用户的覆盖设置为:channels.msteams.dms["<user_id>"].historyLimit。
当前 Teams RSC 权限(Manifest)
这是我们 Teams 应用程序的 现有资源特定权限。这些权限仅在应用被安装的团队/聊天中生效。
对于频道(团队范围):
ChannelMessage.Read.Group(应用程序) - 无需@提醒即可接收所有频道消息ChannelMessage.Send.Group(应用程序)Member.Read.Group(应用程序)Owner.Read.Group(应用程序)ChannelSettings.Read.Group(应用程序)TeamMember.Read.Group(应用程序)TeamSettings.Read.Group(应用程序)
对于群组聊天:
ChatMessage.Read.Chat(应用程序) - 无需@提醒即可接收所有群组聊天消息
示例 Teams Manifest(已脱敏)
一个包含必要字段的最小有效示例。请替换 ID 和 URL。```json { “$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”: “Clawdbot” }, “developer”: { “name”: “Your Org”, “websiteUrl”: “https://example.com”, “privacyUrl”: “https://example.com/privacy”, “termsOfUseUrl”: “https://example.com/terms” }, “description”: { “short”: “Clawdbot in Teams”, “full”: “Clawdbot 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” } ] } } }
### 清单注意事项(必须包含的字段)
- `bots[].botId` **必须** 与 Azure Bot 应用 ID 匹配。
- `webApplicationInfo.id` **必须** 与 Azure Bot 应用 ID 匹配。
- `bots[].scopes` 必须包含你计划使用的表面(`personal`、`team`、`groupChat`)。
- `bots[].supportsFiles: true` 是在个人作用域中处理文件所必需的。
- 如果你想读取或发送频道消息,`authorization.permissions.resourceSpecific` 必须包含 `channel read` 和 `channel send`。
### 更新现有应用
要更新已安装的 Teams 应用(例如,添加 RSC 权限):
1. 使用新设置更新你的 `manifest.json`
2. **增加 `version` 字段**(例如,`1.0.0` → `1.1.0`)
3. **重新压缩** 包含图标(`manifest.json`、`outline.png`、`color.png`)的清单文件
4. 上传新的 zip 文件:
- **选项 A(Teams 管理中心):** Teams 管理中心 → Teams 应用 → 管理应用 → 找到你的应用 → 上传新版本
- **选项 B(侧载):** 在 Teams 中 → 应用 → 管理你的应用 → 上传自定义应用
5. **对于团队频道:** 在每个团队中重新安装应用,以使新权限生效
6. **完全退出并重新启动 Teams**(不只是关闭窗口),以清除缓存的应用元数据
## 功能:仅 RSC 与 Graph
### 仅使用 **Teams RSC**(应用已安装,无 Graph API 权限)
可以实现:
- 读取频道消息的 **文本内容**。
- 发送频道消息的 **文本内容**。
- 接收 **个人聊天(DM)** 中的文件附件。
无法实现:
- 读取频道/群组中的 **图片或文件内容**(仅包含 HTML 占位符)。
- 从 SharePoint/OneDrive 下载附件。
- 读取消息历史记录(超出实时 webhook 事件之外)。
### 使用 **Teams RSC + Microsoft Graph 应用权限**
新增功能包括:
- 下载消息中插入的图片。
- 从 SharePoint/OneDrive 下载文件附件。
- 通过 Graph 读取频道/聊天的消息历史记录。
## RSC 与 Graph API 对比
| 功能 | RSC 权限 | Graph API |
|------|----------|-----------|
| **实时消息** | 是(通过 webhook) | 否(仅支持轮询) |
| **历史消息** | 否 | 是(可以查询历史) |
| **设置复杂度** | 仅需应用清单 | 需要管理员同意 + 令牌流程 |
| **离线工作** | 否(必须运行) | 是(随时可查询) |
**总结:** RSC 用于实时监听;Graph API 用于历史访问。如果你需要在离线时查看错过的消息,你需要使用 Graph API 并授予 `ChannelMessage.Read.All` 权限(需要管理员同意)。
## 启用 Graph 的媒体和历史记录(用于频道的必要条件)
如果你需要在 **频道** 中获取图片/文件,或者想要获取 **消息历史记录**,你必须启用 Microsoft Graph 权限并获得管理员同意。
1. 在 Entra ID(Azure AD)**应用注册**中,添加 Microsoft Graph **应用权限**:
- `ChannelMessage.Read.All`(频道附件 + 历史记录)
- `Chat.Read.All` 或 `ChatMessage.Read.All`(群组聊天)
2. **为租户授予管理员同意**。
3. 升级 Teams 应用的 **manifest 版本**,重新上传,并**在 Teams 中重新安装应用**。
4. **完全退出并重新启动 Teams** 以清除缓存的应用元数据。
## 已知限制
### Webhook 超时
Teams 通过 HTTP webhook 发送消息。如果处理时间过长(例如,LLM 响应缓慢),可能会出现以下情况:
- 网关超时
- Teams 重试消息(导致重复)
- 回复被丢弃
Clawdbot 通过快速返回并主动发送回复来处理这些问题,但非常慢的响应仍可能导致问题。
### 格式化
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`: 允许的 DM 来源(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`(见 [回复样式](#reply-style-threads-vs-posts))。
- `channels.msteams.teams.<teamId>.replyStyle`: 按团队覆盖的回复样式。
- `channels.msteams.teams.<teamId>.requireMention`: 按团队覆盖的 @ 提及要求。
- `channels.msteams.teams.<teamId>.channels.<conversationId>.replyStyle`: 按频道覆盖的回复样式。
- `channels.msteams.teams.<teamId>.channels.<conversationId>.requireMention`: 按频道覆盖的 @ 提及要求。
- `channels.msteams.sharePointSiteId`: 群组聊天/频道中文件上传的 SharePoint 站点 ID(见 [在群组聊天中发送文件](#sending-files-in-group-chats))。
## 路由与会话
- 会话密钥遵循标准代理格式(参见 [/concepts/session](/concepts/session)):
- 直接消息使用主会话(`agent:<agentId>:<mainKey>`)。
- 频道/群组消息使用对话 ID:
- `agent:<agentId>:msteams:channel:<conversationId>`
- `agent:<agentId>:msteams:group:<conversationId>`
## 回复样式:线程 vs 帖子
Teams 最近引入了两种频道 UI 样式,基于相同的底层数据模型:
| 样式 | 描述 | 推荐的 `replyStyle` |
|-------|-------------|--------------------------|
| **帖子**(经典) | 消息以卡片形式显示,线程回复在下方 | `thread`(默认) |
| **线程**(类似 Slack) | 消息线性流动,更像 Slack | `top-level` |
**问题:** Teams API 并不暴露频道使用的 UI 样式。如果你使用了错误的 `replyStyle`:
- 在线程样式频道中使用 `thread` → 回复会以嵌套的方式显示,显得不自然
- 在帖子样式频道中使用 `top-level` → 回复会作为独立的顶层帖子显示,而不是在消息内线程中
**解决方案:** 根据频道的设置为每个频道配置 `replyStyle`:
json
{
"msteams": {
"replyStyle": "thread",
"teams": {
"19:abc...@thread.tacv2": {
"channels": {
"19:xyz...@thread.tacv2": {
"replyStyle": "top-level"
}
}
}
}
}
}
附件与图片
当前限制:
- 私聊(DMs): 图片和文件附件通过 Teams bot 文件 API 实现。
- 频道/群组: 附件存储在 M365 存储中(SharePoint/OneDrive)。Webhook 的 payload 仅包含 HTML 占位符,而非实际文件字节。需要 Graph API 权限 才能下载频道附件。
没有 Graph 权限的情况下,频道中的图片消息将仅以文本形式接收(图片内容无法被 bot 访问)。
默认情况下,Clawdbot 仅下载来自 Microsoft/Teams 主机名的媒体。可通过 channels.msteams.mediaAllowHosts 覆盖(使用 ["*"] 允许任何主机)。
在群组聊天中发送文件
Bots 可以通过 FileConsentCard 流程在私聊中发送文件(内置功能)。然而,在群组聊天/频道中发送文件 需要额外的设置:
| 上下文 | 文件如何发送 | 需要的设置 |
|---|---|---|
| 私聊 | FileConsentCard → 用户接受 → bot 上传 | 无需额外设置 |
| 群组聊天/频道 | 上传到 SharePoint → 生成分享链接 | 需要 sharePointSiteId + Graph 权限 |
| 图片(任何上下文) | Base64 编码的内联图片 | 无需额外设置 |
为什么群组聊天需要 SharePoint
Bots 没有个人的 OneDrive 驱动器(对于应用身份,/me/drive Graph API 端点无法使用)。要在群组聊天/频道中发送文件,bot 需要将文件上传到一个 SharePoint 站点,并创建一个分享链接。 ```bash
# Via Graph Explorer or curl with a valid token:
curl -H “Authorization: Bearer $TOKEN”
“https://graph.microsoft.com/v1.0/sites/{hostname}:/{site-path}”
# Example: for a site at “contoso.sharepoint.com/sites/BotFiles”
curl -H “Authorization: Bearer $TOKEN”
“https://graph.microsoft.com/v1.0/sites/contoso.sharepoint.com:/sites/BotFiles”
# Response includes: “id”: “contoso.sharepoint.com,guid1,guid2”
4. **配置 Clawdbot:**
json5
{
channels: {
msteams: {
// ... 其他配置 ...
sharePointSiteId: "contoso.sharepoint.com,guid1,guid2"
}
}
}``` ```
### 共享行为
| 权限 | 共享行为 |
|------------|------------------|
| 仅 `Sites.ReadWrite.All` | 组织范围内的共享链接(组织内任何人都可以访问) |
| `Sites.ReadWrite.All` + `Chat.Read.All` | 按用户共享链接(只有聊天成员可以访问) |
按用户共享更安全,因为只有聊天参与者才能访问文件。如果缺少 `Chat.Read.All` 权限,机器人将回退到组织范围内的共享。
### 回退行为
| 场景 | 结果 |
|----------|--------|
| 群组聊天 + 文件 + 配置了 `sharePointSiteId` | 上传到 SharePoint,发送共享链接 |
| 群组聊天 + 文件 + 未配置 `sharePointSiteId` | 尝试上传到 OneDrive(可能会失败),仅发送文本 |
| 个人聊天 + 文件 | 文件同意卡片流程(无需 SharePoint 即可工作) |
| 任何上下文 + 图像 | Base64 编码的内联图像(无需 SharePoint 即可工作) |
### 文件存储位置
上传的文件存储在配置的 SharePoint 站点的默认文档库中的 `/ClawdbotShared/` 文件夹中。
## 投票(自适应卡片)
Clawdbot 通过 Teams 发送自适应卡片格式的投票(Teams 没有原生的投票 API)。
- CLI: `clawdbot message poll --channel msteams --target conversation:<id> ...`
- 投票结果由网关记录在 `~/.clawdbot/msteams-polls.json` 中。
- 网关必须保持在线以记录投票。
- 投票目前还不支持自动发布结果摘要(如需查看,请检查存储文件)。
## 自适应卡片(任意)
使用 `message` 工具或 CLI 向 Teams 用户或聊天发送任意的自适应卡片 JSON。
`card` 参数接受一个自适应卡片 JSON 对象。当提供 `card` 时,消息文本是可选的。
**代理工具:**```json
{
"action": "send",
"channel": "msteams",
"target": "user:<id>",
"card": {
"type": "AdaptiveCard",
"version": "1.5",
"body": [{"type": "TextBlock", "text": "Hello!"}]
}
}
命令行界面(CLI):
bash
clawdbot message send –channel msteams
–target “conversation:19:abc…@thread.tacv2”
–card ‘{“type”:”AdaptiveCard”,”version”:”1.5”,”body”:[{“type”:”TextBlock”,”text”:”Hello!”}]}’
有关卡片架构和示例,请参阅 Adaptive Cards 文档。有关目标格式的详细信息,请参阅下面的 目标格式。
目标格式
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:abc123...@thread.tacv2 |
| 群组/频道(原始格式) | <conversation-id> |
19:abc123...@thread.tacv2(如果包含 @thread) |
CLI 示例:```bash
通过用户 ID 发送消息
clawdbot message send –channel msteams –target “user:40a1a0ed-…” –message “Hello”
通过显示名称发送消息(会触发 Graph API 查询)
clawdbot message send –channel msteams –target “user:John Smith” –message “Hello”
发送到群组聊天或频道
clawdbot message send –channel msteams –target “conversation:19:abc…@thread.tacv2” –message “Hello”
向对话发送 Adaptive Card
clawdbot message send –channel msteams –target “conversation:19:abc…@thread.tacv2”
–card ‘{“type”:”AdaptiveCard”,”version”:”1.5”,”body”:[{“type”:”TextBlock”,”text”:”Hello”}]}’
**代理工具示例:**
json
{
"action": "send",
"channel": "msteams",
"target": "user:John Smith",
"message": "Hello!"
}
{ “action”: “发送”, “channel”: “msteams”, “target”: “conversation:19:abc…@thread.tacv2”, “card”: {“type”: “自适应卡片”, “version”: “1.5”, “body”: [{“type”: “文本块”, “text”: “你好”}]} }
注意:当没有 user: 前缀时,名称默认为组/团队解析。在通过显示名称定位人员时,始终使用 user:。
主动消息
- 只有在用户进行过互动之后,才能发送主动消息,因为在那时我们才会存储对话引用。
- 请查看
/gateway/configuration中的dmPolicy和允许列表限制。
团队和频道 ID(常见陷阱)
Teams URL 中的 groupId 查询参数 不是 用于配置的团队 ID。请从 URL 路径中提取 ID:
团队 URL: https://teams.microsoft.com/l/team/19%3ABk4j…%40thread.tacv2/conversations?groupId=… └────────────────────────────┘ Team ID (URL-decode this)频道网址:
https://teams.microsoft.com/l/channel/19%3A15bc…%40thread.tacv2/ChannelName?groupId=… └─────────────────────────┘ 频道 ID(对这部分进行 URL 解码)`````` 关于配置:
- Team ID =
/team/之后的路径段(URL解码,例如19:Bk4j...@thread.tacv2) - Channel ID =
/channel/之后的路径段(URL解码) - 忽略
groupId查询参数
私有频道
机器人在私有频道中的支持有限:
| 功能 | 标准频道 | 私有频道 |
|---|---|---|
| 机器人安装 | 是 | 有限 |
| 实时消息(webhook) | 是 | 可能无法工作 |
| RSC 权限 | 是 | 行为可能不同 |
| @提及 | 是 | 如果机器人可访问 |
| Graph API 历史记录 | 是 | 是(需权限) |
如果私有频道不工作,可以尝试以下解决方法:
- 在标准频道中进行机器人交互
- 使用直接消息(DM) - 用户始终可以与机器人直接聊天
- 使用 Graph API 获取历史记录(需要
ChannelMessage.Read.All权限)
故障排除
常见问题
- 频道中图片不显示: 缺少 Graph 权限或管理员授权。重新安装 Teams 应用并彻底退出/重新打开 Teams。
- 频道中没有响应: 默认需要 @提及;可以设置
channels.msteams.requireMention=false或按团队/频道配置。 - 版本不匹配(Teams 仍显示旧的 manifest): 卸载并重新添加应用,并彻底退出 Teams 以刷新。
- webhook 返回 401 未授权: 在未使用 Azure JWT 手动测试时是正常的,表示端点可达但认证失败。请使用 Azure Web Chat 进行正确测试。
manifest 上传错误
- “图标文件不能为空”: manifest 引用了大小为 0 字节的图标文件。请创建有效的 PNG 图标(
outline.png为 32x32,color.png为 192x192)。 - “webApplicationInfo.Id 已被使用”: 应用仍在其他团队/聊天中安装。请先找到并卸载它,或等待 5-10 分钟以等待传播。
- 上传时出现 “Something went wrong”: 请通过 https://admin.teams.microsoft.com 上传,打开浏览器的 DevTools(F12)→ Network 标签,查看响应体以获取实际错误信息。
- 侧载失败: 尝试使用 “将应用上传到组织的应用目录” 而不是 “上传自定义应用” - 这通常可以绕过侧载限制。
RSC 权限不起作用
- 确认
webApplicationInfo.id与机器人的 App ID 完全一致 - 重新上传应用并重新在团队/聊天中安装
- 检查组织管理员是否阻止了 RSC 权限
- 确认使用了正确的权限范围:团队使用
ChannelMessage.Read.Group,群组聊天使用ChatMessage.Read.Chat
参考资料
- 创建 Azure Bot - Azure Bot 设置指南
- Teams 开发者门户 - 创建/管理 Teams 应用
- Teams 应用清单架构
- 通过 RSC 接收频道消息
- RSC 权限参考
- Teams bot 文件处理(频道/群组需要 Graph)
- 主动消息