Slack APIとbotの作り方:Slackアプリを作ってメッセージを送る・受け取る

公開 書いた人 大林 諒

Slack(スラック)のbotは、Slack APIを使って自分の会社用に作る「Slackアプリ」の一種です。決まったチャンネルに知らせを送るだけならIncoming Webhookで足りますが、送ったメッセージにボタンを付けて押した人を記録する、メンションされたら返事をする、スラッシュコマンドで社内の情報を引く、といったことをしたくなるとbotが要ります。この記事では、社員20名ほどのWeb制作会社「サンプルデザイン」が、サーバー監視の通知に「対応する」ボタンを付けるbotを作るまでを、アプリの作成・スコープ・トークン・送信・受信・トークンの管理の順に書きます。読み終わると、自作するか、n8nやワークフロービルダーで済ませるかを判断でき、自作する場合は最初の1本を動かして、担当が替わっても止まらない形で置けるようになります。前提はプロプランのワークスペースで、エンジニアが1人以上いることです。

この記事の内容
  1. 先に決めること
  2. トークンの種類と、どれを使うか
  3. Slackアプリを作ってトークンを取る
  4. メッセージを送る(chat.postMessage)
  5. メッセージを受け取る(Events APIとSocket Mode)
  6. スラッシュコマンドとボタンの考え方
  7. トークンの管理と、作った人が辞めたとき
  8. 応用
  9. できないことと、その代わり
  10. よく詰まるところ
  11. 次にやること

先に決めること

本当に自作が要るか

Slackアプリを自作すると、動かすサーバーやプログラムの面倒を自社で見続けることになります。サンプルデザインのような小さな会社では、作ること自体より、作った人が忙しくなったり辞めたりしたあとに直せる人がいなくなることのほうが問題になります。先に、自作しないで済む手を当てます。

やりたいこと自作しないで済む手自作が要る場面
外のシステムの異常をチャンネルに流すIncoming Webhook通知に対する操作を受けたい
申請・日報をフォームで集めて担当に回すワークフロービルダー社内の業務システムの値を引いて判断したい
kintoneやスプレッドシートの更新を知らせるn8nや各サービスのSlack連携大量の件数を細かい条件でさばきたい
毎週決まった時刻に知らせる/remind やワークフロービルダーのスケジュールのトリガー送る中身を毎回ほかのシステムから組み立てたい
通知にボタンを付け、押した人を記録するワークフロービルダーのボタンで足りることもある(記録は押した人がスレッドに書く運用)押したあとに外のシステムを書き換えたい
メンションされたら返事をするなし返事の中身を自分で決めたい

この表で「自作しないで済む手」で足りるなら、そちらを使います。n8nでつなぐ方法はkintone・Salesforce・n8nの連携の記事、フォームで集める方法はワークフロービルダーの記事で書いています。

送るだけか、受け取るか

botの作りは、送るだけか、Slackで起きたことを受け取るかで大きく変わります。送るだけなら、トークンを1つ取ってWeb APIを呼ぶだけです。受け取るなら、Slackからの知らせを受ける仕組み(Events APIかSocket Mode)と、それを常に動かしておく場所が要ります。サンプルデザインのbotは、監視の通知を送り、ボタンが押されたのを受け取るので、両方が要ります。

誰がアプリを持つか

Slackアプリは作った人の開発者アカウントにひもづいて作られます。作った人が辞めると、アプリの設定画面に誰も入れなくなることがあります。アプリには共同で管理する人を足せるので、最初から作ったエンジニアCのほかに、エンジニアのもう1人と総務Eを入れておきます。社内用アプリの共同管理者の扱いは、2026年10月時点のヘルプセンターで確かめてください。

どこで動かすか

受け取る仕組みには、インターネットから届くURLを用意するやり方(HTTP)と、こちらからSlackにつなぎに行くやり方(Socket Mode)があります。公式は、社内のネットワークの中で動かしたい、公開のURLを出したくない場合にSocket Modeが役に立つと書いています。社内用のbotを1つ作るだけなら、Socket Modeで始めるのが手軽です。

