🦞

ラズパイで育てる!自分だけのAI【チャネル編】② TeamsでAIと話す

に公開

はじめに

🎯 この記事の対象読者

  • 基礎編 ① 〜 ⑥ を完了し、Discord から AI と会話できている方
  • チャネル編①(LINE)を完了し、Tailscale Funnel をセットアップ済みの方
  • Microsoft Teams からも AI に話しかけたい方

前提環境:

項目 確認済み内容
OpenClaw Discord Bot が正常に応答している
pass pass show discord/openclaw が値を返す
Tailscale Funnel チャネル編①でセットアップ済み・動作中
Microsoft 365 テナントへの管理者アクセスがある

Discord は開発者のハブ、LINE はプライベートの窓口。では 仕事で毎日使っている Teams からも AI に話しかけたくなったら?

チャネル編①の LINE と同じく、Teams も Webhook 型の接続です。ただし間に Azure Bot Service というクラウドのメッセージルーターが入る点が大きく違います。LINE より手順は増えますが、やることの本質は同じです。

もうひとつの違いは、msteams プラグインはコアにバンドルされているものの、依存パッケージが Docker イメージに含まれていない点です。Dockerfile.custom でひと手間加える必要があります。


Teams は LINE と何が違うのか

LINE と Teams はどちらも「外部サーバーから Pi にリクエストが届く」Webhook 型です。ただし、LINE は LINE サーバーが直接 Pi に届けるのに対し、Teams は Azure Bot Service が中継します。

[Teams アプリ]
    ↓ メッセージ送信
[Microsoft Teams サーバー]

[Azure Bot Service] ← クラウド上のメッセージルーター
    ↓ HTTPS POST /api/messages
[Tailscale Funnel] ← インターネット側の入口
    ↓ HTTP(ローカル)
[Pi: OpenClaw + msteams プラグイン] ← ポート 3978 で受信

[Gemini / Claude など]
    ↓ 応答
[OpenClaw] → Azure Bot Service → Teams へ返信

LINE との比較をまとめます。

項目 LINE(チャネル編①) Teams(本記事)
プラグイン コア組み込み(追加不要) コア組み込み(依存パッケージの追加が必要)
中継サービス なし(LINE → Pi 直接) Azure Bot Service
認証情報 2つ(Token + Secret) 3つ(App ID + Password + Tenant ID)
Webhook ポート 18789 3978
コスト 無料(Reply API) 無料(Bot Service Free レベル)
Azure Bot Service の料金体系

Azure Bot Service のチャネルは Standard チャネル(Teams、Slack、Facebook など)と Premium チャネル(Direct Line、Direct Line Speech)に分かれています。

プラン Standard チャネル Premium チャネル
Free(F0) 無制限・無料 月 10,000 メッセージまで
Standard(S1) 無制限・無料 $0.50 / 1,000 メッセージ

Teams は Standard チャネルに分類されるため、Free プランでも Standard プランでもメッセージ数の制限はありません。カウントされるのは Bot が受信するメッセージ(ユーザー → Bot)のみで、Bot の応答メッセージはカウント対象外です。

個人の Raspberry Pi 運用であれば Free プランで十分です。Free と Standard の主な違いは SLA(Standard のみ 99.9%)と Premium チャネルの上限です。Teams だけで使うなら Free 一択です。

参考: Azure AI Bot Service の価格


ステップ 1: Azure Bot Service を作成する

Azure Portal で Bot リソースを作成します。この手順で Entra ID(旧 Azure AD)のアプリ登録も自動的に作成されるため、手動でのアプリ登録は不要です。

① Azure Portal にアクセスする

  1. Azure Portal にサインイン
  2. 上部の検索バーに「Azure Bot」と入力
  3. 「Azure Bot」を選択 →「作成」

② Bot の基本設定を入力する

項目 設定値
Bot handle openclaw-teams(任意の名前)
サブスクリプション 使用する Azure サブスクリプション
リソースグループ 新規作成または既存を選択
Data residency Global
価格レベル Free
Microsoft App ID の種類 Single Tenant(シングルテナント)
作成の種類 新しい Microsoft App ID の作成
Data residency(データ所在地)について

