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はローカルインストールパスを自動的に提示します。

詳細:プラグイン

クイックセットアップ(初心者向け)

  1. Microsoft Teamsプラグインをインストールします。
  2. Azure Bot を作成します(App ID + クライアントシークレット + テナントID)。
  3. それらの認証情報でOpenClawを設定します。
  4. /api/messages(デフォルトポート3978)をパブリックURLまたはトンネル経由で公開します。
  5. 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 },
          },
        },
      },
    },
  },
}

仕組み

  1. Microsoft Teamsプラグインをインストールします。
  2. Azure Bot を作成します(App ID + シークレット + テナントID)。
  3. Botを参照し、以下のRSC権限を含む Teamsアプリパッケージ を作成します。
  4. Teamsアプリをチーム(またはDM用のパーソナルスコープ)にアップロード/インストールします。
  5. ~/.openclaw/openclaw.json(または環境変数)で msteams を設定し、Gatewayを起動します。
  6. Gatewayはデフォルトで /api/messages でBot Framework Webhookトラフィックをリッスンします。

Azure Botセットアップ(前提条件)

OpenClawを設定する前に、Azure Botリソースを作成する必要があります。

ステップ1:Azure Botの作成

  1. Azure Bot作成ページにアクセスします

  2. Basics タブに入力します:

    フィールド
    Bot handleBot名(例:openclaw-msteams、一意である必要があります)
    SubscriptionAzureサブスクリプションを選択
    Resource group新規作成または既存を使用
    Pricing tier開発/テスト用は Free
    Type of AppSingle Tenant(推奨 - 以下の注意を参照)
    Creation typeCreate new Microsoft App ID

注意: 新しいマルチテナントBotの作成は2025-07-31以降に非推奨となりました。新規Botには Single Tenant を使用してください。

  1. Review + createCreate をクリック(1-2分程度待ちます)

ステップ2:認証情報の取得

  1. Azure Botリソース → Configuration に移動します
  2. Microsoft App ID をコピー → これが appId です
  3. Manage Password をクリック → App Registrationに移動します
  4. Certificates & secretsNew client secretValue をコピー → これが appPassword です
  5. OverviewDirectory (tenant) ID をコピー → これが tenantId です

ステップ3:メッセージングエンドポイントの設定

  1. Azure Bot → Configuration に移動します
  2. Messaging endpoint にWebhook URLを設定します:
    • 本番環境:https://your-domain.com/api/messages
    • ローカル開発:トンネルを使用(以下のローカル開発を参照)

ステップ4:Teamsチャンネルの有効化

  1. Azure Bot → Channels に移動します
  2. Microsoft Teams → Configure → Save をクリックします
  3. 利用規約に同意します

ローカル開発(トンネリング)

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を使用できます:

  1. + New app をクリック
  2. 基本情報を入力(名前、説明、開発者情報)
  3. App featuresBot に移動
  4. Enter a bot ID manually を選択し、Azure Bot App IDを貼り付け
  5. スコープを確認:PersonalTeamGroup Chat
  6. DistributeDownload app package をクリック
  7. Teamsで:AppsManage your appsUpload a custom app → ZIPを選択

JSONマニフェストを手動編集するよりも簡単な場合が多いです。

Botのテスト

オプションA:Azure Web Chat(まずWebhookを検証)

  1. Azure Portal → Azure Botリソース → Test in Web Chat
  2. メッセージを送信 - 応答が表示されるはずです
  3. これでTeamsセットアップ前にWebhookエンドポイントの動作を確認できます

オプションB:Teams(アプリインストール後)

  1. Teamsアプリをインストール(サイドロードまたは組織カタログ)
  2. TeamsでBotを見つけてDMを送信
  3. Gatewayログで着信アクティビティを確認

セットアップ(最小テキストのみ)

  1. Microsoft Teamsプラグインのインストール

    • npmから:openclaw plugins install @openclaw/msteams
    • ローカルチェックアウトから:openclaw plugins install ./extensions/msteams
  2. Bot登録

    • Azure Botを作成し(上記参照)、以下を記録:
      • App ID
      • クライアントシークレット(Appパスワード)
      • テナントID(シングルテナント)
  3. Teamsアプリマニフェスト

    • botId = <App ID>bot エントリを含めます。
    • スコープ:personalteamgroupChat
    • supportsFiles: true(パーソナルスコープのファイル処理に必要)
    • RSC権限を追加(以下参照)
    • アイコンを作成:outline.png(32x32)と color.png(192x192)
    • 3ファイルをZIPにまとめます:manifest.jsonoutline.pngcolor.png
  4. OpenClawの設定

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

    設定キーの代わりに環境変数も使用できます:

    • MSTEAMS_APP_ID
    • MSTEAMS_APP_PASSWORD
    • MSTEAMS_TENANT_ID
  5. Botエンドポイント

    • Azure Botのメッセージングエンドポイントを以下に設定:
      • https://<host>:3978/api/messages(または選択したパス/ポート)
  6. 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 に使用する面(personalteamgroupChat)を含める必要があります。
  • bots[].supportsFiles: true はパーソナルスコープのファイル処理に必要です。
  • authorization.permissions.resourceSpecific にチャンネルトラフィックが必要な場合はチャンネル読み取り/送信を含める必要があります。

