跳到內容

如何在 Microsoft Teams 中整合 OpenClaw

「進來的人,放棄一切希望吧。」

更新日期:2026-01-21

狀態:支援文字與 DM 附件;頻道或群組檔案發送需要 sharePointSiteId 與 Graph 權限(請參考 Sending files in group chats)。投票是透過 Adaptive Cards 發送。訊息操作提供明確的 upload-file 用於檔案優先的發送方式。

Microsoft Teams 現在是以 plugin 形式提供,不再內建在 core 安裝包裡。

重大變更 (2026.1.15): Microsoft Teams 已移出核心。如果你要使用它,必須安裝 plugin。

理由很簡單:這能讓 core 安裝保持輕量,並讓 Microsoft Teams 的依賴項目可以獨立更新。

透過 CLI 安裝 (npm registry):

Terminal window
openclaw plugins install @openclaw/msteams

本地檢出(從 git repo 執行時):

Terminal window
openclaw plugins install ./path/to/local/msteams-plugin

如果你在設定過程中選擇 Teams 且系統偵測到 git 檢出,OpenClaw 會自動提供本地安裝路徑。

詳細資訊:Plugins

  1. 安裝 Microsoft Teams plugin。
  2. 建立一個 Azure Bot (App ID + client secret + tenant ID)。
  3. 使用這些憑據設定 OpenClaw。
  4. 透過公開 URL 或 tunnel 公開 /api/messages(預設 port 為 3978)。
  5. 安裝 Teams app 套件並啟動 gateway。

最簡設定:

{
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" 來允許任何成員,但仍需透過 mention 觸發)。

  • 透過 Teams 私訊、群組聊天或頻道與 OpenClaw 對話,並確保路由具備確定性:回覆總是會回到訊息來源的頻道。
  • 預設採用安全的頻道行為(除非另有設定,否則必須 mention 機器人)。

預設情況下,Microsoft Teams 允許透過 /config set|unset 觸發設定更新(需要開啟 commands.config: true)。

使用以下方式停用:

{
channels: { msteams: { configWrites: false } },
}

私訊存取

  • 預設值:channels.msteams.dmPolicy = "pairing"。在核准之前,系統會忽略所有未知的傳送者。
  • channels.msteams.allowFrom 應該使用穩定的 AAD object IDs。
  • UPNs 或顯示名稱是會變動的;預設情況下停用直接名稱比對,只有在開啟 channels.msteams.dangerouslyAllowNameMatching: true 時才會啟用。
  • 當權限允許時,設定精靈可以透過 Microsoft Graph 將名稱解析為 ID。

群組存取

  • 預設值: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 下列出團隊和頻道,來限制群組或頻道的內容回覆範圍。
  • Key 應該使用穩定的 team IDs 和頻道 conversation IDs。
  • 當 groupPolicy="allowlist" 且存在團隊白名單時,只有列出的團隊或頻道會被接受(且需透過 @ 提及)。
  • 設定精靈接受 Team/Channel 輸入並會為你儲存這些資訊。
  • 在啟動時,OpenClaw 會將團隊/頻道和使用者白名單中的名稱解析為 ID(在 Graph 權限允許的情況下)並記錄對應關係;未解析的團隊/頻道名稱會按原樣保留,但除非啟用了 channels.msteams.dangerouslyAllowNameMatching: true,否則預設在路由時會被忽略。

範例:

{
channels: {
msteams: {
groupPolicy: "allowlist",
teams: {
"My Team": {
channels: {
General: { requireMention: true },
},
},
},
},
},
}
  1. 安裝 Microsoft Teams plugin。
  2. 建立一個 Azure Bot (包含 App ID + secret + tenant ID)。
  3. 建立一個 Teams app package,引用該 bot 並包含下方的 RSC 權限。
  4. 將 Teams app 上傳或安裝到團隊中(或個人範圍以用於私訊)。
  5. 在 ~/.openclaw/openclaw.json(或透過環境變數)設定 msteams 並啟動 Gateway。
  6. Gateway 預設會在 /api/messages 監聽 Bot Framework 的 webhook 流量。

在設定 OpenClaw 之前,你需要先建立一個 Azure Bot 資源。

  1. 前往 建立 Azure Bot

  2. 填寫 基本 (Basics) 標籤頁:

    欄位數值
    Bot handle你的 bot 名稱,例如 openclaw-msteams (必須唯一)
    Subscription選擇你的 Azure 訂閱
    Resource group建立新的或使用現有的
    Pricing tier開發或測試建議選 Free
    Type of AppSingle Tenant (推薦 - 請見下方說明)
    Creation typeCreate new Microsoft App ID

棄用通知: 2025-07-31 之後已棄用建立新的 multi-tenant bots。新 bot 請使用 Single Tenant。

  1. 點擊 檢閱 + 建立 (Review + create) → 建立 (Create) (等待約 1-2 分鐘)
  1. 前往你的 Azure Bot 資源 → 組態 (Configuration)
  2. 複製 Microsoft App ID → 這就是你的 appId
  3. 點擊 管理密碼 (Manage Password) → 前往應用程式註冊 (App Registration)
  4. 在 憑證與密碼 (Certificates & secrets) → 新用戶端密碼 (New client secret) → 複製 數值 (Value) → 這就是你的 appPassword
  5. 前往 概觀 (Overview) → 複製 目錄 (租戶) ID (Directory (tenant) ID) → 這就是你的 tenantId

步驟 3:設定訊息端點 (Messaging Endpoint)

Section titled “步驟 3:設定訊息端點 (Messaging Endpoint)”
  1. 在 Azure Bot → 組態 (Configuration)
  2. 將 訊息端點 (Messaging endpoint) 設定為你的 webhook URL:
    • 正式環境:https://your-domain.com/api/messages
    • 本地開發:使用隧道工具 (請參考下方的 本地開發)
  1. 在 Azure Bot → 頻道 (Channels)
  2. 點擊 Microsoft Teams → 設定 → 儲存
  3. 同意服務條款

Teams 無法直接連接到 localhost。本地開發時請使用隧道工具:

選項 A:ngrok

Terminal window
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

Terminal window
tailscale funnel 3978
# Use your Tailscale funnel URL as the messaging endpoint

如果你不想手動建立 manifest ZIP 檔,可以使用 Teams Developer Portal:

  1. 點擊 + New app
  2. 填寫基本資訊(名稱、描述、開發者資訊)
  3. 前往 App features → Bot
  4. 選擇 Enter a bot ID manually 並貼上你的 Azure Bot App ID
  5. 勾選權限範圍 (scopes):Personal、Team、Group Chat
  6. 點擊 Distribute → Download app package
  7. 在 Teams 中:Apps → Manage your apps → Upload a custom app → 選擇該 ZIP 檔

這通常比手動編輯 JSON manifest 來得簡單。

選項 A:Azure Web Chat(先驗證 webhook)

  1. 在 Azure Portal → 你的 Azure Bot 資源 → Test in Web Chat
  2. 發送訊息 —— 你應該會看到回覆
  3. 這能在設定 Teams 之前,確認你的 webhook endpoint 運作正常

選項 B:Teams(安裝 App 後)

  1. 安裝 Teams App(側載或透過組織目錄)
  2. 在 Teams 中找到該 Bot 並傳送私訊
  3. 檢查 Gateway 日誌是否有傳入的活動
  1. 安裝 Microsoft Teams 插件

    • 透過 npm:openclaw plugins install @openclaw/msteams
    • 透過本地路徑:openclaw plugins install ./path/to/local/msteams-plugin
  2. Bot 註冊

    • 建立一個 Azure Bot(見上方說明)並記錄:
      • App ID
      • Client secret (App password)
      • Tenant ID (single-tenant)
  3. Teams app manifest

    • 包含一個 bot 項目,且 botId = <App ID>。
    • Scopes:personal、team、groupChat。
    • supportsFiles: true(處理個人範圍的檔案時需要)。
    • 加入 RSC 權限(見下文)。
    • 準備圖示:outline.png (32x32) 與 color.png (192x192)。
    • 將這三個檔案壓縮在一起:manifest.json、outline.png、color.png。
  4. 設定 OpenClaw

    {
    channels: {
    msteams: {
    enabled: true,
    appId: "<APP_ID>",
    appPassword: "<APP_PASSWORD>",
    tenantId: "<TENANT_ID>",
    webhook: { port: 3978, path: "/api/messages" },
    },
    },
    }

    你也可以使用環境變數代替設定檔中的 key:

    • MSTEAMS_APP_ID
    • MSTEAMS_APP_PASSWORD
    • MSTEAMS_TENANT_ID
  5. Bot endpoint

    • 將 Azure Bot 的 Messaging Endpoint 設定為:
      • https://<host>:3978/api/messages(或你自訂的路徑/連接埠)。
  6. 執行 Gateway

    • 當插件安裝完成且 msteams 設定與憑證皆備齊時,Teams 頻道會自動啟動。

OpenClaw 為 Microsoft Teams 提供了基於 Graph 的 member-info 操作,讓 Agent 和自動化流程可以直接從 Microsoft Graph 解析頻道成員的詳細資訊(顯示名稱、電子郵件、角色)。

需求:

  • Member.Read.Group RSC 權限(已包含在建議的 manifest 中)
  • 跨團隊查詢:具備管理員同意的 User.Read.All Graph Application 權限

此操作由 channels.msteams.actions.memberInfo 控制(預設值:當 Graph 憑證可用時啟用)。

  • channels.msteams.historyLimit 控制有多少最近的頻道/群組訊息會被放入 prompt。
  • 如果沒設定,會退回到 messages.groupChat.historyLimit。設定為 0 則停用(預設為 50)。
  • 抓取的討論串歷史會經過發送者白名單(allowFrom / groupAllowFrom)過濾,所以討論串上下文只會包含來自允許發送者的訊息。
  • DM 歷史紀錄可以用 channels.msteams.dmHistoryLimit 限制(使用者輪次)。個別使用者覆蓋設定:channels.msteams.dms["<user_id>"].historyLimit。

這些是我們 Teams app manifest 中現有的 resourceSpecific 權限。它們只適用於安裝了該 app 的團隊或聊天中。

針對頻道(團隊範圍):

  • ChannelMessage.Read.Group (Application) - 無需 @mention 即可接收所有頻道訊息
  • 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) - 無需 @mention 即可接收所有群組聊天訊息

