Microsoft Teams (プラグイン)

"汝ここに入る者、一切の希望を捨てよ。"

更新日: 2026-01-21

状態: テキスト + DM添付ファイルに対応。チャネル/グループでのファイル送信には sharePointSiteId + Graph権限が必要です(グループチャットでのファイル送信を参照)。投票はAdaptive Cardsを介して送信されます。

プラグインが必要

Microsoft Teamsはプラグインとして提供されており、コアインストールにはバンドルされていません。

破壊的変更 (2026.1.15): MS TeamsはコアからプラグインとBして移行されました。使用する場合は、プラグインをインストールする必要があります。

説明: コアインストールを軽量に保ち、MS Teams依存関係を独立して更新できるようにするためです。

CLI経由でインストール (npmレジストリ):

openclaw plugins install @openclaw/msteams

ローカルチェックアウト (gitリポジトリから実行する場合):

openclaw plugins install ./extensions/msteams

configure/オンボーディング中にTeamsを選択し、gitチェックアウトが検出された場合、 OpenClawは自動的にローカルインストールパスを提供します。

詳細: Plugins

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

  1. Microsoft Teamsプラグインをインストールします。
  2. Azure Botを作成します (App ID + クライアントシークレット + テナントID)。
  3. これらの認証情報でOpenClawを設定します。
  4. 公開URLまたはトンネル経由で /api/messages (デフォルトはポート3978) を公開します。
  5. Teamsアプリパッケージをインストールし、ゲートウェイを起動します。

最小限の設定:

{
  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、または表示名を受け入れます。ウィザードは、認証情報が許可されている場合、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" でチーム許可リストが存在する場合、リストされたチーム/チャネルのみが受け入れられます (メンション制御)。
  • 設定ウィザードは Team/Channel エントリを受け入れ、保存します。
  • 起動時、OpenClawはチーム/チャネルとユーザー許可リストの名前をIDに解決し (Graph権限が許可されている場合)、 マッピングをログに記録します。解決できないエントリは入力されたまま保持されます。

例:

{
  channels: {
    msteams: {
      groupPolicy: "allowlist",
      teams: {
        "My Team": {
          channels: {
            "General": { requireMention: true }
          }
        }
      }
    }
  }
}

仕組み

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

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

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

ステップ1: Azure Botを作成

  1. Azure Bot作成にアクセス

  2. 基本タブを入力:

    フィールド
    ボットハンドルボット名、例: openclaw-msteams (一意である必要があります)
    サブスクリプションAzureサブスクリプションを選択
    リソースグループ新規作成または既存を使用
    価格レベル開発/テスト用は無料
    アプリの種類シングルテナント (推奨 - 以下の注記を参照)
    作成タイプ新しいMicrosoft App IDを作成

非推奨に関する注記: 2025-07-31以降、新しいマルチテナントボットの作成は非推奨になりました。新しいボットにはシングルテナントを使用してください。

  1. 確認 + 作成作成 をクリック (約1-2分待機)

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

  1. Azure Botリソース → 構成 に移動
  2. Microsoft App ID をコピー → これが appId です
  3. パスワードの管理 をクリック → アプリ登録に移動
  4. 証明書とシークレット新しいクライアントシークレット をコピー → これが appPassword です
  5. 概要 に移動 → ディレクトリ (テナント) ID をコピー → これが tenantId です

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

  1. Azure Bot → 構成
  2. メッセージングエンドポイント をwebhook URLに設定:
    • 本番環境: https://your-domain.com/api/messages
    • ローカル開発: トンネルを使用 (以下のローカル開発を参照)

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

  1. Azure Bot → チャネル
  2. Microsoft Teams をクリック → 構成 → 保存
  3. 利用規約に同意

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

Teamsは localhost にアクセスできません。ローカル開発にはトンネルを使用します:

オプションA: ngrok

ngrok http 3978
# httpsURLをコピー、例: https://abc123.ngrok.io
# メッセージングエンドポイントを次のように設定: https://abc123.ngrok.io/api/messages

オプションB: Tailscale Funnel

tailscale funnel 3978
# Tailscale funnel URLをメッセージングエンドポイントとして使用

Teams開発者ポータル (代替)

マニフェストZIPを手動で作成する代わりに、Teams開発者ポータルを使用できます:

  1. + 新しいアプリ をクリック
  2. 基本情報を入力 (名前、説明、開発者情報)
  3. アプリ機能ボット に移動
  4. ボットIDを手動で入力 を選択し、Azure BotアプリIDを貼り付け
  5. スコープをチェック: 個人チームグループチャット
  6. 配布アプリパッケージをダウンロード をクリック
  7. Teamsで: アプリアプリを管理カスタムアプリをアップロード → ZIPを選択

これはJSONマニフェストを手動編集するより簡単なことが多いです。

ボットのテスト

オプションA: Azure Webチャット (webhook検証用)

  1. Azureポータル → Azure Botリソース → Webチャットでテスト
  2. メッセージを送信 - 応答が表示されるはずです
  3. Teamsセットアップ前にwebhookエンドポイントが機能することを確認します

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

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

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

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

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

    • Azure Botを作成 (上記参照) し、以下を記録:
      • App ID
      • クライアントシークレット (アプリパスワード)
      • テナント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. ボットエンドポイント

    • Azure Botメッセージングエンドポイントを次のように設定:
      • https://<host>:3978/api/messages (または選択したパス/ポート)。
  6. ゲートウェイを実行

    • プラグインがインストールされ、認証情報を含む 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 → アプリ → アプリを管理 → カスタムアプリをアップロード
  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) アプリ登録で、Microsoft Graph アプリケーション権限を追加:
    • ChannelMessage.Read.All (チャネル添付ファイル + 履歴)
    • Chat.Read.All または ChatMessage.Read.All (グループチャット)
  2. テナントの管理者の同意を付与
  3. Teamsアプリのマニフェストバージョンを上げて、再アップロードし、Teamsでアプリを再インストール
  4. Teamsを完全に終了して再起動してキャッシュされたアプリメタデータをクリア。