既存アプリの更新

既にインストール済みのTeamsアプリを更新するには(例:RSC権限の追加):

  1. 新しい設定で manifest.json を更新します
  2. version フィールドをインクリメントします(例:1.0.01.1.0
  3. マニフェストとアイコンを再ZIPします(manifest.jsonoutline.pngcolor.png
  4. 新しいZIPをアップロードします:
    • オプションA(Teams管理センター): Teams管理センター → Teamsアプリ → アプリの管理 → アプリを検索 → 新バージョンをアップロード
    • オプションB(サイドロード): Teamsで → Apps → Manage your apps → Upload a custom app
  5. チームチャンネルの場合: 新しい権限を有効にするため、各チームでアプリを再インストールします
  6. 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権限を有効にして管理者同意を付与する必要があります。

  1. Entra ID(Azure AD)のApp Registrationで、Microsoft Graphのアプリケーション権限を追加します:
    • ChannelMessage.Read.All(チャンネル添付 + 履歴)
    • Chat.Read.All または ChatMessage.Read.All(グループチャット)
  2. テナントの管理者同意を付与します。
  3. Teamsアプリのマニフェストバージョンをバンプし、再アップロードして、Teamsでアプリを再インストールします。
  4. 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.appIdchannels.msteams.appPasswordchannels.msteams.tenantId:Bot認証情報
  • channels.msteams.webhook.port(デフォルト 3978
  • channels.msteams.webhook.path(デフォルト /api/messages
  • channels.msteams.dmPolicypairing | allowlist | open | disabled(デフォルト:pairing)
  • channels.msteams.allowFrom:DM許可リスト(AADオブジェクトID推奨)。ウィザードはGraph アクセスが利用可能な場合、セットアップ中に名前をIDに解決します。
  • channels.msteams.dangerouslyAllowNameMatching:変更可能なUPN/表示名マッチングと直接チーム/チャンネル名ルーティングを再有効化するブレークグラストグル。
  • channels.msteams.textChunkLimit:アウトバウンドテキストチャンクサイズ
  • channels.msteams.chunkModelength(デフォルト)または newline(長さチャンキング前に空白行で分割)
  • channels.msteams.mediaAllowHosts:インバウンド添付ホストの許可リスト(デフォルトはMicrosoft/Teamsドメイン)
  • channels.msteams.mediaAuthAllowHosts:メディアリトライ時のAuthorization ヘッダー添付の許可リスト(デフォルトはGraph + Bot Frameworkホスト)
  • channels.msteams.requireMention:チャンネル/グループでの@メンション必須(デフォルトtrue)
  • channels.msteams.replyStylethread | 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フロー(組み込み)でファイルを送信できます。ただし、グループチャット/チャンネルでのファイル送信には追加のセットアップが必要です:

コンテキストファイル送信方法必要なセットアップ
DMFileConsentCard → ユーザーが承認 → Botがアップロード追加セットアップ不要
グループチャット/チャンネルSharePointにアップロード → 共有リンクを送信sharePointSiteId + Graph権限が必要
画像(全コンテキスト)Base64エンコードされたインライン追加セットアップ不要

グループチャットにSharePointが必要な理由

Botは個人用OneDriveドライブを持っていません(/me/drive Graph APIエンドポイントはアプリケーションIDでは動作しません)。グループチャット/チャンネルでファイルを送信するには、BotがSharePointサイトにアップロードして共有リンクを作成します。

セットアップ

  1. Entra ID(Azure AD)→ App RegistrationでGraph API権限を追加します:

    • Sites.ReadWrite.All(Application)- SharePointへのファイルアップロード
    • Chat.Read.All(Application)- 任意、ユーザーごとの共有リンクを有効にします
  2. テナントの管理者同意を付与します。

  3. 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"
  4. 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履歴ありあり(権限付き)

プライベートチャンネルが動作しない場合の回避策:

  1. Bot操作には標準チャンネルを使用
  2. DMを使用 - ユーザーは常にBotに直接メッセージを送信できます
  3. 履歴アクセスには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権限が機能しない

  1. webApplicationInfo.id がBotのApp IDと正確に一致していることを確認
  2. アプリを再アップロードしてチーム/チャットに再インストール
  3. 組織の管理者がRSC権限をブロックしていないか確認
  4. 正しいスコープを使用しているか確認:チームには ChannelMessage.Read.Group、グループチャットには ChatMessage.Read.Chat

参考リンク