トークンの種類と、どれを使うか

Slack APIを呼ぶときは、トークンを付けて「誰として呼ぶか」を伝えます。2026年10月時点の公式では、主に次の種類があります。

種類頭の文字何を表すかサンプルデザインでの使い方
Botトークンxoxb-ワークスペースに入れたアプリのbot送る・受け取るのほとんどをこれで行う
ユーザートークンxoxp-ワークスペースのメンバー本人使わない
Appレベルトークンxapp-組織をまたいだアプリそのものSocket Modeでつなぐときに使う
設定用トークン–人とワークスペースにひもづく、アプリを作る・設定するためのもの使わない
ワークフロートークンxwfp-ワークフローの中で使う短命のトークン使わない

ユーザートークンで書き込むと、その人が書いたように見えます。botトークンは特定の人から独立していて、公式も、インストールした人のアカウントが停止されてもアプリが入ったままでいられると書いています。社内のbotは、botトークンを基本にします。ユーザートークンは、その人の権限でしか取れない情報を扱うときだけに限ります。

スコープの決め方

スコープは、そのトークンで何をしてよいかの許可の一覧です。多く付けるほど漏れたときの被害が大きくなるので、使うものだけを付けます。

やりたいこと付けるスコープ(botトークン)
botが入っているチャンネルに送るchat:write
botが入っていない公開チャンネルにも送るchat:write.public
送るときに名前やアイコンを変えるchat:write.customize
チャンネルの一覧を取るchannels:read
公開チャンネルのメッセージを受け取る・読むchannels:history
メンションされたことを受け取るapp_mentions:read
スラッシュコマンド・ショートカットを使うcommands
メンバーの名前を引くusers:read

サンプルデザインの監視botは、chat:write・app_mentions:read の2つで始めます。ボタンが押されたことを受け取るのに追加のスコープは要りません。新しいアプリは最初から全部の公開チャンネルに送れるわけではなく、送りたいチャンネルにbotを招待するか、chat:write.public を付けます。招待で済むなら招待にします。

Slackアプリを作ってトークンを取る

手順は2026年10月時点の開発者向け設定画面(api.slack.com/apps)です。設定画面は英語表示です。

  1. ブラウザでSlackにログインした状態で https://api.slack.com/apps?new_app=1 を開く
  2. 「Blank app」を選び、「Continue」を押す
  3. 「App Name」に 監視bot と入れる
  4. 「Workspace」で「サンプルデザイン」を選ぶ
  5. 「Create」を押す
api.slack.com/apps の新規作成で「Blank app」を選び、App Name と Workspace を入れたところ
api.slack.com/apps の新規作成で「Blank app」を選び、App Name と Workspace を入れたところ

次にスコープを付けて、ワークスペースに入れます。

  1. 左のメニューで「OAuth & Permissions」を開く
  2. 「Scopes」まで下に進む
  3. 「Bot Token Scopes」の「Add an OAuth Scope」を押し、chat:write を足す
  4. 同じように app_mentions:read を足す
  5. 画面の上に戻り、「Install to Workspace」を押す
  6. 許可の画面で「Allow」を押す
  7. インストールのあとに画面に出る xoxb- で始まるトークンを、社内のパスワード管理に保存する
「OAuth & Permissions」の「Bot Token Scopes」に chat:write と app_mentions:read が並んでいるところ
「OAuth & Permissions」の「Bot Token Scopes」に chat:write と app_mentions:read が並んでいるところ
インストール後にbotトークンが出ているところ(値は伏せる)
インストール後にbotトークンが出ているところ(値は伏せる)

ワークスペースでアプリのインストールに管理者の承認が要るようにしている場合は、6で承認の依頼になります。承認の設定はセキュリティ設定の記事で書いています。スコープをあとから足したときは、もう一度インストールし直さないと新しいスコープが効きません。