Bot 作成画面で Data residency の選択肢が表示されます。これは Bot のメッセージやファイルがどの地域で処理・保存されるか を制御する設定です。

モード 動作 対象
Global(デフォルト) Azure が自動でリージョンを選定して処理 個人利用・コンプライアンス要件なし
Regional 指定した地域(West Europe / Central India)内でのみ処理 GDPR 対象ユーザーがいる場合

個人の Raspberry Pi 運用では Global で問題ありません。Regional は EU の GDPR 規制など、特定地域にデータを留める法的義務がある場合に選択します。

注意点として、Data residency は 作成後に変更できません。変更するにはリソースを削除して作り直す必要があります。個人利用なら Global 一択ですが、将来 EU ユーザーを含める可能性がある企業利用の場合は Regional(West Europe)で作成しておくと安心です。

③ 作成後に値を取得する

作成が完了したら、Bot リソースの「構成」画面で以下の値を確認します。

取得する値 場所
Microsoft App ID 構成 → Microsoft App ID
Tenant ID 構成 → Microsoft App ID のリンク → Entra ID のアプリ概要画面「ディレクトリ(テナント)ID」

④ メッセージングエンドポイントを設定する

「構成」画面の「メッセージングエンドポイント」に以下を入力します。

https://<hostname>.<tailnet>.ts.net/api/messages

<hostname>.<tailnet>.ts.net はチャネル編①で取得した Tailscale Funnel の URL です。tailscale funnel status で確認できます。

⑤ Teams チャネルを有効化する

  1. Bot リソースの「チャネル」を開く
  2. 「Microsoft Teams」を選択して有効化
  3. 利用規約に同意して保存

ステップ 2: クライアントシークレットを作成する

Bot の認証に使うクライアントシークレットを Entra ID で作成します。

  1. Azure Portal → Entra ID(または Azure Active Directory)
  2. 「アプリの登録」→ ステップ 1 で自動作成されたアプリを開く
  3. 左メニュー「証明書とシークレット」→「クライアントシークレット」タブ
  4. 「新しいクライアントシークレット」をクリック
  5. 説明: OpenClaw Teams Bot、有効期限: 12 ヶ月(推奨)
  6. 「追加」をクリック
証明書ベース認証について

Microsoft は本番環境では証明書ベース認証を推奨しています。クライアントシークレットは「知識」ベース(文字列を知っていれば使える)、証明書は「所有」ベース(ファイルを持っていないと使えない)で、セキュリティレベルが異なります。

この記事では手軽なクライアントシークレット方式で進めます。企業の本番環境で長期運用する場合は、自己署名証明書を作成してアプリ登録にアップロードする方式を検討してください。


ステップ 3: トークンを pass に保存する

取得した 3 つの値を pass に保存します。

ssh pi@pi01

# App ID を保存
pass insert msteams/openclaw-app-id
# → Enter password for msteams/openclaw-app-id: と表示されたら貼り付けて Enter

# クライアントシークレットを保存
pass insert msteams/openclaw-app-password
# → Enter password for msteams/openclaw-app-password: と表示されたら貼り付けて Enter

# Tenant ID を保存
pass insert msteams/openclaw-tenant-id
# → Enter password for msteams/openclaw-tenant-id: と表示されたら貼り付けて Enter

# 確認
pass show msteams/openclaw-app-id
pass show msteams/openclaw-app-password
pass show msteams/openclaw-tenant-id

ステップ 4: msteams プラグインを確認する

LINE と同じく、msteams プラグインは OpenClaw のコアにバンドルされています。追加のインストールは不要です。

念のため、バンドルされているか確認しておきます。

docker compose -f ~/projects/openclaw/docker-compose.yml \
               -f ~/projects/openclaw/docker-compose.override.yml \
               exec openclaw-gateway openclaw plugins list

msteams が一覧に表示されれば OK です。そのままステップ 5 に進んでください。

