openclaw.connect('slack')
/** 24時間365日、全Slackワークスペースチャンネルで利用可能なAIチームメンバー */
## ステップ 1:Slackアプリの作成
## ステップ 2:OpenClawの設定
// 💡 ヒント: パブリックURLがない場合は、ngrokまたはCloudflare Tunnelを使用してポート3000を公開してください
💬 メッセージ例
• @alice 認証リファクタを出荷 — mainにマージ済
• @bob: DB移行テスト完了、14時にデプロイ予定
• @carlos: 新ダッシュボードのデザインレビュー待ちでブロック中
⚠ ブロッカー: @carlos は終業までにデザインの承認が必要です
作り始める前にトランスポートを決める
これは最初の判断であり、後から覆すと高くつきます。Slackアプリのマニフェストが両者で異なるためです。メッセージングとスラッシュコマンドの機能は同等なので、問題はネットワーク環境とゲートウェイの台数だけです。
| 状況 | トランスポート | 理由 |
|---|---|---|
| ノートPCや自宅サーバー上の単一ゲートウェイ | Socket Mode | 受信ポートも公開ホスト名も、維持すべきTLS証明書も不要です。 |
| 社内ネットワークが受信HTTPSを遮断している | Socket Mode | wss-primary.slack.comへの送信WSSだけで済みます。 |
| ロードバランサ配下の複数レプリカ | HTTP | Socket Modeはapp-level tokenを1本の接続に結び付けるため、複数レプリカへの分割は想定形ではありません。 |
| ポリシーで送信WSSが禁止されている | HTTP | Socket Modeがそもそも使えない唯一のケースです。 |
| 既に他サービスでHTTPS終端をしている | HTTP | 差は小さいものの、常時保持するWebSocketを1本減らせます。 |
セルフホストのエージェントではSocket Modeが正しい既定値です。公開された攻撃面をまったく持たないSlack連携が得られます。ソケットの向こう側にいるものがシェルコマンドを実行できる以上、この点は通常のボットより重要です。
Socket Modeの手順
トークンは2種類あり、混同しやすい点です。app-level tokenはWebSocket自体を認可し、bot tokenはメッセージが流れ始めた後の操作を認可します。片方だけ正しいと、接続はできるのに何も起きない状態になります。
# api.slack.com/apps → your app → Basic Information # Generate an App-Level Token with scope: connections:write # Then: OAuth & Permissions → install to workspace → copy the Bot User OAuth Token
`connections:write` スコープこそが、それをbot tokenではなくapp-level tokenにしています。SlackがSocket Modeを提示しない場合、たいていこのスコープが原因です。
{
channels: {
slack: {
mode: "socket",
appToken: { source: "env", id: "SLACK_APP_TOKEN" },
botToken: { source: "env", id: "SLACK_BOT_TOKEN" },
},
},
}どちらもSecretRefにします。SlackのトークンはIPに紐づかない単なるBearer資格情報で、漏れればローテーションするまで誰でも使えます。設定ファイルには置かないでください。
# Minimum bot scopes: # app_mentions:read channels:history channels:read # chat:write commands groups:history # groups:read im:history im:read # users:read
この一覧は提案ではなく下限です。特に `channels:history` が欠けると、投稿はできるが読めないボットになります。権限の問題ではなく、エージェントが文脈を無視しているように見えます。
openclaw config patch --file ./slack.socket.json5 openclaw gateway restart openclaw gateway status
見るべきは `gateway status` です。app-level tokenの設定ミスは接続時に失敗し、その失敗はSlack側ではなくここにしか現れません。
HTTPモードと、誰もが踏むIDの罠
HTTPモードが必要だと判断した場合、設定の違いは2点です。app-level tokenの代わりにsigning secretを使い、Slackが実際に到達できるURLが必要になります。それ以降の挙動は同一です。
{
channels: {
slack: {
mode: "http",
botToken: { source: "env", id: "SLACK_BOT_TOKEN" },
signingSecret: { source: "env", id: "SLACK_SIGNING_SECRET" },
webhookPath: "/slack/events",
},
},
}signing secretは、リクエストが本当にSlackから来たことを検証する手段です。検証がなければ、そのWebhookパスはエージェントに指示を出せる無認証のエンドポイントになります。省略はゲートウェイを開放するのと同等だと考えてください。
# Channel allowlists are keyed by Slack ID, never by name. # Right-click a channel → View channel details → the ID is at the bottom. # # "C12345678" correct # "#engineering" silently matches nothing
`#名前` をキーにしてもエラーにはならず、単に何にも一致しません。結果として、有効化したかったまさにそのチャンネルでエージェントが沈黙します。Slack設定で最も多い間違いです。
共有ワークスペースに入れる前に決めておくこと
- ✗channels:historyを持つボットは、そのチャンネルに投稿された内容をすべて読めます。エージェントの導入を検討するずっと前に書かれたメッセージも含みます。
- ✗DMのペアリングは既定で承認が必要です。dmPolicyを"open"にしallowFrom: ["*"]を設定すると、ワークスペースの全員がコマンドを実行できるエージェントへの私的な経路を得ます。
- ✗Slackワークスペースには通常、他人のデータが含まれます。「セルフホストだからプライベート」は、エージェントが共有チャンネルを読み始めた時点で成り立たなくなります。
- ✗グループDMはdm.groupEnabledを設定しない限り無効です。連携が壊れていると判断する前に知っておく価値があります。