最後に、送り先のチャンネルにbotを招待します。#log-サーバー監視 で次のように打ちます。

/invite @監視bot

メッセージを送る(chat.postMessage)

送るときは chat.postMessage を呼びます。必須なのは、トークンと送り先の channel です。channel にはチャンネル名より、チャンネルを開いたときのURLの最後の部分(C で始まるID)を使うほうが、名前を変えても壊れません。

curl -X POST https://slack.com/api/chat.postMessage \
  -H 'Authorization: Bearer xoxb-xxxxxxxx' \
  -H 'Content-type: application/json; charset=utf-8' \
  --data '{"channel":"C0000000000","text":"監視botのテスト送信です"}'

うまくいくと、次のような形で返ってきます。ts は送ったメッセージを特定する値で、スレッドへの返信や書き換えに使います。

{
  "ok": true,
  "channel": "C0000000000",
  "ts": "1761875520.000100",
  "message": { "text": "監視botのテスト送信です" }
}

送れなかったときは "ok": false と error に理由が入ります。

エラー意味直し方
not_in_channelbotがチャンネルに入っていない/invite で招待するか chat:write.public を足す
channel_not_foundchannel の値が違うチャンネルIDを確かめる
missing_scope必要なスコープが無いスコープを足してインストールし直す
invalid_authトークンが正しくない保存したトークンを確かめる
is_archivedチャンネルがアーカイブ済み送り先を変える
restricted_actionワークスペースの設定で投稿が制限されているチャンネルの投稿権限を確かめる
rate_limited送りすぎ間をあけて送り直す

ボタン付きで送り、スレッドに返信する

監視の通知に「対応する」ボタンを付けます。blocks を使うときも text は入れます。公式も、blocks を使うときの text は通知に出る代わりの文字として使われると書いています。

curl -X POST https://slack.com/api/chat.postMessage \
  -H 'Authorization: Bearer xoxb-xxxxxxxx' \
  -H 'Content-type: application/json; charset=utf-8' \
  --data '{
    "channel": "C0000000000",
    "text": "サーバー監視: sample-design.example が応答しません",
    "blocks": [
      {"type": "section", "text": {"type": "mrkdwn", "text": ":rotating_light: sample-design.example が応答しません"}},
      {"type": "actions", "elements": [
        {"type": "button", "text": {"type": "plain_text", "text": "対応する"}, "action_id": "take_incident"}
      ]}
    ]
  }'

復旧したときは、最初の通知の ts を thread_ts に入れて送ると、同じスレッドにまとまります。Incoming Webhookでは ts が返ってこないので、これはbotでないとできません。

{ "channel": "C0000000000", "thread_ts": "1761875520.000100", "text": ":white_check_mark: 復旧しました(09:31)" }
監視botの通知に「対応する」ボタンが付き、復旧の知らせがスレッドに入っているところ
監視botの通知に「対応する」ボタンが付き、復旧の知らせがスレッドに入っているところ

送る量には上限があります。公式では、chat.postMessage は1つのチャンネルに1秒1件ほどで、ワークスペース全体でも1分に数百件までの上限があります。超えるとHTTPの429と、待つ秒数を示す Retry-After が返ります。text は4,000文字までを目安にし、40,000文字を超えると切り詰められます。

メッセージを受け取る(Events APIとSocket Mode)

Slackで起きたこと(メンションされた・メッセージが書かれた・ボタンが押された)は、Events APIや操作の知らせとしてアプリに届きます。届け方は2つです。

比べるところHTTP(Request URL)Socket Mode
つなぎ方Slackがこちらの公開URLに送ってくるこちらからSlackにWebSocketでつなぐ
用意するものインターネットから届くHTTPSのURLAppレベルトークン(connections:write)
社内のネットワークの中で動かす難しいできる
Slack Marketplaceで公開できる2026年10月時点ではできない
同時につなげる数関係ない10本まで
向く場面クラウドに置いて外部にも配るアプリ社内用のbot