msteams の依存パッケージを追加する(v2026.2.22 以前のみ)

v2026.2.22 以前では、実行時に必要な @microsoft/agents-hosting パッケージが Docker イメージに含まれていません。Dockerfile.custom に以下を追記してください。

ツール編② PlaywrightDockerfile.custom を作成済みの方は、末尾に追加します。

# === msteams プラグインの依存パッケージ ===
RUN npm install --prefix /app/extensions/msteams @microsoft/agents-hosting --no-save

Dockerfile.custom がまだない方は、以下の内容で作成します。

cat > ~/projects/openclaw/Dockerfile.custom <<'EOF'
FROM openclaw:local

# === msteams プラグインの依存パッケージ ===
RUN npm install --prefix /app/extensions/msteams @microsoft/agents-hosting --no-save
EOF

カスタムイメージを再ビルドします。

cd ~/projects/openclaw
docker build -f Dockerfile.custom -t openclaw-gateway-custom:local .

ステップ 5: openclaw.json に Teams 設定を追加する

# バックアップ
cp ~/.openclaw/openclaw.json ~/.openclaw/openclaw.json.bak

# Teams チャンネル設定を追加
python3 - <<'EOF'
import json, pathlib

p = pathlib.Path.home() / ".openclaw/openclaw.json"
cfg = json.loads(p.read_text())

cfg.setdefault("channels", {}).setdefault("msteams", {}).update({
    "enabled": True,
    "appId": "",
    "appPassword": "",
    "tenantId": "",
    "webhook": {
        "port": 3978,
        "path": "/api/messages"
    },
    "dmPolicy": "pairing"
})

p.write_text(json.dumps(cfg, ensure_ascii=False, indent=2))
print("Done")
print(json.dumps(cfg["channels"]["msteams"], ensure_ascii=False, indent=2))
EOF

出力例:

{
  "enabled": true,
  "appId": "",
  "appPassword": "",
  "tenantId": "",
  "webhook": {
    "port": 3978,
    "path": "/api/messages"
  },
  "dmPolicy": "pairing"
}

ステップ 6: start-openclaw.sh と docker-compose.override.yml を更新する

start-openclaw.sh に Teams トークンを追加

nano ~/projects/openclaw/start-openclaw.sh

既存のエクスポート行の直後に 3 行追記します。

export DISCORD_BOT_TOKEN=$(pass show discord/openclaw)
export GEMINI_API_KEY=$(pass show gemini/openclaw)
export BRAVE_API_KEY=$(pass show brave/openclaw)
export LINE_CHANNEL_ACCESS_TOKEN=$(pass show line/openclaw-token)
export LINE_CHANNEL_SECRET=$(pass show line/openclaw-secret)
export MSTEAMS_APP_ID=$(pass show msteams/openclaw-app-id)               # ← 追加
export MSTEAMS_APP_PASSWORD=$(pass show msteams/openclaw-app-password)    # ← 追加
export MSTEAMS_TENANT_ID=$(pass show msteams/openclaw-tenant-id)          # ← 追加

docker-compose.override.yml を更新する

環境変数とポートの両方を追加します。

