Microsoft Teams(プラグイン)
“Abandon all hope, ye who enter here.”
更新日:2026-01-21
ステータス:テキスト + DM添付ファイルに対応。チャンネル/グループのファイル送信には sharePointSiteId + Graph権限が必要です(グループチャットでのファイル送信を参照)。投票はAdaptive Cardsで送信されます。
プラグインが必要です
Microsoft Teamsはプラグインとして提供されており、コアインストールにはバンドルされていません。
破壊的変更(2026.1.15): MS Teamsがコアから分離されました。使用する場合はプラグインのインストールが必要です。
理由:コアインストールを軽量に保ち、MS Teamsの依存関係を独立して更新できるようにするためです。
CLI経由でインストール(npmレジストリ):
openclaw plugins install @openclaw/msteams
ローカルチェックアウト(gitリポジトリから実行する場合):
openclaw plugins install ./extensions/msteams
設定/オンボーディング中にTeamsを選択し、gitチェックアウトが検出された場合、OpenClawはローカルインストールパスを自動的に提示します。
詳細:プラグイン
クイックセットアップ(初心者向け)
- Microsoft Teamsプラグインをインストールします。
- Azure Bot を作成します(App ID + クライアントシークレット + テナントID)。
- それらの認証情報でOpenClawを設定します。
/api/messages(デフォルトポート3978)をパブリックURLまたはトンネル経由で公開します。- Teamsアプリパッケージをインストールし、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" で任意のメンバーを許可、メンションゲート付き)。
目標
- Teams DM、グループチャット、またはチャンネル経由でOpenClawと会話できるようにします。
- ルーティングを決定的に保ちます:返信は常に着信と同じチャンネルに戻ります。
- デフォルトで安全なチャンネル動作にします(別途設定しない限り、メンションが必要)。
設定の書き込み
デフォルトで、Microsoft Teamsは /config set|unset でトリガーされる設定更新の書き込みが許可されています(commands.config: true が必要)。
無効化:
{
channels: { msteams: { configWrites: false } },
}
アクセス制御(DM + グループ)
DMアクセス
- デフォルト:
channels.msteams.dmPolicy = "pairing"。不明な送信者は承認されるまで無視されます。 channels.msteams.allowFromには安定したAADオブジェクトIDを使用してください。- UPN/表示名は変更可能です。直接マッチングはデフォルトで無効であり、
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: ["[email protected]"],
},
},
}
チーム + チャンネル許可リスト
channels.msteams.teamsでチームとチャンネルをリストして、グループ/チャンネル返信のスコープを設定します。- キーには安定したチームIDとチャンネル会話IDを使用してください。
groupPolicy="allowlist"でチーム許可リストが存在する場合、リストされたチーム/チャンネルのみ受け付けます(メンションゲート付き)。- 設定ウィザードは
チーム/チャンネルエントリを受け付けて保存します。 - 起動時、OpenClawはチーム/チャンネルとユーザー許可リストの名前をIDに解決し(Graph権限がある場合)、マッピングをログに記録します。解決されなかったチーム/チャンネル名はそのまま保持されますが、
channels.msteams.dangerouslyAllowNameMatching: trueが有効でない限り、ルーティングでは無視されます。
例:
{
channels: {
msteams: {
groupPolicy: "allowlist",
teams: {
"My Team": {
channels: {
General: { requireMention: true },
},
},
},
},
},
}
仕組み
- Microsoft Teamsプラグインをインストールします。
- Azure Bot を作成します(App ID + シークレット + テナントID)。
- Botを参照し、以下のRSC権限を含む Teamsアプリパッケージ を作成します。
- Teamsアプリをチーム(またはDM用のパーソナルスコープ)にアップロード/インストールします。
~/.openclaw/openclaw.json(または環境変数)でmsteamsを設定し、Gatewayを起動します。- Gatewayはデフォルトで
/api/messagesでBot Framework Webhookトラフィックをリッスンします。
Azure Botセットアップ(前提条件)
OpenClawを設定する前に、Azure Botリソースを作成する必要があります。
ステップ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
注意: 新しいマルチテナントBotの作成は2025-07-31以降に非推奨となりました。新規Botには Single Tenant を使用してください。
- Review + create → Create をクリック(1-2分程度待ちます)
ステップ2:認証情報の取得
- Azure Botリソース → Configuration に移動します
- Microsoft App ID をコピー → これが
appIdです - Manage Password をクリック → App Registrationに移動します
- Certificates & secrets → New client secret → Value をコピー → これが
appPasswordです - Overview → Directory (tenant) ID をコピー → これが
tenantIdです
ステップ3:メッセージングエンドポイントの設定
- Azure Bot → Configuration に移動します
- Messaging endpoint にWebhook URLを設定します:
- 本番環境:
https://your-domain.com/api/messages - ローカル開発:トンネルを使用(以下のローカル開発を参照)
- 本番環境:
ステップ4:Teamsチャンネルの有効化
- Azure Bot → Channels に移動します
- Microsoft Teams → Configure → Save をクリックします
- 利用規約に同意します
ローカル開発(トンネリング)
Teamsはlocalhostに到達できません。ローカル開発にはトンネルを使用してください:
オプションA:ngrok
ngrok http 3978
# httpsのURLをコピー(例:https://abc123.ngrok.io)
# メッセージングエンドポイントを https://abc123.ngrok.io/api/messages に設定
オプションB:Tailscale Funnel
tailscale funnel 3978
# Tailscale FunnelのURLをメッセージングエンドポイントとして使用
Teams Developer Portal(代替手段)
マニフェストZIPを手動で作成する代わりに、Teams Developer Portalを使用できます:
- + New app をクリック
- 基本情報を入力(名前、説明、開発者情報)
- App features → Bot に移動
- Enter a bot ID manually を選択し、Azure Bot App IDを貼り付け
- スコープを確認:Personal、Team、Group Chat
- Distribute → Download app package をクリック
- Teamsで:Apps → Manage your apps → Upload a custom app → ZIPを選択
JSONマニフェストを手動編集するよりも簡単な場合が多いです。
Botのテスト
オプションA:Azure Web Chat(まずWebhookを検証)
- Azure Portal → Azure Botリソース → Test in Web Chat
- メッセージを送信 - 応答が表示されるはずです
- これでTeamsセットアップ前にWebhookエンドポイントの動作を確認できます
オプションB:Teams(アプリインストール後)
- Teamsアプリをインストール(サイドロードまたは組織カタログ)
- TeamsでBotを見つけてDMを送信
- Gatewayログで着信アクティビティを確認
セットアップ(最小テキストのみ)
-
Microsoft Teamsプラグインのインストール
- npmから:
openclaw plugins install @openclaw/msteams - ローカルチェックアウトから:
openclaw plugins install ./extensions/msteams
- npmから:
-
Bot登録
- Azure Botを作成し(上記参照)、以下を記録:
- App ID
- クライアントシークレット(Appパスワード)
- テナントID(シングルテナント)
- Azure Botを作成し(上記参照)、以下を記録:
-
Teamsアプリマニフェスト
botId = <App ID>のbotエントリを含めます。- スコープ:
personal、team、groupChat supportsFiles: true(パーソナルスコープのファイル処理に必要)- RSC権限を追加(以下参照)
- アイコンを作成:
outline.png(32x32)とcolor.png(192x192) - 3ファイルをZIPにまとめます:
manifest.json、outline.png、color.png
-
OpenClawの設定
{ "msteams": { "enabled": true, "appId": "<APP_ID>", "appPassword": "<APP_PASSWORD>", "tenantId": "<TENANT_ID>", "webhook": { "port": 3978, "path": "/api/messages" } } }設定キーの代わりに環境変数も使用できます:
MSTEAMS_APP_IDMSTEAMS_APP_PASSWORDMSTEAMS_TENANT_ID
-
Botエンドポイント
- Azure Botのメッセージングエンドポイントを以下に設定:
https://<host>:3978/api/messages(または選択したパス/ポート)
- Azure Botのメッセージングエンドポイントを以下に設定:
-
Gatewayの起動
- プラグインがインストール済みで、認証情報付きの
msteams設定が存在する場合、Teamsチャンネルは自動的に起動します。
- プラグインがインストール済みで、認証情報付きの
履歴コンテキスト
channels.msteams.historyLimitはプロンプトに含まれる最近のチャンネル/グループメッセージ数を制御します。messages.groupChat.historyLimitにフォールバックします。0で無効化(デフォルト50)。- DM履歴は
channels.msteams.dmHistoryLimit(ユーザーターン)で制限できます。ユーザーごとのオーバーライド:channels.msteams.dms["<user_id>"].historyLimit。
現在のTeams RSC権限(マニフェスト)
以下はTeamsアプリマニフェストの既存のresourceSpecific権限です。これらはアプリがインストールされたチーム/チャット内でのみ適用されます。
チャンネル用(チームスコープ):
ChannelMessage.Read.Group(Application)- @メンションなしで全チャンネルメッセージを受信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)- @メンションなしで全グループチャットメッセージを受信
Teamsマニフェストの例(抜粋)
必須フィールドを含む最小限の有効な例です。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)を含める必要があります。bots[].supportsFiles: trueはパーソナルスコープのファイル処理に必要です。authorization.permissions.resourceSpecificにチャンネルトラフィックが必要な場合はチャンネル読み取り/送信を含める必要があります。
既存アプリの更新
既にインストール済みのTeamsアプリを更新するには(例:RSC権限の追加):
- 新しい設定で
manifest.jsonを更新します versionフィールドをインクリメントします(例:1.0.0→1.1.0)- マニフェストとアイコンを再ZIPします(
manifest.json、outline.png、color.png) - 新しいZIPをアップロードします:
- オプションA(Teams管理センター): Teams管理センター → Teamsアプリ → アプリの管理 → アプリを検索 → 新バージョンをアップロード
- オプションB(サイドロード): Teamsで → Apps → Manage your apps → Upload a custom app
- チームチャンネルの場合: 新しい権限を有効にするため、各チームでアプリを再インストールします
- Teamsを完全に終了して再起動します(ウィンドウを閉じるだけでなく)。キャッシュされたアプリメタデータをクリアするためです
機能:RSCのみ vs Graph
Teams RSCのみ(アプリインストール済み、Graph API権限なし)
動作するもの:
- チャンネルメッセージのテキストコンテンツの読み取り
- チャンネルメッセージのテキストコンテンツの送信
- **パーソナル(DM)**ファイル添付の受信
動作しないもの:
- チャンネル/グループの画像またはファイルコンテンツ(ペイロードにはHTMLスタブのみ含まれます)
- SharePoint/OneDriveに保存された添付ファイルのダウンロード
- メッセージ履歴の読み取り(ライブWebhookイベントを超えて)
Teams RSC + Microsoft Graphアプリケーション権限
追加機能:
- ホステッドコンテンツのダウンロード(メッセージに貼り付けた画像)
- SharePoint/OneDriveに保存されたファイル添付のダウンロード
- Graph経由でのチャンネル/チャットメッセージ履歴の読み取り
RSC vs Graph API
| 機能 | RSC権限 | Graph API |
|---|---|---|
| リアルタイムメッセージ | あり(Webhook経由) | なし(ポーリングのみ) |
| メッセージ履歴 | なし | あり(履歴をクエリ可能) |
| セットアップの複雑さ | アプリマニフェストのみ | 管理者同意 + トークンフローが必要 |
| オフライン動作 | なし(稼働中である必要あり) | あり(いつでもクエリ可能) |
結論: RSCはリアルタイムリッスン用、Graph APIは履歴アクセス用です。オフライン中の見逃したメッセージのキャッチアップには、ChannelMessage.Read.All を持つGraph API(管理者同意が必要)が必要です。
Graph対応のメディア + 履歴(チャンネルに必要)
チャンネルで画像/ファイルが必要な場合、またはメッセージ履歴を取得したい場合は、Microsoft Graph権限を有効にして管理者同意を付与する必要があります。
- Entra ID(Azure AD)のApp Registrationで、Microsoft Graphのアプリケーション権限を追加します:
ChannelMessage.Read.All(チャンネル添付 + 履歴)Chat.Read.AllまたはChatMessage.Read.All(グループチャット)
- テナントの管理者同意を付与します。
- Teamsアプリのマニフェストバージョンをバンプし、再アップロードして、Teamsでアプリを再インストールします。
- Teamsを完全に終了して再起動し、キャッシュされたアプリメタデータをクリアします。
ユーザーメンションの追加権限: ユーザー@メンションは会話内のユーザーに対してはそのまま動作します。ただし、現在の会話にいないユーザーを動的に検索してメンションする場合は、User.Read.All(Application)権限を追加して管理者同意を付与してください。
既知の制限事項
Webhookタイムアウト
TeamsはHTTP Webhook経由でメッセージを配信します。処理に時間がかかりすぎる場合(例:LLMの応答が遅い)、以下が発生する可能性があります:
- Gatewayタイムアウト
- 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オブジェクトID推奨)。ウィザードは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:チャンネル/グループでの@メンション必須(デフォルトtrue)channels.msteams.replyStyle:thread | top-level(返信スタイルを参照)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キーには明示的なプレフィックスを使用してください:id:、e164:、username:、name:(レガシーのプレフィックスなしキーはid:のみにマッピングされます)channels.msteams.sharePointSiteId:グループチャット/チャンネルでのファイルアップロード用SharePointサイトID(グループチャットでのファイル送信を参照)
ルーティングとセッション
- セッションキーは標準的なエージェント形式に従います(/concepts/session を参照):
- ダイレクトメッセージはメインセッションを共有します(
agent:<agentId>:<mainKey>) - チャンネル/グループメッセージは会話IDを使用します:
agent:<agentId>:msteams:channel:<conversationId>agent:<agentId>:msteams:group:<conversationId>
- ダイレクトメッセージはメインセッションを共有します(
返信スタイル:スレッド vs 投稿
Teamsは最近、同じ基盤データモデル上に2つのチャンネルUIスタイルを導入しました:
| スタイル | 説明 | 推奨 replyStyle |
|---|---|---|
| Posts(クラシック) | メッセージがカードとして表示され、その下にスレッド返信 | thread(デフォルト) |
| Threads(Slack風) | メッセージがSlackのように直線的に流れる | top-level |
問題点: Teams APIはチャンネルがどのUIスタイルを使用しているかを公開しません。間違った replyStyle を使用すると:
- Threadsスタイルのチャンネルで
thread→ 返信がぎこちなくネストされて表示 - Postsスタイルのチャンネルで
top-level→ 返信がスレッド内ではなく別のトップレベル投稿として表示
解決策: チャンネルの設定に基づいて replyStyle をチャンネルごとに設定します:
{
"msteams": {
"replyStyle": "thread",
"teams": {
"19:[email protected]": {
"channels": {
"19:[email protected]": {
"replyStyle": "top-level"
}
}
}
}
}
}
添付ファイルと画像
現在の制限事項:
- DM: Teams Bot ファイルAPI経由で画像とファイル添付が動作します。
- チャンネル/グループ: 添付ファイルはM365ストレージ(SharePoint/OneDrive)に存在します。WebhookペイロードにはHTMLスタブのみが含まれ、実際のファイルバイトは含まれません。チャンネル添付のダウンロードにはGraph API権限が必要です。
Graph権限がない場合、画像を含むチャンネルメッセージはテキストのみとして受信されます(画像コンテンツにBotからアクセスできません)。
デフォルトでは、OpenClawはMicrosoft/Teamsホスト名からのみメディアをダウンロードします。channels.msteams.mediaAllowHosts でオーバーライドしてください(["*"] で任意のホストを許可)。
Authorizationヘッダーは channels.msteams.mediaAuthAllowHosts 内のホストにのみ添付されます(デフォルトはGraph + Bot Frameworkホスト)。このリストは厳格に保ってください(マルチテナントサフィックスを避けてください)。
グループチャットでのファイル送信
BotはDMではFileConsentCardフロー(組み込み)でファイルを送信できます。ただし、グループチャット/チャンネルでのファイル送信には追加のセットアップが必要です:
| コンテキスト | ファイル送信方法 | 必要なセットアップ |
|---|---|---|
| DM | FileConsentCard → ユーザーが承認 → Botがアップロード | 追加セットアップ不要 |
| グループチャット/チャンネル | SharePointにアップロード → 共有リンクを送信 | sharePointSiteId + Graph権限が必要 |
| 画像(全コンテキスト) | Base64エンコードされたインライン | 追加セットアップ不要 |
グループチャットにSharePointが必要な理由
Botは個人用OneDriveドライブを持っていません(/me/drive Graph APIエンドポイントはアプリケーションIDでは動作しません)。グループチャット/チャンネルでファイルを送信するには、BotがSharePointサイトにアップロードして共有リンクを作成します。
セットアップ
-
Entra ID(Azure AD)→ App RegistrationでGraph API権限を追加します:
Sites.ReadWrite.All(Application)- SharePointへのファイルアップロードChat.Read.All(Application)- 任意、ユーザーごとの共有リンクを有効にします
-
テナントの管理者同意を付与します。
-
SharePointサイトIDを取得します:
# Graph ExplorerまたはcurlでValidなトークンを使用: curl -H "Authorization: Bearer $TOKEN" \ "https://graph.microsoft.com/v1.0/sites/{hostname}:/{site-path}" # 例:"contoso.sharepoint.com/sites/BotFiles" のサイトの場合 curl -H "Authorization: Bearer $TOKEN" \ "https://graph.microsoft.com/v1.0/sites/contoso.sharepoint.com:/sites/BotFiles" # レスポンスに含まれる:"id": "contoso.sharepoint.com,guid1,guid2" -
OpenClawの設定:
{ channels: { msteams: { // ... その他の設定 ... sharePointSiteId: "contoso.sharepoint.com,guid1,guid2", }, }, }
共有動作
| 権限 | 共有動作 |
|---|---|
Sites.ReadWrite.All のみ | 組織全体の共有リンク(組織内の誰でもアクセス可能) |
Sites.ReadWrite.All + Chat.Read.All | ユーザーごとの共有リンク(チャットメンバーのみアクセス可能) |
ユーザーごとの共有はチャット参加者のみがファイルにアクセスできるため、より安全です。Chat.Read.All 権限がない場合、Botは組織全体の共有にフォールバックします。
フォールバック動作
| シナリオ | 結果 |
|---|---|
グループチャット + ファイル + sharePointSiteId 設定済み | SharePointにアップロード、共有リンクを送信 |
グループチャット + ファイル + sharePointSiteId 未設定 | OneDriveアップロードを試行(失敗する可能性あり)、テキストのみ送信 |
| パーソナルチャット + ファイル | FileConsentCardフロー(SharePoint不要) |
| 任意のコンテキスト + 画像 | Base64エンコードされたインライン(SharePoint不要) |
ファイルの保存場所
アップロードされたファイルは、設定されたSharePointサイトのデフォルトドキュメントライブラリ内の /OpenClawShared/ フォルダに保存されます。
投票(Adaptive Cards)
OpenClawはTeamsの投票をAdaptive Cardsとして送信します(ネイティブのTeams投票APIはありません)。
- CLI:
openclaw message poll --channel msteams --target conversation:<id> ... - 投票は
~/.openclaw/msteams-polls.jsonにGatewayで記録されます。 - 投票記録にはGatewayがオンラインである必要があります。
- 投票結果の自動投稿はまだ未実装です(必要に応じてストアファイルを確認してください)。
Adaptive Cards(任意)
メッセージツールまたはCLIを使用して、任意のAdaptive Card JSONをTeamsユーザーまたは会話に送信できます。
card パラメータはAdaptive Card JSONオブジェクトを受け付けます。card が提供されている場合、メッセージテキストは任意です。
エージェントツール:
{
"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:[email protected]" \
--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:[email protected] |
| グループ/チャンネル(直接指定) | <conversation-id> | 19:[email protected](@thread を含む場合) |
CLI例:
# IDでユーザーに送信
openclaw message send --channel msteams --target "user:40a1a0ed-..." --message "Hello"
# 表示名でユーザーに送信(Graph API検索をトリガー)
openclaw message send --channel msteams --target "user:John Smith" --message "Hello"
# グループチャットまたはチャンネルに送信
openclaw message send --channel msteams --target "conversation:19:[email protected]" --message "Hello"
# Adaptive Cardを会話に送信
openclaw message send --channel msteams --target "conversation:19:[email protected]" \
--card '{"type":"AdaptiveCard","version":"1.5","body":[{"type":"TextBlock","text":"Hello"}]}'
エージェントツール例:
{
"action": "send",
"channel": "msteams",
"target": "user:John Smith",
"message": "Hello!"
}
{
"action": "send",
"channel": "msteams",
"target": "conversation:19:[email protected]",
"card": {
"type": "AdaptiveCard",
"version": "1.5",
"body": [{ "type": "TextBlock", "text": "Hello" }]
}
}
注意:user: プレフィックスなしの場合、名前はデフォルトでグループ/チーム解決になります。表示名でユーザーをターゲットにする場合は常に user: を使用してください。
プロアクティブメッセージング
- プロアクティブメッセージはユーザーがインタラクションした後にのみ可能です(その時点で会話参照が保存されるため)。
dmPolicyと許可リストゲーティングについては/gateway/configurationを参照してください。
チームとチャンネルのID(よくある落とし穴)
TeamsのURLに含まれる groupId クエリパラメータは設定で使用するチームIDではありません。URLパスからIDを抽出してください:
チームURL:
https://teams.microsoft.com/l/team/19%3ABk4j...%40thread.tacv2/conversations?groupId=...
└────────────────────────────┘
チームID(これをURLデコード)
チャンネルURL:
https://teams.microsoft.com/l/channel/19%3A15bc...%40thread.tacv2/ChannelName?groupId=...
└─────────────────────────┘
チャンネルID(これをURLデコード)
設定用:
- チームID =
/team/の後のパスセグメント(URLデコード済み、例:19:[email protected]) - チャンネルID =
/channel/の後のパスセグメント(URLデコード済み) groupIdクエリパラメータは無視してください
プライベートチャンネル
Botのプライベートチャンネルサポートは制限的です:
| 機能 | 標準チャンネル | プライベートチャンネル |
|---|---|---|
| Botインストール | あり | 制限あり |
| リアルタイムメッセージ(Webhook) | あり | 動作しない場合あり |
| RSC権限 | あり | 異なる動作の場合あり |
| @メンション | あり | Botがアクセス可能な場合 |
| Graph API履歴 | あり | あり(権限付き) |
プライベートチャンネルが動作しない場合の回避策:
- Bot操作には標準チャンネルを使用
- DMを使用 - ユーザーは常にBotに直接メッセージを送信できます
- 履歴アクセスにはGraph APIを使用(
ChannelMessage.Read.Allが必要)
トラブルシューティング
よくある問題
- チャンネルで画像が表示されない: Graph権限または管理者同意が不足しています。Teamsアプリを再インストールし、Teamsを完全に終了/再起動してください。
- チャンネルで応答がない: デフォルトでメンションが必要です。
channels.msteams.requireMention=falseを設定するか、チーム/チャンネルごとに設定してください。 - バージョン不一致(Teamsが古いマニフェストを表示): アプリを削除して再追加し、Teamsを完全に終了してリフレッシュしてください。
- Webhookからの401 Unauthorized: Azure JWTなしでの手動テスト時に想定される動作で、エンドポイントに到達可能だが認証に失敗したことを意味します。正しくテストするにはAzure Web Chatを使用してください。
マニフェストアップロードエラー
- 「Icon file cannot be empty」: マニフェストが参照するアイコンファイルが0バイトです。有効なPNGアイコン(
outline.pngは32x32、color.pngは192x192)を作成してください。 - 「webApplicationInfo.Id already in use」: アプリが別のチーム/チャットにまだインストールされています。先にアンインストールするか、伝播のため5-10分待ってください。
- アップロード時に「Something went wrong」: 代わりにhttps://admin.teams.microsoft.comからアップロードし、ブラウザのDevTools(F12)→ ネットワークタブを開いて、レスポンスボディで実際のエラーを確認してください。
- サイドロードに失敗: 「Upload a custom app」の代わりに「Upload an app to your org’s app catalog」を試してください。サイドロード制限をバイパスできることが多いです。
RSC権限が機能しない
webApplicationInfo.idがBotのApp IDと正確に一致していることを確認- アプリを再アップロードしてチーム/チャットに再インストール
- 組織の管理者がRSC権限をブロックしていないか確認
- 正しいスコープを使用しているか確認:チームには
ChannelMessage.Read.Group、グループチャットにはChatMessage.Read.Chat
参考リンク
- Azure Bot作成 - Azure Botセットアップガイド
- Teams Developer Portal - Teamsアプリの作成/管理
- Teamsアプリマニフェストスキーマ
- RSCでチャンネルメッセージを受信
- RSC権限リファレンス
- Teams Botファイル処理(チャンネル/グループにはGraphが必要)
- プロアクティブメッセージング