どちらでも、受け取ったら急いで返事をする必要があります。Events APIは3秒以内にHTTPの2xxを返すよう求めていて、返さないと最大3回送り直してきます。送り直しには x-slack-retry-num という見出しが付くので、重い処理を2重に走らせないよう、受け取ったらすぐ返事をして、処理は後で行う作りにします。届くイベントの数にも上限があり、公式では1つのワークスペースで1つのアプリあたり60分に30,000件までです。

メンションを受け取る app_mention は、botが入っていないチャンネルでメンションされても届きません。公式も、会話に参加していない(招待されていない)アプリはイベントを受け取らないと書いています。

Socket Modeをオンにする

  1. アプリ設定の「Basic Information」を開き、「App-Level Tokens」まで下に進む
  2. 「Generate Token and Scopes」を押し、名前を付けて connections:write を足し、トークンを作る
  3. できた xapp- で始まるトークンを、社内のパスワード管理に保存する
  4. 左のメニューで「Socket Mode」を開き、「Enable Socket Mode」をオンにする
  5. 「Event Subscriptions」を開いてオンにし、「Subscribe to bot events」に app_mention を足す
  6. ボタンなどの操作を受け取る設定がオンになっているか、アプリ設定の画面で確かめる
  7. 「Install App」からインストールし直す
「Basic Information」の「App-Level Tokens」で connections:write を付けてトークンを作るところ
「Basic Information」の「App-Level Tokens」で connections:write を付けてトークンを作るところ
「Socket Mode」で「Enable Socket Mode」をオンにしたところ
「Socket Mode」で「Enable Socket Mode」をオンにしたところ
「Event Subscriptions」の「Subscribe to bot events」に app_mention が入っているところ
「Event Subscriptions」の「Subscribe to bot events」に app_mention が入っているところ

Boltを使うか

Boltは、Slackが用意しているアプリ作りの道具(JavaScript・Python・Java)です。署名の確かめ、3秒以内の返事、Socket Modeのつなぎ直しといった、自分で書くとつまずきやすい部分を引き受けてくれます。公式のSocket Modeの説明でも、BoltかSlackのSDKを使うことを勧めています。受け取る処理があるbotは、Boltを使わない理由がなければBoltで書きます。送るだけなら、curlや各言語のHTTPの呼び出しで十分です。

サンプルデザインの監視botを、PythonのBoltとSocket Modeで書くと次のようになります。

pip install slack_bolt
export SLACK_BOT_TOKEN=xoxb-xxxxxxxx
export SLACK_APP_TOKEN=xapp-xxxxxxxx
import os
from slack_bolt import App
from slack_bolt.adapter.socket_mode import SocketModeHandler

app = App(token=os.environ["SLACK_BOT_TOKEN"])

@app.action("take_incident")
def take_incident(ack, body, client):
    ack()  # まず受け取ったことを返す
    user = body["user"]["id"]
    channel = body["channel"]["id"]
    ts = body["message"]["ts"]
    client.chat_update(
        channel=channel,
        ts=ts,
        text=f"対応中: <@{user}>",
        blocks=[{"type": "section", "text": {"type": "mrkdwn",
                 "text": f":construction: <@{user}> が対応しています"}}],
    )
    client.chat_postMessage(channel=channel, thread_ts=ts,
                            text=f"<@{user}> が対応を始めました")

@app.event("app_mention")
def on_mention(event, say):
    say(text="障害時の手順はこちらです: <https://example.com/runbook|障害時の手順>",
        thread_ts=event["ts"])

if __name__ == "__main__":
    SocketModeHandler(app, os.environ["SLACK_APP_TOKEN"]).start()

ボタンを押すと、通知の本文が「エンジニアCが対応しています」に書き換わり、スレッドに対応開始が残ります。押した人が分かるので、深夜に2人が同じ障害を見て手を動かす、ということが減ります。