services:
  openclaw-gateway:
    ports:
      - "127.0.0.1:3978:3978"                                      # ← 追加
    environment:
      - DISCORD_BOT_TOKEN=${DISCORD_BOT_TOKEN}
      - GEMINI_API_KEY=${GEMINI_API_KEY}
      - BRAVE_API_KEY=${BRAVE_API_KEY}
      - LINE_CHANNEL_ACCESS_TOKEN=${LINE_CHANNEL_ACCESS_TOKEN}
      - LINE_CHANNEL_SECRET=${LINE_CHANNEL_SECRET}
      - MSTEAMS_APP_ID=${MSTEAMS_APP_ID}                            # ← 追加
      - MSTEAMS_APP_PASSWORD=${MSTEAMS_APP_PASSWORD}                # ← 追加
      - MSTEAMS_TENANT_ID=${MSTEAMS_TENANT_ID}                      # ← 追加
      - TZ=Asia/Tokyo
  openclaw-cli:
    environment:
      - DISCORD_BOT_TOKEN=${DISCORD_BOT_TOKEN}
      - GEMINI_API_KEY=${GEMINI_API_KEY}
      - BRAVE_API_KEY=${BRAVE_API_KEY}
      - LINE_CHANNEL_ACCESS_TOKEN=${LINE_CHANNEL_ACCESS_TOKEN}
      - LINE_CHANNEL_SECRET=${LINE_CHANNEL_SECRET}
      - MSTEAMS_APP_ID=${MSTEAMS_APP_ID}                            # ← 追加
      - MSTEAMS_APP_PASSWORD=${MSTEAMS_APP_PASSWORD}                # ← 追加
      - MSTEAMS_TENANT_ID=${MSTEAMS_TENANT_ID}                      # ← 追加
      - TZ=Asia/Tokyo

ステップ 7: Tailscale Funnel にポート 3978 を追加する

チャネル編①で LINE 用に sudo tailscale funnel --bg 18789 を設定しました。Teams 用にポート 3978 も追加します。

sudo tailscale funnel --bg 3978

両方のポートが公開されているか確認します。

tailscale funnel status

https://<hostname>.<tailnet>.ts.net 配下に 18789(LINE)と 3978(Teams)の両方が表示されていれば OK です。


ステップ 8: Teams App マニフェストを作成・アップロードする

Teams に Bot を追加するには、アプリマニフェスト(manifest.json)とアイコンを zip にまとめてアップロードします。

マニフェストを作成する

以下の JSON を manifest.json として保存します。2 箇所の <APP_ID> を両方ともステップ 1 で取得した Microsoft App ID(GUID 形式: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx)に置き換えてください。

{
  "$schema": "https://developer.microsoft.com/json-schemas/teams/v1.17/MicrosoftTeams.schema.json",
  "manifestVersion": "1.17",
  "version": "1.0.0",
  "id": "<APP_ID>",
  "developer": {
    "name": "OpenClaw Bot Owner",
    "websiteUrl": "https://openclaw.ai",
    "privacyUrl": "https://openclaw.ai/privacy",
    "termsOfUseUrl": "https://openclaw.ai/terms"
  },
  "name": {
    "short": "OpenClaw",
    "full": "OpenClaw — あなた専用のAIアシスタント"
  },
  "description": {
    "short": "あなた専用のAIアシスタント",
    "full": "あなた専用のAIアシスタントです。質問、相談、調べもの、なんでも気軽に話しかけてください。"
  },
  "icons": {
    "outline": "outline.png",
    "color": "color.png"
  },
  "accentColor": "#FF6B35",
  "bots": [
    {
      "botId": "<APP_ID>",
      "scopes": ["personal", "team", "groupChat"],
      "isNotificationOnly": false,
      "supportsFiles": false
    }
  ],
  "validDomains": []
}
グループチャット・チャネルで @メンションなしにする場合(RSC 権限)

後述の「利用シーンを広げる」セクションで説明しますが、グループチャットやチームチャネルで @メンションなしで Bot にメッセージを届けるには、manifest.json に RSC(Resource Specific Consent)権限 を追加する必要があります。

以下のセクションをマニフェストに追加してください(botsvalidDomains と同じ階層)。

// manifest.json に追加(bots や validDomains と同じ階層)
"webApplicationInfo": {
  "id": "<APP_ID>",
  "resource": ""          // Teams Bot では空文字で可
},
"authorization": {
  "permissions": {
    "resourceSpecific": [
      {
        "name": "ChannelMessage.Read.Group",
        "type": "Application"
      },
      {
        "name": "ChatMessage.Read.Chat",
        "type": "Application"
      }
    ]
  }
}
権限名 効果
ChannelMessage.Read.Group チームチャネルで @メンションなしのメッセージも Bot に配信される
ChatMessage.Read.Chat グループチャットで @メンションなしのメッセージも Bot に配信される