包含必要欄位的精簡、有效範例。記得替換 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" },
],
},
},
}
  • bots[].botId 必須與 Azure Bot App ID 一致。
  • webApplicationInfo.id 必須與 Azure Bot App ID 一致。
  • bots[].scopes 必須包含你打算使用的介面(personal, team, groupChat)。
  • 在 personal 範圍內處理檔案需要設定 bots[].supportsFiles: true。
  • 如果你想要頻道流量,authorization.permissions.resourceSpecific 必須包含頻道的讀取與發送權限。

要更新已安裝的 Teams app(例如:為了加入 RSC 權限):

  1. 更新你的 manifest.json 設定
  2. 增加 version 欄位 (例如:1.0.0 → 1.1.0)
  3. 重新壓縮 manifest 與圖示 (manifest.json, outline.png, color.png)
  4. 上傳新的 zip:
    • 選項 A (Teams 管理中心): Teams 管理中心 → Teams app → 管理 app → 找到你的 app → 上傳新版本
    • 選項 B (側載): 在 Teams 中 → App → 管理你的 app → 上傳自訂 app
  5. 針對團隊頻道: 在每個團隊中重新安裝 app,新權限才會生效
  6. 完全退出並重啟 Teams (而不只是關閉視窗) 來清除快取的 app 中繼資料

僅使用 Teams RSC(已安裝 app,無 Graph API 權限)

Section titled “僅使用 Teams RSC(已安裝 app,無 Graph API 權限)”

可行:

  • 讀取與發送頻道訊息的文字內容。
  • 接收個人 (DM) 檔案附件。