「対応する」を押したあと、通知が「○○が対応しています」に書き換わったところ
「対応する」を押したあと、通知が「○○が対応しています」に書き換わったところ

このプログラムは、止めるとbotも止まります。社内のサーバーや常に動かしておけるクラウドに置き、止まったら気づけるようにしておきます。エンジニアのパソコンで動かしたままにすると、そのパソコンを閉じた時点で止まります。

スラッシュコマンドとボタンの考え方

スラッシュコマンドは、/障害 のように打つとアプリに知らせが届く入口です。アプリ設定の「Slash Commands」で「Create New Command」を押し、「Command」「Request URL」「Short Description」「Usage Hint」を入れて作ります。スコープは commands を付けます。Socket Modeで動かすときは、Request URLの代わりにSocket Modeのつなぎで届きます。

公式では、コマンドを受け取ったら3,000ミリ秒以内にHTTPの200を返す必要があり、返さないと打った人に operation_timeout のエラーが出ます。返事は何もしなければ打った本人にだけ見える形(ephemeral)になり、response_type を in_channel にするとチャンネルの全員に見えます。

入口向く使い方サンプルデザインでの例
スラッシュコマンド打つ人が決まっていて、引数を付けて呼ぶ/障害 sample-design.example で手順と過去の対応を出す
ボタン通知に対して、次の操作を1回で選ぶ「対応する」「誤報」
メンション会話の流れで気軽に呼ぶ@監視bot で手順を返す
ショートカットメッセージに対する操作を出す通知を案件の管理表に記録する

実際に運用していると、スラッシュコマンドは打ち方を覚えてもらえず使われなくなりがちです。通知にボタンを付けて「押すだけ」にするほうが、小さな会社では定着します。スラッシュコマンドは、エンジニアのように毎日使う人だけが使うものに絞ります。

トークンの管理と、作った人が辞めたとき

トークンは、そのbotとして何でもできる鍵です。公式も、トークンを公開のバージョン管理に入れず、環境変数から読むように勧めています。

置き場所向くか
社内のパスワード管理(1Passwordなど)原本の置き場所として向く
動かすサーバーの環境変数・シークレット向く
コードの中・GitHubのリポジトリ向かない
Slackのチャンネル・DM・スプレッドシート向かない

漏れたかもしれないときは、アプリ設定でトークンを無効にして作り直し、動かしている場所のトークンを入れ替えます。トークンを定期的に入れ替える「トークンのローテーション」も用意されていますが、公式では一度オンにするとオフに戻せません。入れ替えの仕組みを作れないうちはオンにしません。

作った人が辞めるときに確かめることは次のとおりです。

  1. アプリの共同管理者に、残る人が2人以上入っているか確かめる
  2. トークンの原本が、個人の場所ではなく社内のパスワード管理にあるか確かめる
  3. 動かしているサーバーやクラウドのアカウントが、個人ではなく会社のものか確かめる
  4. botトークンで動いているか確かめる(ユーザートークンで動かしている部分は、その人に頼らない形に作り直す)
  5. 管理の一覧表に「アプリ名・何をするか・動かしている場所・共同管理者」を書いておく

botトークンは、インストールした人が停止されてもアプリが入ったままでいられると公式にあります。一方で、設定画面に入れる人がいなくなると、スコープの変更もトークンの作り直しもできません。共同管理者の追加は、辞めると決まってからではなく、作った日に済ませます。

アプリ設定の共同管理者の欄に3人が並んでいるところ
アプリ設定の共同管理者の欄に3人が並んでいるところ

応用

AIで返事をするbot