1対1チャット(DM)では RSC 権限は不要です。 DM はもともとすべてのメッセージが Bot に届きます。

RSC 権限を追加した場合、アプリをチームやグループチャットに追加する際に権限の同意画面が表示されます。チーム所有者やグループメンバーが同意すると、Bot が全メッセージを受信できるようになります。

@メンション必須のままで問題ない場合(デフォルト)は、この設定は不要です。

アイコンを用意する

ファイル名 サイズ 用途
outline.png 32 x 32 px 透過背景のアウトラインアイコン
color.png 192 x 192 px フルカラーアイコン

シンプルなアイコンで構いません。OpenClaw のロゴや自作のアイコンを用意してください。

zip にまとめてアップロードする

openclaw-teams-app/
├── manifest.json
├── outline.png
└── color.png

この 3 ファイルを zip に圧縮します。

Teams へのアップロード手順:

  1. Teams を開く →「アプリ」→「アプリの管理」
  2. 「カスタムアプリをアップロード」を選択
  3. 作成した zip ファイルをアップロード
  4. アプリの説明を確認して「追加」
scopes の選択肢について

マニフェストの scopesopenclaw.json のポリシー設定の組み合わせで、Bot がどこで使えるかが決まります。詳しくはステップ 9 以降の「利用シーンを広げる」セクションを参照してください。

チームや組織全体に配布するには

「カスタムアプリをアップロード」で追加した Bot は 自分だけ が使える状態(サイドロード)です。チームのメンバーや組織全体で使いたい場合は、Teams 管理者が組織のアプリカタログに公開する必要があります。

配布方法 範囲 必要な権限
サイドロード(本記事の手順) 自分だけ ユーザー
組織のアプリカタログに公開 テナント全体 Teams 管理者
Teams App Store に公開 全世界 Microsoft の審査通過

組織のアプリカタログに公開する手順:

  1. Teams Admin Center にアクセス(管理者アカウントでサインイン)
  2. Teams アプリアプリの管理新しいアプリをアップロード
  3. ステップ 8 で作成した zip ファイルをアップロード

管理者がアップロードすると、承認なしで組織のアプリストアに公開されます。テナント内のユーザーは Teams の「アプリ」→「自分の組織向けに作成」から Bot を追加できます。