不可行:

  • 頻道或群組的圖片或檔案內容(payload 僅包含 HTML 存根),以及下載儲存在 SharePoint 或 OneDrive 的附件。
  • 讀取訊息歷史紀錄(除了即時的 webhook 事件之外)。

使用 Teams RSC + Microsoft Graph 應用程式權限

Section titled “使用 Teams RSC + Microsoft Graph 應用程式權限”

新增:

  • 下載託管內容(如圖片)以及儲存在 SharePoint 或 OneDrive 的檔案附件。
  • 透過 Graph 讀取頻道或聊天訊息歷史紀錄。
功能RSC 權限Graph API
即時訊息是 (透過 webhook)否 (僅限輪詢)
歷史訊息否是 (可以查詢歷史)
設定複雜度僅需 App manifest需要管理員同意 + token 流程
離線工作否 (必須在執行中)是 (隨時可查詢)

重點: RSC 是用來即時監聽的;Graph API 則是用來存取歷史紀錄。如果你想在離線時補抓錯過的訊息,你需要具備 ChannelMessage.Read.All 權限的 Graph API(這需要管理員同意)。

啟用 Graph 媒體與歷史紀錄(頻道必備)

Section titled “啟用 Graph 媒體與歷史紀錄(頻道必備)”

如果你需要在 channels 中處理圖片/檔案,或是想要獲取 message history,你必須啟用 Microsoft Graph 權限並授予管理員同意。

  1. 在 Entra ID (Azure AD) 的 App Registration 中,新增 Microsoft Graph 的 Application permissions:
    • ChannelMessage.Read.All(頻道附件 + 歷史紀錄)
    • Chat.Read.All 或 ChatMessage.Read.All(群組聊天)
  2. 為租戶 Grant admin consent(授予管理員同意)。
  3. 提升 Teams app 的 manifest version,重新上傳並 在 Teams 中重新安裝 app。
  4. 完全退出並重啟 Teams 以清除快取的 app 中繼資料。

關於使用者提及(User mentions)的額外權限: 對於對話中的使用者,@mentions 功能開箱即用。但如果你想動態搜尋並提及 不在當前對話中 的使用者,請新增 User.Read.All (Application) 權限並授予管理員同意。

Teams 透過 HTTP webhook 傳送訊息。如果處理時間太長(例如 LLM 回應太慢),你可能會遇到:

  • Gateway timeouts
  • Teams 重試傳送訊息(導致重複)
  • 回覆遺失

OpenClaw 的處理方式是快速回傳並主動發送回覆,但回應速度極慢時仍可能發生問題。

Teams 的 markdown 限制比 Slack 或 Discord 更多:

  • 基礎格式沒問題:粗體、斜體、程式碼、連結
  • 複雜的 markdown(表格、巢狀列表)可能無法正常渲染
  • 支援 Adaptive Cards,可用於投票或發送自定義卡片(見下文)

關鍵設定(參考 /gateway/configuration 了解共享頻道模式):

  • channels.msteams.enabled: 啟用/停用頻道。
  • channels.msteams.appId, channels.msteams.appPassword, channels.msteams.tenantId: bot 憑證。
  • channels.msteams.webhook.port (預設 3978)
  • channels.msteams.webhook.path (預設 /api/messages)
  • channels.msteams.dmPolicy: pairing | allowlist | open | disabled (預設: pairing)
  • channels.msteams.allowFrom: DM 白名單(建議使用 AAD object IDs)。在設定過程中,如果 Graph 權限可用,設定精靈會將名稱解析為 ID。
  • channels.msteams.dangerouslyAllowNameMatching: 緊急開關,用於重新啟用可變的 UPN/顯示名稱匹配,以及直接透過團隊/頻道名稱進行路由。
  • channels.msteams.textChunkLimit: 出站文字分段大小。
  • channels.msteams.chunkMode: length (預設) 或 newline(在長度分段前先按空行/段落邊界拆分)。
  • channels.msteams.mediaAllowHosts: 入站附件主機白名單(預設為 Microsoft/Teams 網域)。
  • channels.msteams.mediaAuthAllowHosts: 媒體重試時允許附加 Authorization 標頭的主機白名單(預設為 Graph + Bot Framework 主機)。
  • channels.msteams.requireMention: 在頻道/群組中是否需要 @mention (預設為 true)。
  • channels.msteams.replyStyle: thread | top-level (參考 Reply Style)。
  • 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: 針對特定頻道、特定發送者的工具策略覆寫(支援 "*" 通配符)。
  • toolsBySender 的 key 應使用明確的前綴: id:, e164:, username:, name:(舊版無前綴的 key 仍僅映射至 id:)。
  • channels.msteams.actions.memberInfo: 啟用或停用基於 Graph 的成員資訊 action(預設:當 Graph 憑證可用時啟用)。
  • channels.msteams.sharePointSiteId: 用於群組聊天/頻道中檔案上傳的 SharePoint site ID(參考 Sending files in group chats)。

