如何在 Microsoft Teams 中整合 OpenClaw
Microsoft Teams (plugin)
Section titled “Microsoft Teams (plugin)”「進來的人,放棄一切希望吧。」
更新日期:2026-01-21
狀態:支援文字與 DM 附件;頻道或群組檔案發送需要 sharePointSiteId 與 Graph 權限(請參考 Sending files in group chats)。投票是透過 Adaptive Cards 發送。訊息操作提供明確的 upload-file 用於檔案優先的發送方式。
必須安裝 Plugin
Section titled “必須安裝 Plugin”Microsoft Teams 現在是以 plugin 形式提供,不再內建在 core 安裝包裡。
重大變更 (2026.1.15): Microsoft Teams 已移出核心。如果你要使用它,必須安裝 plugin。
理由很簡單:這能讓 core 安裝保持輕量,並讓 Microsoft Teams 的依賴項目可以獨立更新。
透過 CLI 安裝 (npm registry):
openclaw plugins install @openclaw/msteams本地檢出(從 git repo 執行時):
openclaw plugins install ./path/to/local/msteams-plugin如果你在設定過程中選擇 Teams 且系統偵測到 git 檢出,OpenClaw 會自動提供本地安裝路徑。
詳細資訊:Plugins
快速設定(初學者)
Section titled “快速設定(初學者)”- 安裝 Microsoft Teams plugin。
- 建立一個 Azure Bot (App ID + client secret + tenant ID)。
- 使用這些憑據設定 OpenClaw。
- 透過公開 URL 或 tunnel 公開
/api/messages(預設 port 為 3978)。 - 安裝 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 } },}存取控制 (私訊 + 群組)
Section titled “存取控制 (私訊 + 群組)”私訊存取
- 預設值:
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 }, }, }, }, }, },}- 安裝 Microsoft Teams plugin。
- 建立一個 Azure Bot (包含 App ID + secret + tenant ID)。
- 建立一個 Teams app package,引用該 bot 並包含下方的 RSC 權限。
- 將 Teams app 上傳或安裝到團隊中(或個人範圍以用於私訊)。
- 在
~/.openclaw/openclaw.json(或透過環境變數)設定msteams並啟動 Gateway。 - Gateway 預設會在
/api/messages監聽 Bot Framework 的 webhook 流量。
Azure Bot 設定 (先決條件)
Section titled “Azure Bot 設定 (先決條件)”在設定 OpenClaw 之前,你需要先建立一個 Azure Bot 資源。
步驟 1:建立 Azure Bot
Section titled “步驟 1:建立 Azure Bot”-
前往 建立 Azure Bot
-
填寫 基本 (Basics) 標籤頁:
欄位 數值 Bot handle 你的 bot 名稱,例如 openclaw-msteams(必須唯一)Subscription 選擇你的 Azure 訂閱 Resource group 建立新的或使用現有的 Pricing tier 開發或測試建議選 Free Type of App Single Tenant (推薦 - 請見下方說明) Creation type Create new Microsoft App ID
棄用通知: 2025-07-31 之後已棄用建立新的 multi-tenant bots。新 bot 請使用 Single Tenant。
- 點擊 檢閱 + 建立 (Review + create) → 建立 (Create) (等待約 1-2 分鐘)
步驟 2:取得憑證
Section titled “步驟 2:取得憑證”- 前往你的 Azure Bot 資源 → 組態 (Configuration)
- 複製 Microsoft App ID → 這就是你的
appId - 點擊 管理密碼 (Manage Password) → 前往應用程式註冊 (App Registration)
- 在 憑證與密碼 (Certificates & secrets) → 新用戶端密碼 (New client secret) → 複製 數值 (Value) → 這就是你的
appPassword - 前往 概觀 (Overview) → 複製 目錄 (租戶) ID (Directory (tenant) ID) → 這就是你的
tenantId
步驟 3:設定訊息端點 (Messaging Endpoint)
Section titled “步驟 3:設定訊息端點 (Messaging Endpoint)”- 在 Azure Bot → 組態 (Configuration)
- 將 訊息端點 (Messaging endpoint) 設定為你的 webhook URL:
- 正式環境:
https://your-domain.com/api/messages - 本地開發:使用隧道工具 (請參考下方的 本地開發)
- 正式環境:
步驟 4:啟用 Teams 頻道
Section titled “步驟 4:啟用 Teams 頻道”- 在 Azure Bot → 頻道 (Channels)
- 點擊 Microsoft Teams → 設定 → 儲存
- 同意服務條款
本地開發 (隧道技術)
Section titled “本地開發 (隧道技術)”Teams 無法直接連接到 localhost。本地開發時請使用隧道工具:
選項 A:ngrok
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
tailscale funnel 3978# Use your Tailscale funnel URL as the messaging endpointTeams Developer Portal (替代方案)
Section titled “Teams Developer Portal (替代方案)”如果你不想手動建立 manifest ZIP 檔,可以使用 Teams Developer Portal:
- 點擊 + New app
- 填寫基本資訊(名稱、描述、開發者資訊)
- 前往 App features → Bot
- 選擇 Enter a bot ID manually 並貼上你的 Azure Bot App ID
- 勾選權限範圍 (scopes):Personal、Team、Group Chat
- 點擊 Distribute → Download app package
- 在 Teams 中:Apps → Manage your apps → Upload a custom app → 選擇該 ZIP 檔
這通常比手動編輯 JSON manifest 來得簡單。
測試 Bot
Section titled “測試 Bot”選項 A:Azure Web Chat(先驗證 webhook)
- 在 Azure Portal → 你的 Azure Bot 資源 → Test in Web Chat
- 發送訊息 —— 你應該會看到回覆
- 這能在設定 Teams 之前,確認你的 webhook endpoint 運作正常
選項 B:Teams(安裝 App 後)
- 安裝 Teams App(側載或透過組織目錄)
- 在 Teams 中找到該 Bot 並傳送私訊
- 檢查 Gateway 日誌是否有傳入的活動
設定 (純文字簡介)
Section titled “設定 (純文字簡介)”-
安裝 Microsoft Teams 插件
- 透過 npm:
openclaw plugins install @openclaw/msteams - 透過本地路徑:
openclaw plugins install ./path/to/local/msteams-plugin
- 透過 npm:
-
Bot 註冊
- 建立一個 Azure Bot(見上方說明)並記錄:
- App ID
- Client secret (App password)
- Tenant ID (single-tenant)
- 建立一個 Azure Bot(見上方說明)並記錄:
-
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。
- 包含一個
-
設定 OpenClaw
{channels: {msteams: {enabled: true,appId: "<APP_ID>",appPassword: "<APP_PASSWORD>",tenantId: "<TENANT_ID>",webhook: { port: 3978, path: "/api/messages" },},},}你也可以使用環境變數代替設定檔中的 key:
MSTEAMS_APP_IDMSTEAMS_APP_PASSWORDMSTEAMS_TENANT_ID
-
Bot endpoint
- 將 Azure Bot 的 Messaging Endpoint 設定為:
https://<host>:3978/api/messages(或你自訂的路徑/連接埠)。
- 將 Azure Bot 的 Messaging Endpoint 設定為:
-
執行 Gateway
- 當插件安裝完成且
msteams設定與憑證皆備齊時,Teams 頻道會自動啟動。
- 當插件安裝完成且
Member info 操作
Section titled “Member info 操作”OpenClaw 為 Microsoft Teams 提供了基於 Graph 的 member-info 操作,讓 Agent 和自動化流程可以直接從 Microsoft Graph 解析頻道成員的詳細資訊(顯示名稱、電子郵件、角色)。
需求:
Member.Read.GroupRSC 權限(已包含在建議的 manifest 中)- 跨團隊查詢:具備管理員同意的
User.Read.AllGraph 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 RSC 權限 (Manifest)
Section titled “目前的 Teams RSC 權限 (Manifest)”這些是我們 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 即可接收所有群組聊天訊息
Teams Manifest 範例(已簡化)
Section titled “Teams Manifest 範例(已簡化)”包含必要欄位的精簡、有效範例。記得替換 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" }, ], }, },}Manifest 注意事項(必填欄位)
Section titled “Manifest 注意事項(必填欄位)”bots[].botId必須與 Azure Bot App ID 一致。webApplicationInfo.id必須與 Azure Bot App ID 一致。bots[].scopes必須包含你打算使用的介面(personal,team,groupChat)。- 在 personal 範圍內處理檔案需要設定
bots[].supportsFiles: true。 - 如果你想要頻道流量,
authorization.permissions.resourceSpecific必須包含頻道的讀取與發送權限。
更新現有的 app
Section titled “更新現有的 app”要更新已安裝的 Teams app(例如:為了加入 RSC 權限):
- 更新你的
manifest.json設定 - 增加
version欄位 (例如:1.0.0→1.1.0) - 重新壓縮 manifest 與圖示 (
manifest.json,outline.png,color.png) - 上傳新的 zip:
- 選項 A (Teams 管理中心): Teams 管理中心 → Teams app → 管理 app → 找到你的 app → 上傳新版本
- 選項 B (側載): 在 Teams 中 → App → 管理你的 app → 上傳自訂 app
- 針對團隊頻道: 在每個團隊中重新安裝 app,新權限才會生效
- 完全退出並重啟 Teams (而不只是關閉視窗) 來清除快取的 app 中繼資料
功能比較:僅限 RSC vs Graph
Section titled “功能比較:僅限 RSC vs Graph”僅使用 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 vs Graph API
Section titled “RSC vs Graph API”| 功能 | RSC 權限 | Graph API |
|---|---|---|
| 即時訊息 | 是 (透過 webhook) | 否 (僅限輪詢) |
| 歷史訊息 | 否 | 是 (可以查詢歷史) |
| 設定複雜度 | 僅需 App manifest | 需要管理員同意 + token 流程 |
| 離線工作 | 否 (必須在執行中) | 是 (隨時可查詢) |
重點: RSC 是用來即時監聽的;Graph API 則是用來存取歷史紀錄。如果你想在離線時補抓錯過的訊息,你需要具備 ChannelMessage.Read.All 權限的 Graph API(這需要管理員同意)。
啟用 Graph 媒體與歷史紀錄(頻道必備)
Section titled “啟用 Graph 媒體與歷史紀錄(頻道必備)”如果你需要在 channels 中處理圖片/檔案,或是想要獲取 message history,你必須啟用 Microsoft Graph 權限並授予管理員同意。
- 在 Entra ID (Azure AD) 的 App Registration 中,新增 Microsoft Graph 的 Application permissions:
ChannelMessage.Read.All(頻道附件 + 歷史紀錄)Chat.Read.All或ChatMessage.Read.All(群組聊天)
- 為租戶 Grant admin consent(授予管理員同意)。
- 提升 Teams app 的 manifest version,重新上傳並 在 Teams 中重新安裝 app。
- 完全退出並重啟 Teams 以清除快取的 app 中繼資料。
關於使用者提及(User mentions)的額外權限: 對於對話中的使用者,@mentions 功能開箱即用。但如果你想動態搜尋並提及 不在當前對話中 的使用者,請新增 User.Read.All (Application) 權限並授予管理員同意。
Webhook 超時
Section titled “Webhook 超時”Teams 透過 HTTP webhook 傳送訊息。如果處理時間太長(例如 LLM 回應太慢),你可能會遇到:
- Gateway timeouts
- Teams 重試傳送訊息(導致重複)
- 回覆遺失
OpenClaw 的處理方式是快速回傳並主動發送回覆,但回應速度極慢時仍可能發生問題。
Teams 的 markdown 限制比 Slack 或 Discord 更多:
- 基礎格式沒問題:粗體、斜體、
程式碼、連結 - 複雜的 markdown(表格、巢狀列表)可能無法正常渲染
- 支援 Adaptive Cards,可用於投票或發送自定義卡片(見下文)
配置 (Configuration)
Section titled “配置 (Configuration)”關鍵設定(參考 /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>
- 直接訊息(DM)共享主 session (
回覆樣式:Threads vs Posts
Section titled “回覆樣式:Threads vs Posts”Teams 最近在相同的資料模型上推出了兩種頻道 UI 樣式:
| 樣式 | 描述 | 建議的 replyStyle |
|---|---|---|
| Posts (傳統) | 訊息以卡片形式顯示,下方有串連的回覆 | thread (預設) |
| Threads (類似 Slack) | 訊息以線性流動,更像 Slack | top-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 主機)。請保持此清單嚴謹(避免使用多租戶後綴)。
在群組聊天中傳送檔案
Section titled “在群組聊天中傳送檔案”機器人可以在私訊中使用內建的 FileConsentCard 流程傳送檔案。然而,在群組聊天/頻道中傳送檔案 需要額外的設定:
| 情境 | 檔案如何傳送 | 需要的設定 |
|---|---|---|
| 私訊 (DMs) | FileConsentCard → 使用者接受 → 機器人上傳 | 開箱即用 |
| 群組聊天/頻道 | 上傳到 SharePoint → 分享連結 | 需要 sharePointSiteId + Graph 權限 |
| 圖片 (任何情境) | Base64 編碼的內嵌圖片 | 開箱即用 |
為什麼群組聊天需要 SharePoint
Section titled “為什麼群組聊天需要 SharePoint”機器人沒有個人的 OneDrive 雲端硬碟(/me/drive 這個 Graph API 端點不適用於應用程式身分)。要在群組聊天/頻道中傳送檔案,機器人會上傳到 SharePoint 網站 並建立分享連結。
-
新增 Graph API 權限,在 Entra ID (Azure AD) → 應用程式註冊中:
Sites.ReadWrite.All(Application) - 上傳檔案到 SharePointChat.Read.All(Application) - 選填,啟用針對個別使用者的分享連結
-
為租戶 授予管理員同意。
-
取得你的 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" -
配置 OpenClaw:
{channels: {msteams: {// ... other config ...sharePointSiteId: "contoso.sharepoint.com,guid1,guid2",},},}
| 權限 | 分享行為 |
|---|---|
僅 Sites.ReadWrite.All | 全組織分享連結(組織內的任何人都可以存取) |
Sites.ReadWrite.All + Chat.Read.All | 針對個別使用者的分享連結(只有聊天成員可以存取) |
針對個別使用者的分享更安全,因為只有聊天參與者可以存取檔案。如果缺少 Chat.Read.All 權限,機器人會退而求其次使用全組織分享。
回退行為 (Fallback behavior)
Section titled “回退行為 (Fallback behavior)”| 情境 | 結果 |
|---|---|
群組聊天 + 檔案 + 已配置 sharePointSiteId | 上傳到 SharePoint,傳送分享連結 |
群組聊天 + 檔案 + 未配置 sharePointSiteId | 嘗試上傳到 OneDrive(可能會失敗),僅傳送文字 |
| 個人聊天 + 檔案 | FileConsentCard 流程(不需要 SharePoint 即可運作) |
| 任何情境 + 圖片 | Base64 編碼內嵌(不需要 SharePoint 即可運作) |
檔案儲存位置
Section titled “檔案儲存位置”上傳的檔案會儲存在配置的 SharePoint 網站預設文件庫中的 /OpenClawShared/ 資料夾。
投票(Adaptive Cards)
Section titled “投票(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 (自定義)
Section titled “Adaptive Cards (自定義)”你可以透過 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:
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 範例:
# Send to a user by IDopenclaw 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 channelopenclaw message send --channel msteams --target "conversation:19:abc...@thread.tacv2" --message "Hello"
# Send an Adaptive Card to a conversationopenclaw 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:。
主動傳送訊息
Section titled “主動傳送訊息”- 只有在使用者互動之後才能傳送主動訊息,因為我們在那時才會儲存對話引用(conversation references)。
- 關於
dmPolicy和白名單過濾的設定,請參考/gateway/configuration。
Team 和 Channel ID(常見地雷)
Section titled “Team 和 Channel ID(常見地雷)”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 歷史紀錄 | Yes | Yes (需具備權限) |
如果私人頻道無法運作,可以嘗試以下替代方案:
- 使用標準頻道進行 Bot 互動
- 使用 DMs — 使用者隨時可以直接傳送訊息給 Bot
- 使用 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 進行正確測試。
Manifest 上傳錯誤
Section titled “Manifest 上傳錯誤”- 「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」— 這通常能繞過側載限制。
RSC 權限失效
Section titled “RSC 權限失效”- 檢查
webApplicationInfo.id是否與你的 bot App ID 完全一致 - 重新上傳 app 並在團隊/聊天中重新安裝
- 檢查你的組織管理員是否封鎖了 RSC 權限
- 確認你使用了正確的 scope:團隊使用
ChannelMessage.Read.Group,群組聊天使用ChatMessage.Read.Chat
- 建立 Azure Bot - Azure Bot 設定指南
- Teams 開發者入口網站 - 建立與管理 Teams app
- Teams app manifest 結構定義
- 透過 RSC 接收頻道訊息
- RSC 權限參考
- Teams bot 檔案處理 (頻道或群組需要使用 Graph)
- 主動傳送訊息
OpenClaw Expert
還是卡住了?
如果這篇文件沒有解決你的情境,直接問 OpenClaw Expert,拿到可執行步驟。