ラズパイで育てる!自分だけの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 一択です。
ステップ 1: Azure Bot Service を作成する
Azure Portal で Bot リソースを作成します。この手順で Entra ID(旧 Azure AD)のアプリ登録も自動的に作成されるため、手動でのアプリ登録は不要です。
① Azure Portal にアクセスする
- Azure Portal にサインイン
- 上部の検索バーに「Azure Bot」と入力
- 「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 チャネルを有効化する
- Bot リソースの「チャネル」を開く
- 「Microsoft Teams」を選択して有効化
- 利用規約に同意して保存
ステップ 2: クライアントシークレットを作成する
Bot の認証に使うクライアントシークレットを Entra ID で作成します。
- Azure Portal → Entra ID(または Azure Active Directory)
- 「アプリの登録」→ ステップ 1 で自動作成されたアプリを開く
- 左メニュー「証明書とシークレット」→「クライアントシークレット」タブ
- 「新しいクライアントシークレット」をクリック
- 説明:
OpenClaw Teams Bot、有効期限: 12 ヶ月(推奨) - 「追加」をクリック
証明書ベース認証について
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 に以下を追記してください。
ツール編② Playwright で Dockerfile.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)権限 を追加する必要があります。
以下のセクションをマニフェストに追加してください(bots や validDomains と同じ階層)。
// 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 へのアップロード手順:
- Teams を開く →「アプリ」→「アプリの管理」
- 「カスタムアプリをアップロード」を選択
- 作成した zip ファイルをアップロード
- アプリの説明を確認して「追加」
scopes の選択肢について
マニフェストの scopes と openclaw.json のポリシー設定の組み合わせで、Bot がどこで使えるかが決まります。詳しくはステップ 9 以降の「利用シーンを広げる」セクションを参照してください。
チームや組織全体に配布するには
「カスタムアプリをアップロード」で追加した Bot は 自分だけ が使える状態(サイドロード)です。チームのメンバーや組織全体で使いたい場合は、Teams 管理者が組織のアプリカタログに公開する必要があります。
| 配布方法 | 範囲 | 必要な権限 |
|---|---|---|
| サイドロード(本記事の手順) | 自分だけ | ユーザー |
| 組織のアプリカタログに公開 | テナント全体 | Teams 管理者 |
| Teams App Store に公開 | 全世界 | Microsoft の審査通過 |
組織のアプリカタログに公開する手順:
- Teams Admin Center にアクセス(管理者アカウントでサインイン)
- Teams アプリ → アプリの管理 → 新しいアプリをアップロード
- ステップ 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.json の msteams ブロックに dmPolicy と allowFrom の両方を設定してください(ステップ 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 を追加する
- Teams でグループチャットを開く(既存のグループ、または新規作成)
- チャット画面の上部にある 参加者の追加(人のアイコン+)をクリック
- 検索ボックスに Bot 名(「OpenClaw」)を入力
- 表示された Bot を選択して追加
④ Bot に話しかける
グループチャットでは @メンションが必須 です(デフォルト)。
@OpenClaw 今日の天気を教えて
Bot がメンションされたメッセージだけに応答します。メンションなしのメッセージは Bot に配信されないため、他のメンバー同士の会話に Bot が割り込むことはありません。
パターン 3: チームチャネルに Bot を追加する
チーム内のチャネル(#general など)で Bot を使うパターンです。
① openclaw.json の設定
パターン 2 と同じく groupPolicy: "open" が必要です(未設定の場合はパターン 2 の手順を実行)。チャネルでの利用も groupPolicy で制御されます。
② チームに Bot を追加する
- Teams のサイドバーでチーム名の横にある 「…」 をクリック
- 「チームを管理」 を選択
- 「アプリ」 タブを開く
- 「その他のアプリを入手」 をクリック
- 「自分の組織向けに作成」 セクションから「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 に webApplicationInfo と authorization セクションを追加してください(詳細はステップ 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 など他のチャネル: メンション必須のまま
設定の優先順位は チャネル > チーム > グローバル です。より具体的な設定が優先されます。
teams と channels のキーには ディスプレイ名("プロジェクト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.sh と docker-compose.override.yml を見直してください。
値が表示されているのに 401 が出る場合は、pass show msteams/openclaw-app-password の値が Azure Portal のクライアントシークレットの「値」(「シークレット ID」ではない)と一致しているか確認します。
「Sorry, this app isn't available」— アプリが見つからない
Teams App マニフェストのアップロードが完了していないか、サイドロードが許可されていません。
- Teams →「アプリ」で「OpenClaw」が表示されるか確認
- 表示されない場合、テナントのサイドロードポリシーを確認
「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 ヶ月に設定していても、早めに更新するクセをつけてください。カレンダーにリマインダーを設定しておくと安心です。
おわりに
✅ 今回やったこと:
- Teams と LINE の仕組みの違いを理解した(Azure Bot Service が中継する)
- Azure Bot Service を作成し、クライアントシークレット認証を設定した
- msteams プラグインの依存パッケージを
Dockerfile.customで追加した -
openclaw.jsonに Teams チャンネル設定を追加した - トークン類は
passで管理し、JSON に平文を書かない構成を維持した - Tailscale Funnel でポート 3978 を追加公開した
- Teams App マニフェストを作成・アップロードした
- Teams からのペアリング承認を行い、AI と会話できるようにした
- 1対1・グループチャット・チームチャネルの 3 パターンの使い分けを理解した
- RSC 権限による @メンション不要設定を把握した
これで Discord・LINE・Teams の 3 チャネルから AI に話しかけられるようになりました。Teams では 1対1の DM だけでなく、グループチャットやチームチャネルでも Bot を活用できます。Discord は開発者向けのハブ、LINE はプライベートの窓口、Teams は仕事の相棒。用途に応じてチャネルを使い分けることで、AI がより身近な存在になります。
チャネル編:
- ① LINEでAIと話す・Tailscale Funnel
- ② TeamsでAIと話す(本記事)
- ③ @メンションなしで気軽に話しかける
Discussion