路由與對話階段 (Routing & Sessions)

Section titled “路由與對話階段 (Routing & Sessions)”
  • Session keys 遵循標準 agent 格式(參考 /concepts/session):
    • 直接訊息(DM)共享主 session (agent:<agentId>:<mainKey>)。
    • 頻道/群組訊息使用對話 ID:
      • agent:<agentId>:msteams:channel:<conversationId>
      • agent:<agentId>:msteams:group:<conversationId>

Teams 最近在相同的資料模型上推出了兩種頻道 UI 樣式:

樣式描述建議的 replyStyle
Posts (傳統)訊息以卡片形式顯示,下方有串連的回覆thread (預設)
Threads (類似 Slack)訊息以線性流動,更像 Slacktop-level

問題在於: Teams API 不會顯示頻道使用的是哪種 UI 樣式。如果你用錯了 replyStyle:

  • 在 Threads 樣式的頻道使用 thread → 回覆會出現尷尬的嵌套
  • 在 Posts 樣式的頻道使用 top-level → 回覆會變成獨立的頂層貼文,而不是在討論串內

解決方案: 根據頻道的設定方式,為每個頻道單獨配置 replyStyle:

{
channels: {
msteams: {
replyStyle: "thread",
teams: {
"19:abc...@thread.tacv2": {
channels: {
"19:xyz...@thread.tacv2": {
replyStyle: "top-level",
},
},
},
},
},
},
}

目前的限制:

  • 私訊 (DMs): 圖片和檔案附件可以透過 Teams bot file APIs 運作。
  • 頻道/群組: 附件儲存在 M365 儲存空間(SharePoint/OneDrive)。Webhook 的資料內容只包含一個 HTML 存根 (stub),而不是實際的檔案位元組。需要 Graph API 權限 才能下載頻道附件。
  • 對於明確的檔案優先傳送,請使用 action=upload-file 搭配 media / filePath / path;選填的 message 會變成隨附的文字/評論,而 filename 則會覆蓋上傳的名稱。

如果沒有 Graph 權限,包含圖片的頻道訊息會以純文字形式接收(機器人無法存取圖片內容)。 預設情況下,OpenClaw 只會從 Microsoft/Teams 的主機名稱下載媒體。你可以透過 channels.msteams.mediaAllowHosts 來覆蓋此設定(使用 ["*"] 允許任何主機)。 授權標頭 (Authorization headers) 只會附加到 channels.msteams.mediaAuthAllowHosts 中的主機(預設為 Graph + Bot Framework 主機)。請保持此清單嚴謹(避免使用多租戶後綴)。

機器人可以在私訊中使用內建的 FileConsentCard 流程傳送檔案。然而,在群組聊天/頻道中傳送檔案 需要額外的設定:

情境檔案如何傳送需要的設定
私訊 (DMs)FileConsentCard → 使用者接受 → 機器人上傳開箱即用
群組聊天/頻道上傳到 SharePoint → 分享連結需要 sharePointSiteId + Graph 權限
圖片 (任何情境)Base64 編碼的內嵌圖片開箱即用

