8.11 Microsoft Teams

通过 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

  1. 访问 Azure Portal
  2. 搜索 "Azure Bot" 并创建新资源
  3. 选择 "Single Tenant"(单租户)类型
  4. 记录以下信息:
    • App ID(应用程序 ID)
    • Tenant ID(租户 ID)

2. 创建客户端密钥

  1. 在 Azure Portal 中进入 "App registrations"
  2. 找到刚创建的应用
  3. 进入 "Certificates & secrets"
  4. 创建新的 Client Secret
  5. 记录 Secret Value(密钥值,这是 App Password)
重要
Client Secret 值只在创建时显示一次,请立即保存。

3. 配置 Messaging Endpoint

  1. 在 Azure Bot 资源的 "Configuration" 中
  2. 设置 Messaging endpoint:https://your-domain.com/msteams/messages
  3. 保存配置

4. 添加 Teams 频道

  1. 在 Azure Bot 的 "Channels" 设置中
  2. 添加 "Microsoft Teams" 频道
  3. 完成授权

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

  1. 准备图标文件:color.png(192x192)和 outline.png(32x32)
  2. manifest.json 和图标文件打包成 ZIP
  3. 在 Teams 中点击 "Apps" → "Manage your apps" → "Upload an app"
  4. 选择 "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 权限

  1. 在 Azure Portal 的 App registration 中
  2. 进入 "API permissions"
  3. 添加 "Microsoft Graph" 权限:Sites.ReadWrite.All
  4. 点击 "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.AllFiles.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
  • 使用 pairingallowlist DM 策略
  • 仅授予必需的 Graph API 权限
  • 限制敏感群组和频道的访问
提示
更多详细信息和高级配置,请访问 官方文档