2026年6月23日
Slackスラッシュコマンドで自社コマンドを作る — Slack API実装ガイド
スラッシュコマンドで「Slackを操作パネル」にする
Slack Bot・APIで何ができるのかで概観したように、Slack運用の自動化はメッセージ操作・インタラクション・ワークフローの3層から成ります。その入口として最も使いやすいのがスラッシュコマンドです。
/help でFAQが表示される。/report @ユーザー でモデレーターに通知される。/standup でその日のスタンドアップを収集する——こうした仕組みは、参加者が特別なUIを覚えなくても「コマンドを打つだけ」で使えます。Discordと同様、スラッシュコマンドはコミュニティBotの最も重要なインターフェースです。
仕組み:コマンドが実行されると何が起きるか
ユーザーが /hello と入力して送信
→ Slack がリクエストURLにPOSTリクエスト(application/x-www-form-urlencoded)
→ サーバーがSlack署名を検証
→ 3秒以内にレスポンスを返す(または ack())
→ 必要ならresponse_urlや非同期処理で追加投稿
Slack APIはDiscordと違い、コマンドの引数を text フィールドの生テキストとして受け取ります。構造化した入力を受け取りたい場合はモーダル(Block Kitのinput要素)を組み合わせます。
実装:Bolt for JavaScript(Node.js)で作る
Slack公式のBoltフレームワークを使うと、署名検証・イベントルーティング・応答まわりの定型コードを大幅に省けます。
インストール
npm install @slack/bolt
最小構成のスラッシュコマンド
// src/index.ts
import { App } from '@slack/bolt';
const app = new App({
token: process.env.SLACK_BOT_TOKEN,
signingSecret: process.env.SLACK_SIGNING_SECRET,
socketMode: true, // Socket Modeを使う場合
appToken: process.env.SLACK_APP_TOKEN,
});
// /hello コマンドに応答
app.command('/hello', async ({ command, ack, respond }) => {
await ack(); // 3秒以内にack(確認)を返す
await respond({
text: `こんにちは、<@${command.user_id}> さん!`,
response_type: 'in_channel', // チャンネルに表示('ephemeral'にすると本人のみ)
});
});
(async () => {
await app.start();
console.log('Bolt app is running!');
})();
response_type: 'in_channel' にするとチャンネル全体に見える形で返答し、'ephemeral' にすると実行したユーザーのみに見える形で返します。通知・確認系は ephemeral、共有情報は in_channel が基本の使い分けです。
モデレーション通知コマンドの実装例
運営でよく使う「メンバー通報コマンド」の実装例です。
app.command('/report', async ({ command, ack, client, respond }) => {
await ack();
const text = command.text.trim(); // "/report @ユーザー 理由" の "@ユーザー 理由" 部分
// モデレーターチャンネルへ通知
await client.chat.postMessage({
channel: process.env.MODERATOR_CHANNEL_ID!, // #moderatorsチャンネルのID
blocks: [
{
type: 'section',
text: {
type: 'mrkdwn',
text: `🚨 *新しい通報*\n*通報者:* <@${command.user_id}>\n*内容:* ${text || '(理由なし)'}`,
},
},
{
type: 'context',
elements: [
{
type: 'mrkdwn',
text: `チャンネル: <#${command.channel_id}> | 受信: <!date^${Math.floor(Date.now() / 1000)}^{date_pretty} {time}|${new Date().toISOString()}>`,
},
],
},
],
});
// 通報者にだけ確認を返す
await respond({
text: '通報を受け付けました。モデレーターが確認します。',
response_type: 'ephemeral',
});
});
モーダルで構造化された入力を受け取る
/report の引数を自由テキストにすると入力がバラバラになります。モーダルを使うと、フォーム形式で構造化された入力を強制できます。
app.command('/report', async ({ command, ack, client }) => {
await ack();
// モーダルを開く
await client.views.open({
trigger_id: command.trigger_id,
view: {
type: 'modal',
callback_id: 'report_modal',
title: { type: 'plain_text', text: 'メンバーを通報' },
submit: { type: 'plain_text', text: '送信' },
blocks: [
{
type: 'input',
block_id: 'user_block',
element: {
type: 'users_select',
action_id: 'user',
placeholder: { type: 'plain_text', text: '通報するメンバーを選ぶ' },
},
label: { type: 'plain_text', text: '対象メンバー' },
},
{
type: 'input',
block_id: 'reason_block',
element: {
type: 'plain_text_input',
action_id: 'reason',
multiline: true,
placeholder: { type: 'plain_text', text: '状況を詳しく教えてください' },
},
label: { type: 'plain_text', text: '理由・状況' },
optional: true,
},
],
},
});
});
// モーダル送信時の処理
app.view('report_modal', async ({ ack, view, body, client }) => {
await ack();
const userId = view.state.values.user_block.user.selected_user;
const reason = view.state.values.reason_block.reason.value ?? '(理由なし)';
await client.chat.postMessage({
channel: process.env.MODERATOR_CHANNEL_ID!,
text: `🚨 通報: <@${userId}> | 理由: ${reason} | 通報者: <@${body.user.id}>`,
});
});
バイブコーディングで実装する
上記の実装をAIコーディング(Claude等)で生成させる場合のプロンプト例です。
Slack BotのスラッシュコマンドをTypeScriptで作りたい。
フレームワーク: Bolt for JavaScript + Socket Mode
コマンド名: /feedback
動作:
- モーダルを開く(テキストエリア1つ:フィードバック内容・必須)
- モーダル送信後、#feedback チャンネルにBlock Kitで投稿
(送信者名・内容・タイムスタンプ)
- 送信者にはephemeralで「受け付けました」と返す
package.jsonのscriptsと.envの変数名も含めて生成してください。
受け取ったコードで必ず確認すること:
SLACK_SIGNING_SECRET検証(なりすまし防止のための署名検証)- 3秒以内の
ack()(処理が遅い場合の非同期パターン) - エラーハンドリング(チャンネルが見つからない、権限不足など)
よく使うコマンドパターン一覧
| コマンド | 用途 | 返答形式 |
|---|---|---|
/help | FAQや使い方の案内 | Ephemeral(本人のみ) |
/report | 通報・問題申告 | Ephemeral確認 + Moderatorに通知 |
/announce | 管理者が告知文を投稿 | in_channel |
/standup | スタンドアップ収集(Modal) | チャンネルに集計 |
/tag @user | メンバーにタグ付与(権限管理) | Ephemeral確認 |
/digest | 過去N日の投稿サマリ(LLM連携) | Ephemeral |
コミュニティ運用のコードとしての発想全体は「コミュニティ運用をコードで表現する — Slackで実装する3要素」で解説しています。
まとめ
- Slackスラッシュコマンドはapi.slack.comでコマンド名とリクエストURLを登録して使う
- Boltフレームワークで署名検証・ルーティング・応答の定型コードを省ける
ack()は3秒以内必須。重い処理は非同期でrespond()やchat.postMessageで後送り- モーダルを組み合わせると構造化された入力を受け取れ、通報フォームなどに使える
- バイブコーディングでは「コマンド名・動作・ライブラリ・.env変数名」を具体的に伝える
スラッシュコマンドが動くと、次は定期投稿・リアクション自動化・LLM連携へと自動化の幅が広がります。
コミュニティのSlack Bot設計・実装の伴走支援をお探しの方は、六瀬のコミュニティ開発サービスもご覧ください。
関連記事
Contact · 六瀬合同会社
コミュニティの話を、続けませんか。
読みながら「自分のところはどうなんだろう」と思った瞬間があれば、その問いをそのまま送ってください。整理されていなくても、相談の入口を一緒に言葉にしていきます。
よくある質問
- Q. Slackのスラッシュコマンドはどこで設定しますか?
- A. api.slack.com/apps からアプリを作成し、「Slash Commands」メニューで新しいコマンドを追加します。コマンド名(/hello等)・リクエストURL(コマンド実行時にSlackがPOSTするURL)・説明文を設定します。リクエストURLには自作サーバーやCloudflare WorkersのURLを入力します。
- Q. スラッシュコマンドの応答は3秒以内に返さなければいけないのですか?
- A. はい、Slackはコマンド実行から3秒以内の応答を要求します。3秒以内に処理が終わらない場合は「200 OK」とともに空レスポンス(またはack())を即時返し、処理完了後に
response_urlへPOSTするか、Bolt/Socketモードでsay()を使って非同期に投稿します。重い処理(LLM呼び出し・DB検索等)はほぼ必ず非同期処理が必要です。 - Q. スラッシュコマンドに引数を渡せますか?
- A. はい、コマンドの後ろにテキストを入力すると
textパラメータとして受け取れます(例:/report @田中 ルール違反)。Discordと異なり、Slack標準のスラッシュコマンドには型付き引数がないため、textの文字列を自分でパースするか、モーダルを開いて構造化された入力を受け取るのが一般的です。Bolt v4からBlock KitのSuggestionsで入力補完も実装できます。 - Q. 既存のSlack Botアプリにスラッシュコマンドを追加できますか?
- A. できます。api.slack.com/apps から対象アプリを選び、「Slash Commands」から追加するだけです。ただしコマンドを追加した後、ワークスペースにインストールし直す(再認証)か、管理者が承認する手順が必要な場合があります。また、コマンドを処理する実装(リクエストURLのエンドポイント)も追加してください。