機器人沒有個人的 OneDrive 雲端硬碟(/me/drive 這個 Graph API 端點不適用於應用程式身分)。要在群組聊天/頻道中傳送檔案,機器人會上傳到 SharePoint 網站 並建立分享連結。

  1. 新增 Graph API 權限,在 Entra ID (Azure AD) → 應用程式註冊中:

    • Sites.ReadWrite.All (Application) - 上傳檔案到 SharePoint
    • Chat.Read.All (Application) - 選填,啟用針對個別使用者的分享連結
  2. 為租戶 授予管理員同意。

  3. 取得你的 SharePoint 網站 ID:

    Terminal window
    # 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. 配置 OpenClaw:

    {
    channels: {
    msteams: {
    // ... other config ...
    sharePointSiteId: "contoso.sharepoint.com,guid1,guid2",
    },
    },
    }
權限分享行為
僅 Sites.ReadWrite.All全組織分享連結(組織內的任何人都可以存取)
Sites.ReadWrite.All + Chat.Read.All針對個別使用者的分享連結(只有聊天成員可以存取)

針對個別使用者的分享更安全,因為只有聊天參與者可以存取檔案。如果缺少 Chat.Read.All 權限,機器人會退而求其次使用全組織分享。

情境結果
群組聊天 + 檔案 + 已配置 sharePointSiteId上傳到 SharePoint,傳送分享連結
群組聊天 + 檔案 + 未配置 sharePointSiteId嘗試上傳到 OneDrive(可能會失敗),僅傳送文字
個人聊天 + 檔案FileConsentCard 流程(不需要 SharePoint 即可運作)
任何情境 + 圖片Base64 編碼內嵌(不需要 SharePoint 即可運作)

上傳的檔案會儲存在配置的 SharePoint 網站預設文件庫中的 /OpenClawShared/ 資料夾。

OpenClaw 將 Teams 投票作為 Adaptive Cards 傳送(Teams 沒有原生的投票 API)。

  • CLI: openclaw message poll --channel msteams --target conversation:<id> ...
  • 投票結果由 Gateway 記錄在 ~/.openclaw/msteams-polls.json。
  • Gateway 必須保持在線才能記錄投票。
  • 投票目前還不會自動發佈結果摘要(如果需要,請檢查儲存檔案)。

你可以透過 message 工具或 CLI,將任何 Adaptive Card JSON 傳送給 Teams 使用者或對話。

card 參數接受一個 Adaptive Card JSON 物件。當你提供了 card 時,訊息文字(message text)是選填的。

Agent 工具:

{
action: "send",
channel: "msteams",
target: "user:<id>",
card: {
type: "AdaptiveCard",
version: "1.5",
body: [{ type: "TextBlock", text: "Hello!" }],
},
}

CLI:

Terminal window
openclaw message send --channel msteams \
--target "conversation:19:abc...@thread.tacv2" \
--card '{"type":"AdaptiveCard","version":"1.5","body":[{"type":"TextBlock","text":"Hello!"}]}'

參考 Adaptive Cards documentation 查看卡片結構與範例。關於目標格式的細節,請參考下方的 目標格式。

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 範例:

Terminal window
# Send to a user by ID
openclaw message send --channel msteams --target "user:40a1a0ed-..." --message "Hello"
# Send to a user by display name (triggers Graph API lookup)
openclaw message send --channel msteams --target "user:John Smith" --message "Hello"
# Send to a group chat or channel
openclaw message send --channel msteams --target "conversation:19:abc...@thread.tacv2" --message "Hello"
# Send an Adaptive Card to a conversation
openclaw message send --channel msteams --target "conversation:19:abc...@thread.tacv2" \
--card '{"type":"AdaptiveCard","version":"1.5","body":[{"type":"TextBlock","text":"Hello"}]}'

Agent 工具範例:

{
action: "send",
channel: "msteams",
target: "user:John Smith",
message: "Hello!",
}
{
action: "send",
channel: "msteams",
target: "conversation:19:abc...@thread.tacv2",
card: {
type: "AdaptiveCard",
version: "1.5",
body: [{ type: "TextBlock", text: "Hello" }],
},
}

注意:如果沒有 user: 前綴,名稱預設會被視為群組或團隊。當你透過顯示名稱(display name)指定對象時,請務必使用 user:。

  • 只有在使用者互動之後才能傳送主動訊息,因為我們在那時才會儲存對話引用(conversation references)。
  • 關於 dmPolicy 和白名單過濾的設定,請參考 /gateway/configuration。

Teams URL 裡的 groupId 查詢參數不是設定用的 Team ID。你應該從 URL 路徑中提取 ID:

Team URL:

https://teams.microsoft.com/l/team/19%3ABk4j...%40thread.tacv2/conversations?groupId=...
└────────────────────────────┘
Team ID (URL-decode this)

Channel URL:

https://teams.microsoft.com/l/channel/19%3A15bc...%40thread.tacv2/ChannelName?groupId=...
└─────────────────────────┘
Channel ID (URL-decode this)

設定說明:

  • Team ID = /team/ 後面的路徑片段(需經過 URL-decode,例如 19:Bk4j...@thread.tacv2)
  • Channel ID = /channel/ 後面的路徑片段(需經過 URL-decode)
  • 直接忽略 groupId 查詢參數

Bot 在私人頻道中的支援有限:

功能標準頻道私人頻道
Bot 安裝Yes有限支援
即時訊息 (webhook)Yes可能無法運作
RSC 權限Yes行為可能有所不同
@提及 (@mentions)Yes若 Bot 可被存取則支援
Graph API 歷史紀錄YesYes (需具備權限)

如果私人頻道無法運作,可以嘗試以下替代方案:

  1. 使用標準頻道進行 Bot 互動
  2. 使用 DMs — 使用者隨時可以直接傳送訊息給 Bot
  3. 使用 Graph API 存取歷史紀錄(需要 ChannelMessage.Read.All 權限)
  • 圖片無法在頻道中顯示: 可能是 Graph 權限或 admin consent 缺失。請重新安裝 Teams app 並完全退出後重啟 Teams。
  • 頻道內沒有回應: 預設需要 @提及;請設定 channels.msteams.requireMention=false 或針對特定團隊/頻道進行配置。
  • 版本不符(Teams 仍顯示舊的 manifest): 移除並重新加入 app,並完全退出 Teams 以進行重新整理。
  • 來自 webhook 的 401 Unauthorized: 在沒有 Azure JWT 的情況下進行手動測試時,這是正常現象 — 這代表端點可以連通但驗證失敗。請使用 Azure Web Chat 進行正確測試。
  • 「Icon file cannot be empty」: Manifest 引用了 0 bytes 的圖示檔案。請建立有效的 PNG 圖示(outline.png 為 32x32,color.png 為 192x192)。
  • 「webApplicationInfo.Id already in use」: 該 app 仍安裝在其他團隊或聊天中。請先找到並解除安裝,或等待 5-10 分鐘讓系統同步。
  • 上傳時顯示「Something went wrong」: 改經由 https://admin.teams.microsoft.com 上傳,開啟瀏覽器開發者工具 (F12) → Network 標籤,並檢查回應內容 (response body) 中的實際錯誤訊息。
  • 側載 (Sideload) 失敗: 嘗試「上傳 app 到你的組織 app 目錄」而不是「上傳自訂 app」— 這通常能繞過側載限制。
  1. 檢查 webApplicationInfo.id 是否與你的 bot App ID 完全一致
  2. 重新上傳 app 並在團隊/聊天中重新安裝
  3. 檢查你的組織管理員是否封鎖了 RSC 權限
  4. 確認你使用了正確的 scope:團隊使用 ChannelMessage.Read.Group,群組聊天使用 ChatMessage.Read.Chat
OpenClaw

OpenClaw Expert

還是卡住了?

如果這篇文件沒有解決你的情境,直接問 OpenClaw Expert,拿到可執行步驟。