既知の制限事項

Webhookタイムアウト

TeamsはHTTP webhook経由でメッセージを配信します。処理に時間がかかりすぎる場合 (例: 遅いLLM応答)、次のような問題が発生する可能性があります:

  • ゲートウェイタイムアウト
  • Teamsがメッセージを再試行 (重複の原因)
  • 返信がドロップされる

OpenClawは迅速に戻り、プロアクティブに返信を送信することでこれを処理しますが、非常に遅い応答は依然として問題を引き起こす可能性があります。

フォーマット

Teamsのmarkdownは、SlackやDiscordよりも制限されています:

  • 基本的なフォーマットは機能: 太字イタリックコード、リンク
  • 複雑なmarkdown (テーブル、ネストリスト) は正しくレンダリングされない可能性があります
  • Adaptive Cardsは投票と任意のカード送信に対応 (以下を参照)

設定

主要な設定 (共有チャネルパターンについては /gateway/configuration を参照):

  • channels.msteams.enabled: チャネルを有効/無効化。
  • channels.msteams.appIdchannels.msteams.appPasswordchannels.msteams.tenantId: ボット認証情報。
  • 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、UPN、または表示名)。ウィザードは、Graphアクセスが利用可能な場合、セットアップ中に名前をIDに解決します。
  • channels.msteams.textChunkLimit: アウトバウンドテキストチャンクサイズ。
  • channels.msteams.chunkMode: length (デフォルト) または newline で空白行 (段落境界) で分割してから長さチャンク。
  • channels.msteams.mediaAllowHosts: インバウンド添付ファイルホストの許可リスト (デフォルトはMicrosoft/Teamsドメイン)。
  • 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: チャネルごとの送信者ごとのツールポリシーオーバーライド ("*" ワイルドカードサポート)。
  • 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
ポスト (クラシック)メッセージはカードとして表示され、その下にスレッド化された返信thread (デフォルト)
スレッド (Slackライク)メッセージはSlackのように線形に流れるtop-level