前提条件:

  • アップロードする人が Teams 管理者(またはグローバル管理者)であること
  • テナントの セットアップポリシー で「カスタムアプリのアップロード」が オン になっていること(Teams Admin Center → Teams アプリセットアップポリシーGlobal (Org-wide default)

ステップ 9: 再起動と動作確認

bash ~/projects/openclaw/start-openclaw.sh

起動後、環境変数がコンテナに渡っているか確認します。

docker compose -f ~/projects/openclaw/docker-compose.yml \
               -f ~/projects/openclaw/docker-compose.override.yml \
               exec openclaw-gateway env | grep MSTEAMS
# MSTEAMS_APP_ID=...
# MSTEAMS_APP_PASSWORD=...
# MSTEAMS_TENANT_ID=...
# 3つとも表示されれば OK

ログに Teams 関連のエラーがないか確認します。

docker compose -f ~/projects/openclaw/docker-compose.yml \
               -f ~/projects/openclaw/docker-compose.override.yml \
               logs --tail=30 openclaw-gateway | grep -i teams

Teams から話しかけてみる

Teams で Bot を開いて(アプリ一覧から「OpenClaw」を選択)、DM でメッセージを送ります。

初回は以下のような応答が返ってきます。

OpenClaw: access not configured.

Your msteamsUserId: 29:1xxxx...

Pairing code: XXXXXXXX

Ask the bot owner to approve with:
openclaw pairing approve msteams XXXXXXXX

LINE と同じペアリング方式です。Pi で以下を実行して承認します。

docker compose -f ~/projects/openclaw/docker-compose.yml \
               -f ~/projects/openclaw/docker-compose.override.yml \
               exec openclaw-gateway openclaw pairing approve msteams XXXXXXXX

XXXXXXXX は Teams に表示されたペアリングコードに置き換えてください。

承認後、Teams から再度メッセージを送ると AI が応答します。


利用シーンを広げる — グループチャット & チームチャネル

ここまでのステップで 1対1チャット(DM) が動く状態になりました。Teams Bot はさらに グループチャットチームチャネル でも使えます。

使い方 manifest scopes openclaw.json 話しかけ方 @メンション
1:1 DM personal dmPolicy 直接メッセージ 不要
グループチャット groupChat groupPolicy: "open" @OpenClaw 必須(デフォルト)
チームチャネル team groupPolicy: "open" @OpenClaw 必須(デフォルト)

ステップ 8 のマニフェストは 3 つすべてのスコープ("scopes": ["personal", "team", "groupChat"])を含んでいるため、マニフェストの変更は不要です。openclaw.json の設定変更と、Teams 上での Bot 追加操作 だけで使えるようになります。

パターン 1: 1対1チャット(DM)— 設定済み

ステップ 5 〜 9 で完了しています。dmPolicy: "pairing" がデフォルトで、ペアリング承認後に会話できます。

テナント内メンバーだけなら "open" にすると承認なしで即会話できます。openclaw.jsonmsteams ブロックに dmPolicyallowFrom の両方を設定してください(ステップ 5 では allowFrom を省略しているため追加が必要です)。

"dmPolicy": "open",
"allowFrom": ["*"]

パターン 2: グループチャットに Bot を追加する

複数人のグループチャットに Bot を追加して、メンションで話しかけるパターンです。

① openclaw.json を設定する

python3 - <<'EOF'
import json, pathlib

p = pathlib.Path.home() / ".openclaw/openclaw.json"
cfg = json.loads(p.read_text())

cfg["channels"]["msteams"]["groupPolicy"] = "open"

p.write_text(json.dumps(cfg, ensure_ascii=False, indent=2))
print("groupPolicy:", cfg["channels"]["msteams"]["groupPolicy"])
EOF

② OpenClaw を再起動する

bash ~/projects/openclaw/start-openclaw.sh

③ Teams でグループチャットに Bot を追加する

  1. Teams でグループチャットを開く(既存のグループ、または新規作成)
  2. チャット画面の上部にある 参加者の追加(人のアイコン+)をクリック
  3. 検索ボックスに Bot 名(「OpenClaw」)を入力
  4. 表示された Bot を選択して追加

④ Bot に話しかける

グループチャットでは @メンションが必須 です(デフォルト)。

@OpenClaw 今日の天気を教えて

Bot がメンションされたメッセージだけに応答します。メンションなしのメッセージは Bot に配信されないため、他のメンバー同士の会話に Bot が割り込むことはありません。

パターン 3: チームチャネルに Bot を追加する

チーム内のチャネル(#general など)で Bot を使うパターンです。

① openclaw.json の設定

パターン 2 と同じく groupPolicy: "open" が必要です(未設定の場合はパターン 2 の手順を実行)。チャネルでの利用も groupPolicy で制御されます。

② チームに Bot を追加する

  1. Teams のサイドバーでチーム名の横にある 「…」 をクリック
  2. 「チームを管理」 を選択
  3. 「アプリ」 タブを開く
  4. 「その他のアプリを入手」 をクリック
  5. 「自分の組織向けに作成」 セクションから「OpenClaw」を検索して 「追加」

③ チャネルで Bot に話しかける

グループチャットと同じく @メンションが必須 です。

@OpenClaw このチャネルの要約を作って

Bot はメンションされたチャネル内のメッセージに応答します。

@メンションなしで反応させたい場合(グループチャット / チャネルのみ)

1対1チャット(DM)はもともと @メンション不要で動きます。ここではグループチャットとチームチャネルで @メンションを不要にする方法を説明します。

@メンションなしにするには 2 箇所の設定が必要です。

設定箇所 設定内容 役割
Teams 側(manifest.json) RSC 権限を追加 Teams がメンションなしメッセージも Bot に配信する
OpenClaw 側(openclaw.json) requireMention: false Bot がメンションなしメッセージを処理する

① manifest.json に RSC 権限を追加する

ステップ 8 の manifest.json に webApplicationInfoauthorization セクションを追加してください(詳細はステップ 8 の「グループチャット・チャネルで @メンションなしにする場合(RSC 権限)」を参照)。

追加後、zip を作り直して Teams に再アップロードします。

② openclaw.json に requireMention 設定を追加する

全体のデフォルトはメンション必須のまま、特定のチャネルだけメンション不要にするのがおすすめです。

"msteams": {
  "enabled": true,
  "requireMention": true,
  "teams": {
    "プロジェクトA": {
      "requireMention": true,
      "channels": {
        "ai-sandbox": { "requireMention": false }
      }
    }
  }
}

この例では:

  • 全体: @メンション必須(デフォルト)
  • プロジェクトA / ai-sandbox: メンション不要(このチャネルだけ自由に話しかけられる)
  • プロジェクトA / general など他のチャネル: メンション必須のまま

設定の優先順位は チャネル > チーム > グローバル です。より具体的な設定が優先されます。

teamschannels のキーには ディスプレイ名"プロジェクトA")と ID"19:xxx@thread.tacv2")のどちらも使えます。ディスプレイ名を使うと起動時に OpenClaw が自動的に ID へ解決します。チーム名やチャネル名を変更する可能性がある場合は ID を使うと安定します。

