通过 Azure Bot Service 将 OpenClaw 集成到 Microsoft Teams 工作区。
概述
Microsoft Teams 集成通过 @openclaw/msteams 插件提供支持,使用 Azure Bot Framework 实现。支持直接消息、频道消息、群组聊天、Adaptive Cards 等功能。
状态
以插件形式提供,需单独安装。生产环境可用。
前置要求
- 一个 Azure 账号(用于创建 Bot 注册)
- Microsoft 365 工作区或 Teams 账号
- 公网可访问的 HTTPS 端点(本地开发可使用 ngrok)
安装插件
openclaw plugins install @openclaw/msteams
Azure Bot 注册
1. 创建 Azure Bot
- 访问 Azure Portal
- 搜索 "Azure Bot" 并创建新资源
- 选择 "Single Tenant"(单租户)类型
- 记录以下信息:
- App ID(应用程序 ID)
- Tenant ID(租户 ID)
2. 创建客户端密钥
- 在 Azure Portal 中进入 "App registrations"
- 找到刚创建的应用
- 进入 "Certificates & secrets"
- 创建新的 Client Secret
- 记录 Secret Value(密钥值,这是 App Password)
重要
Client Secret 值只在创建时显示一次,请立即保存。
3. 配置 Messaging Endpoint
- 在 Azure Bot 资源的 "Configuration" 中
- 设置 Messaging endpoint:
https://your-domain.com/msteams/messages - 保存配置
4. 添加 Teams 频道
- 在 Azure Bot 的 "Channels" 设置中
- 添加 "Microsoft Teams" 频道
- 完成授权
Teams App Manifest
创建 manifest.json
{
"$schema": "https://developer.microsoft.com/en-us/json-schemas/teams/v1.16/MicrosoftTeams.schema.json",
"manifestVersion": "1.16",
"version": "1.0.0",
"id": "YOUR_APP_ID",
"packageName": "com.yourcompany.openclawbot",
"developer": {
"name": "Your Company",
"websiteUrl": "https://your-company.com",
"privacyUrl": "https://your-company.com/privacy",
"termsOfUseUrl": "https://your-company.com/terms"
},
"name": {
"short": "OpenClaw Bot",
"full": "OpenClaw AI Assistant"
},
"description": {
"short": "AI assistant powered by OpenClaw",
"full": "An intelligent AI assistant that helps with tasks and answers questions."
},
"icons": {
"outline": "outline.png",
"color": "color.png"
},
"accentColor": "#2c2d30",
"bots": [
{
"botId": "YOUR_APP_ID",
"scopes": ["personal", "team", "groupchat"],
"supportsFiles": true,
"isNotificationOnly": false
}
],
"permissions": ["identity", "messageTeamMembers"],
"validDomains": ["your-domain.com"],
"webApplicationInfo": {
"id": "YOUR_APP_ID",
"resource": "https://RscBasedStoreApp"
},
"authorization": {
"permissions": {
"resourceSpecific": [
{
"name": "ChannelMessage.Read.Group",
"type": "Application"
},
{
"name": "ChatMessage.Read.Chat",
"type": "Application"
},
{
"name": "TeamsActivity.Send.Group",
"type": "Application"
},
{
"name": "TeamsActivity.Send.Chat",
"type": "Application"
}
]
}
}
}
将 YOUR_APP_ID 替换为你的 Azure App ID。
5. 打包并上传 App
- 准备图标文件:
color.png(192x192)和outline.png(32x32) - 将
manifest.json和图标文件打包成 ZIP - 在 Teams 中点击 "Apps" → "Manage your apps" → "Upload an app"
- 选择 "Upload a custom app" 并上传 ZIP 文件
OpenClaw 配置
基础配置
{
channels: {
msteams: {
enabled: true,
appId: process.env.MSTEAMS_APP_ID,
appPassword: process.env.MSTEAMS_APP_PASSWORD,
tenantId: process.env.MSTEAMS_TENANT_ID,
webhook: {
path: "/msteams/messages", // 默认路径
port: 3000 // OpenClaw 网关端口
}
}
}
}
环境变量
export MSTEAMS_APP_ID="your-app-id"
export MSTEAMS_APP_PASSWORD="your-client-secret"
export MSTEAMS_TENANT_ID="your-tenant-id"
访问控制
直接消息策略
{
channels: {
msteams: {
enabled: true,
appId: process.env.MSTEAMS_APP_ID,
appPassword: process.env.MSTEAMS_APP_PASSWORD,
tenantId: process.env.MSTEAMS_TENANT_ID,
dmPolicy: "pairing" // 默认值
}
}
}
dmPolicy 选项:
"pairing"(默认):需要配对审批"allowlist":仅允许指定用户"open":接受所有直接消息"disabled":禁用直接消息
群组聊天策略
{
channels: {
msteams: {
enabled: true,
appId: process.env.MSTEAMS_APP_ID,
appPassword: process.env.MSTEAMS_APP_PASSWORD,
tenantId: process.env.MSTEAMS_TENANT_ID,
groupPolicy: "allowlist", // 默认为 "open"
groups: {
"19:meeting_xxxxx": { allow: true }, // 聊天 ID
"project-team": { allow: true } // 聊天名称
}
}
}
}
频道文件发送
在 Teams 频道中发送文件需要 SharePoint 权限:
{
channels: {
msteams: {
enabled: true,
appId: process.env.MSTEAMS_APP_ID,
appPassword: process.env.MSTEAMS_APP_PASSWORD,
tenantId: process.env.MSTEAMS_TENANT_ID,
sharePointSiteId: "your-site-id",
graphPermissions: ["Sites.ReadWrite.All"]
}
}
}
授予 Graph API 权限
- 在 Azure Portal 的 App registration 中
- 进入 "API permissions"
- 添加 "Microsoft Graph" 权限:
Sites.ReadWrite.All - 点击 "Grant admin consent"(需要管理员权限)
历史消息上下文
控制机器人可以读取的历史消息数量:
{
channels: {
msteams: {
enabled: true,
appId: process.env.MSTEAMS_APP_ID,
appPassword: process.env.MSTEAMS_APP_PASSWORD,
tenantId: process.env.MSTEAMS_TENANT_ID,
historyLimit: 50 // 默认值
}
}
}
目标识别
Teams 使用特殊的 ID 格式。使用以下前缀:
# 对话 ID(频道、群组聊天)
conversation:19:xxxxx@thread.tacv2
# 用户 ID
user:29:xxxxx
# ❌ 避免使用 groupId(从 URL 复制的值不可靠)
# ✅ 使用 URL 解码后的路径段
获取对话 ID
- 从 Teams URL 中提取并进行 URL 解码
- 或查看 OpenClaw 日志中的 conversation ID
- 使用 Graph API:
GET /teams/{team-id}/channels
Adaptive Cards
Teams 支持丰富的 Adaptive Cards UI:
// 在 OpenClaw 中发送 Adaptive Card
{
type: "AdaptiveCard",
version: "1.4",
body: [
{
type: "TextBlock",
text: "Poll: What's your favorite color?",
weight: "bolder",
size: "medium"
}
],
actions: [
{
type: "Action.Submit",
title: "Red",
data: { choice: "red" }
},
{
type: "Action.Submit",
title: "Blue",
data: { choice: "blue" }
}
]
}
本地开发(使用 ngrok)
1. 安装 ngrok
# macOS
brew install ngrok
# 或下载:https://ngrok.com/download
2. 启动隧道
# 假设 OpenClaw 在 3000 端口运行
ngrok http 3000
3. 更新 Azure Bot Endpoint
将 ngrok 生成的 HTTPS URL 设置为 Messaging endpoint:
https://xxxx-xx-xx-xxx-xxx.ngrok-free.app/msteams/messages
注意
免费版 ngrok URL 每次重启会变化,需要更新 Azure 配置。生产环境应使用固定域名。
配对工作流
# 查看待审批的配对请求
openclaw pairing list
# 批准用户
openclaw pairing approve msteams:29:xxxxx
# 撤销配对
openclaw pairing revoke msteams:29:xxxxx
故障排查
Bot 无法连接
- 验证 App ID、App Password、Tenant ID 正确
- 确认 Messaging endpoint 可公网访问
- 检查 Azure Bot 状态是否正常
消息未接收
- 确认 RSC 权限已在 manifest 中声明
- 检查 Teams app 是否已正确安装
- 查看 OpenClaw 日志:
openclaw logs --follow
文件发送失败
- 确认已配置
sharePointSiteId - 验证 Graph API 权限
Sites.ReadWrite.All已授权 - 检查管理员是否已同意权限
频道图片/文件下载失败
- 需要 Graph API 权限才能下载频道附件
- 添加
Files.Read.All或Files.ReadWrite.All - 确保管理员已同意
Webhook 验证失败
- 确认 OpenClaw 网关正在运行
- 检查端口和路径配置是否匹配
- 验证 HTTPS 证书有效
多账号配置
{
channels: {
msteams: {
accounts: {
corporate: {
enabled: true,
appId: process.env.MSTEAMS_APP_ID_CORP,
appPassword: process.env.MSTEAMS_APP_PASSWORD_CORP,
tenantId: process.env.MSTEAMS_TENANT_ID_CORP
},
partner: {
enabled: true,
appId: process.env.MSTEAMS_APP_ID_PARTNER,
appPassword: process.env.MSTEAMS_APP_PASSWORD_PARTNER,
tenantId: process.env.MSTEAMS_TENANT_ID_PARTNER,
dmPolicy: "allowlist"
}
}
}
}
}
安全建议
- 使用 Single Tenant 类型提高安全性
- 定期轮换 Client Secret
- 使用
pairing或allowlistDM 策略 - 仅授予必需的 Graph API 权限
- 限制敏感群组和频道的访问
提示
更多详细信息和高级配置,请访问 官方文档。