問題: Teams APIはチャネルが使用するUIスタイルを公開しません。間違った replyStyle を使用すると:

  • スレッドスタイルチャネルで thread → 返信が不自然にネストされる
  • ポストスタイルチャネルで top-level → 返信がスレッド内ではなく別のトップレベルポストとして表示される

解決策: チャネルの設定に基づいてチャネルごとに replyStyle を設定:

{
  "msteams": {
    "replyStyle": "thread",
    "teams": {
      "19:[email protected]": {
        "channels": {
          "19:[email protected]": {
            "replyStyle": "top-level"
          }
        }
      }
    }
  }
}

添付ファイルと画像

現在の制限:

  • DM: 画像とファイル添付ファイルはTeamsボットファイルAPI経由で機能します。
  • チャネル/グループ: 添付ファイルはM365ストレージ (SharePoint/OneDrive) に存在します。webhookペイロードにはHTMLスタブのみが含まれ、実際のファイルバイトは含まれません。チャネル添付ファイルをダウンロードするにはGraph API権限が必要です。

Graph権限がない場合、画像を含むチャネルメッセージはテキストのみとして受信されます (画像コンテンツはボットにアクセスできません)。 デフォルトでは、OpenClawはMicrosoft/Teamsホスト名からのみメディアをダウンロードします。channels.msteams.mediaAllowHosts で上書き (全ホストを許可するには ["*"] を使用)。

グループチャットでのファイル送信

ボットはFileConsentCardフロー (組み込み) を使用してDMでファイルを送信できます。ただし、グループチャット/チャネルでファイルを送信するには追加のセットアップが必要です:

コンテキストファイルの送信方法必要なセットアップ
DMFileConsentCard → ユーザーが承諾 → ボットがアップロードすぐに動作
グループチャット/チャネルSharePointにアップロード → 共有リンクsharePointSiteId + Graph権限が必要
画像 (任意のコンテキスト)Base64エンコードインラインすぐに動作

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

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

セットアップ

  1. Entra ID (Azure AD) → アプリ登録でGraph API権限を追加:

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

  3. SharePointサイトIDを取得:

    # Graph ExplorerまたはcurlにValid TOKENで:
    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 権限がない場合、ボットは組織全体の共有にフォールバックします。

フォールバック動作

シナリオ結果
グループチャット + ファイル + 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 に記録されます。
  • ゲートウェイは投票を記録するためにオンラインである必要があります。
  • 投票はまだ結果の要約を自動投稿しません (必要に応じてストアファイルを検査)。

Adaptive Cards (任意)

message ツールまたは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 クエリパラメータは無視

プライベートチャネル

ボットはプライベートチャネルで限定的なサポートがあります:

機能標準チャネルプライベートチャネル
ボットインストールあり制限あり
リアルタイムメッセージ (webhook)あり動作しない可能性
RSC権限あり動作が異なる可能性
@メンションありボットがアクセス可能な場合
Graph API履歴ありあり (権限付き)

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

  1. ボット対話には標準チャネルを使用
  2. DMを使用 - ユーザーは常にボットに直接メッセージできます
  3. 履歴アクセスにはGraph APIを使用 (ChannelMessage.Read.All が必要)

トラブルシューティング

よくある問題

  • チャネルで画像が表示されない: Graph権限または管理者の同意が欠落。Teamsアプリを再インストールし、Teamsを完全に終了/再起動。
  • チャネルで応答がない: デフォルトではメンションが必要。channels.msteams.requireMention=false を設定するか、チーム/チャネルごとに設定。
  • バージョンの不一致 (Teamsが古いマニフェストを表示): アプリを削除して再追加し、Teamsを完全に終了して更新。
  • webhookから401 Unauthorized: Azure JWTなしで手動テストする場合は予想される - エンドポイントは到達可能だが認証失敗を意味します。適切にテストするにはAzure Webチャットを使用。

マニフェストアップロードエラー

  • "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) → ネットワークタブを開き、実際のエラーのレスポンス本文を確認。
  • サイドロード失敗: 「カスタムアプリをアップロード」ではなく「組織のアプリカタログにアプリをアップロード」を試す - これはサイドロード制限をバイパスすることが多いです。

RSC権限が動作しない

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

参考資料