チーム ID・チャネル ID の取得方法

Teams でチャネルを右クリック →「チャネルへのリンクを取得」→ URL の groupId= がチーム ID、channel/19:xxx がチャネル ID です。

詳しくは Microsoft Teams のチームID、チャネルIDの確認方法(Qiita / @yamad365 さん) が図付きで分かりやすいです。

③ OpenClaw を再起動する

bash ~/projects/openclaw/start-openclaw.sh

セキュリティチェックリスト

  • pass show msteams/openclaw-app-id が値を返す
  • pass show msteams/openclaw-app-password が値を返す
  • pass show msteams/openclaw-tenant-id が値を返す
  • ~/.openclaw/openclaw.json に平文トークンが含まれていない
    python3 -c "
    import json, pathlib
    cfg = json.loads((pathlib.Path.home() / '.openclaw/openclaw.json').read_text())
    ch = cfg.get('channels', {}).get('msteams', {})
    print('appId:', repr(ch.get('appId', '(なし)')))
    print('appPassword:', repr(ch.get('appPassword', '(なし)')))
    print('tenantId:', repr(ch.get('tenantId', '(なし)')))
    "
    # → 3つとも '' (空文字) であること
    
  • Tailscale Funnel がポート 3978 を公開している
    tailscale funnel status
    
  • Azure Bot Service のメッセージングエンドポイントが正しい URL になっている
  • Teams から 1対1チャット(DM)で話しかけて AI が応答する
  • (グループチャットを使う場合)groupPolicy: "open" を設定し、グループチャットで @OpenClaw に応答がある
  • (チームチャネルを使う場合)チームに Bot を追加し、チャネルで @OpenClaw に応答がある
  • Discord / LINE も引き続き正常に動作している

トラブルシューティング

Bot が応答しない(「Bot is not responding」)

Tailscale Funnel のポート設定か、Azure Bot Service のエンドポイント設定が間違っている可能性があります。

# Funnel がポート 3978 を公開しているか
tailscale funnel status

# コンテナが起動しているか
docker compose -f ~/projects/openclaw/docker-compose.yml \
               -f ~/projects/openclaw/docker-compose.override.yml ps

# Gateway のログを確認
docker compose -f ~/projects/openclaw/docker-compose.yml \
               -f ~/projects/openclaw/docker-compose.override.yml \
               logs --tail=50 openclaw-gateway

Azure Portal の Bot リソース →「構成」→「メッセージングエンドポイント」の URL が https://<hostname>.<tailnet>.ts.net/api/messages になっているか確認してください。

401 Unauthorized — 認証エラー