「slack bot ai」で調べる人の多くは、ChatGPTのような生成AIに答えさせるbotを作りたい人です。作りは上のbotと同じで、メンションを受け取ったら外部の生成AIのAPIに質問を送り、返ってきた文を say() で返します。公式の開発者向けドキュメントにもAIのエージェントを作るための章があり、エージェント向けの画面の部品が用意されています。社内の文書や問い合わせの中身を外部のAIに送ることになるので、送ってよい情報の範囲を先に決めます。Slackの中で要約や検索をしたいだけなら、自作する前にSlackのAI機能で足りるかを確かめます。AI機能のプランごとの差は2026年10月時点の料金ページで確かめてください。

リマインダーのbot

決まった時刻に決まった文を送るだけなら、bot を作る必要はありません。/remind #team-direction "案件の管理表を更新" every Monday at 9am のように、Slackの標準のリマインダーで済みます(内容は日本語、日時は英語で書きます)。書き方はリマインダーの記事で書いています。送る中身を毎回スプレッドシートやkintoneから組み立てたいときだけ、n8nの定時実行か、botを定時に動かす作りにします。

Slackbotとの違い

Slackが用意している「Slackbot」は、リマインダーなどの通知を送ります。これはSlackが用意しているもので、この記事で作るbotとは別物です。自作のbotは、作ったアプリの名前とアイコンで投稿します。

できないことと、その代わり

できないこと代わりの手
botが入っていないチャンネルのメッセージを受け取る必要なチャンネルにだけ招待する
botが入っていないチャンネルでメンションに反応する招待してから使ってもらう
3秒を超える処理をそのまま返事にするすぐ受け取りを返し、後から別のメッセージで結果を送る
Socket ModeのアプリをSlack Marketplaceで公開する外部に配るならHTTPで作る
過去の会話をまとめて保管・監査する台帳や記録はkintone・専用システムに残す
作った人がいなくても勝手に直る共同管理者・一覧表・会社のアカウントで運用する

Slackのbotは「知らせて、押してもらう」のは得意ですが、申請の承認の履歴を何年も残す、案件の記録を検索できる形で保つ、といった仕事には向きません。承認や記録が要るものはkintoneやSalesforceに置き、Slackには知らせとボタンだけを出します。

よく詰まるところ

症状原因直し方
not_in_channel で送れないbotがチャンネルに入っていない/invite @監視bot で招待する
スコープを足したのに missing_scopeインストールし直していない「Install App」から入れ直す
メンションしても反応しないbotがチャンネルにいない・app_mention を購読していない招待し、「Subscribe to bot events」を確かめる
同じ処理が2回、3回走る3秒以内に返事をせず送り直された受け取ったらすぐ返し、処理は後に回す
スラッシュコマンドで operation_timeout3,000ミリ秒以内に200を返していない先に受け取りを返し、結果は後から送る
ボタンを押しても何も起きない操作を受け取る設定がオフ・action_id の不一致設定と action_id を確かめる
夜になるとbotが止まるエンジニアのパソコンで動かしていたサーバーやクラウドに置く
Socket ModeでつながらないAppレベルトークンに connections:write が無いスコープを付けたトークンを作り直す
作った人が辞めて設定を直せない共同管理者がいなかった管理者に相談し、次からは作った日に共同管理者を足す
通知に何も出ないblocks だけで text を入れていないtext も入れる
「Event Subscriptions」の画面で、購読しているbotイベントの一覧を確かめているところ
「Event Subscriptions」の画面で、購読しているbotイベントの一覧を確かめているところ

次にやること

botを作る前に、送るだけで足りるならSlackのIncoming Webhook:外のシステムからチャンネルに通知を送るの方法のほうが早く済みます。kintoneやSalesforceの更新を知らせて承認につなぐなら、自作より先にSlackとkintone・Salesforce・n8nの連携:業務システムの通知と承認をつなぐを読んでください。フォームで集めて担当に回すだけなら、Slackのワークフロービルダー:作り方と、日報・申請・問い合わせ受付の例で作れます。作ったアプリを誰が入れてよいか、外部のアプリをどこまで許すかは、Slackのセキュリティ設定:2段階認証・外部共有・アプリの許可・データの保持で決めます。

あわせて読む