# 環境変数がコンテナに渡っているか
docker compose -f ~/projects/openclaw/docker-compose.yml \
               -f ~/projects/openclaw/docker-compose.override.yml \
               exec openclaw-gateway env | grep MSTEAMS

3 つとも表示されない場合は start-openclaw.shdocker-compose.override.yml を見直してください。

値が表示されているのに 401 が出る場合は、pass show msteams/openclaw-app-password の値が Azure Portal のクライアントシークレットの「値」(「シークレット ID」ではない)と一致しているか確認します。

「Sorry, this app isn't available」— アプリが見つからない

Teams App マニフェストのアップロードが完了していないか、サイドロードが許可されていません。

  1. Teams →「アプリ」で「OpenClaw」が表示されるか確認
  2. 表示されない場合、テナントのサイドロードポリシーを確認

「access not configured」— ペアリング未承認

これは正常な動作です。ステップ 9 のペアリング承認手順を実行してください。

Cannot find module '@microsoft/agents-hosting'

[msteams] [default] channel exited: Cannot find module '@microsoft/agents-hosting'
Require stack:
- /app/extensions/msteams/src/sdk.ts

msteams の依存パッケージが Docker イメージに含まれていない問題です(#23543)。

v2026.2.23 以降をお使いの場合: update-openclaw.sh で最新版に更新すれば解消されます。

bash ~/projects/openclaw/update-openclaw.sh

v2026.2.22 以前をお使いの場合: ステップ 4 の「msteams の依存パッケージを追加する」を実行して Dockerfile.custom を修正し、カスタムイメージを再ビルドしてください。

msteams が auto-restart を繰り返す(モジュールエラーなし)

ログに Cannot find module が出ず、以下だけが繰り返される場合:

[msteams] starting provider (port 3978)
[msteams] [default] auto-restart attempt 1/10 in 5s

これは monitor.ts の既知バグ(#24374)で、Express サーバーの起動完了を待たずに「終了した」と誤判定される問題です。v2026.3.8 以降で修正されています。

OpenClaw を最新版に更新してください。基礎編⑧ 最新版に保つ更新手順 の更新スクリプトを実行します。

bash ~/projects/openclaw/update-openclaw.sh
クライアントシークレットの有効期限が切れたら

Azure Portal で新しいシークレットを作成し、pass を更新して再起動します。

# 1. Azure Portal で新しいクライアントシークレットを作成
# 2. pass を上書き更新
pass insert --force msteams/openclaw-app-password
# → 新しいシークレットの「値」を貼り付け

# 3. 再起動
bash ~/projects/openclaw/start-openclaw.sh

推奨ローテーション頻度は 90 〜 180 日です。有効期限を 12 ヶ月に設定していても、早めに更新するクセをつけてください。カレンダーにリマインダーを設定しておくと安心です。


おわりに

✅ 今回やったこと:

  1. Teams と LINE の仕組みの違いを理解した(Azure Bot Service が中継する)
  2. Azure Bot Service を作成し、クライアントシークレット認証を設定した
  3. msteams プラグインの依存パッケージを Dockerfile.custom で追加した
  4. openclaw.json に Teams チャンネル設定を追加した
  5. トークン類は pass で管理し、JSON に平文を書かない構成を維持した
  6. Tailscale Funnel でポート 3978 を追加公開した
  7. Teams App マニフェストを作成・アップロードした
  8. Teams からのペアリング承認を行い、AI と会話できるようにした
  9. 1対1・グループチャット・チームチャネルの 3 パターンの使い分けを理解した
  10. RSC 権限による @メンション不要設定を把握した

これで Discord・LINE・Teams の 3 チャネルから AI に話しかけられるようになりました。Teams では 1対1の DM だけでなく、グループチャットやチームチャネルでも Bot を活用できます。Discord は開発者向けのハブ、LINE はプライベートの窓口、Teams は仕事の相棒。用途に応じてチャネルを使い分けることで、AI がより身近な存在になります。


チャネル編:

📚 シリーズ全記事の目次はこちら

Discussion