mcpField
S
slack-bot

slack-bot

github.com/openclaudia生産性722429 回インストール1 週間前に更新
リポジトリ

slack-bot について

Incoming Webhooks または Slack Web API を使って、Slack にメッセージや整形済みコンテンツを送るスキルです。Block Kit の告知やレポート、スレッド返信、ファイル投稿などの例を提供します。

主な機能

  1. 01Webhook と Web API による投稿
  2. 02Block Kit メッセージの整形
  3. 03スレッド返信とメッセージ更新
  4. 04チャンネル一覧とファイル投稿
  5. 05Slack mrkdwn の書式リファレンス

活用シーン

  1. 01整形したマーケティングレポートの投稿
  2. 02チャンネルでの告知共有
  3. 03既存メッセージへのスレッド返信
  4. 04Slack へのレポートファイル投稿

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/openclaudia/openclaudia-skills --skill slack-bot

インストール後、Claude Code で/slack-botを入力して読み込まれたか確認します。

詳細

Slack ボット

Incoming Webhook または Slack Web API を使用して、Slack チャンネルにメッセージやリッチコンテンツを送信します。 Block Kit を使って、書式付きのお知らせ、マーケティングレポート、メトリクスダッシュボード、コミュニティの最新情報を作成できます。

前提条件

.env、.env.local、または ~/.claude/.env.global に SLACK_WEBHOOK_URL または SLACK_BOT_TOKEN のいずれかを設定する必要があります。

source ~/.claude/.env.global 2>/dev/null
source .env 2>/dev/null
source .env.local 2>/dev/null

if [ -n "$SLACK_WEBHOOK_URL" ]; then
  echo "SLACK_WEBHOOK_URL is set. Webhook mode available."
elif [ -n "$SLACK_BOT_TOKEN" ]; then
  echo "SLACK_BOT_TOKEN is set. Web API mode available."
else
  echo "Neither SLACK_WEBHOOK_URL nor SLACK_BOT_TOKEN is set."
  echo "See the Setup Guide below to configure Slack credentials."
fi

どちらの変数も設定されていない場合は、以下のセットアップガイドに従うようユーザーに案内してください。


セットアップガイド

オプション A:Incoming Webhook(簡単)

Incoming Webhook はメッセージを投稿する最も手軽な方法です。OAuth スコープは不要で、単一のチャンネルに限定されます。

  1. https://api.slack.com/apps にアクセスし、Create New App > From scratch をクリックします。
  2. アプリ名(例:「Marketing Bot」)を入力し、ワークスペースを選択します。
  3. 左サイドバーで Incoming Webhooks をクリックし、切り替えボタンを On にします。
  4. 下部にある Add New Webhook to Workspace をクリックします。
  5. 投稿先のチャンネルを選択し、Allow をクリックします。
  6. Webhook URL(https://hooks.slack.com/services/... で始まる)をコピーします。
  7. 環境に追加します。
echo 'SLACK_WEBHOOK_URL=https://hooks.slack.com/services/T.../B.../xxxx' >> .env

制限事項: 1 チャンネルにつき Webhook は 1 つです。プログラムからメッセージの読み取り、チャンネルの一覧表示、スレッドへの返信はできません(事前の API レスポンスから thread_ts を取得しておく必要があります)。

オプション B:ボットトークン(全機能)

ボットトークンを使うと、Slack Web API の全機能にアクセスできます。ボットが参加している任意のチャンネルへの投稿、スレッドへの返信、チャンネルの一覧表示、ファイルのアップロードなどが可能です。

  1. https://api.slack.com/apps にアクセスし、Create New App > From scratch をクリックします。
  2. アプリ名を入力し、ワークスペースを選択します。
  3. 左サイドバーで OAuth & Permissions をクリックします。
  4. Bot Token Scopes で、次のスコープを追加します。
    • chat:write - メッセージの投稿
    • chat:write.public - 参加していないチャンネルへの投稿
    • channels:read - パブリックチャンネルの一覧表示
    • files:write - ファイルのアップロード(任意。画像やレポート用)
    • reactions:write - 絵文字リアクションの追加(任意)
  5. 上部の Install to Workspace をクリックし、認可します。
  6. Bot User OAuth Token(xoxb- で始まる)をコピーします。
  7. 環境に追加します。
echo 'SLACK_BOT_TOKEN=xoxb-your-token-here' >> .env
  1. ボットが投稿するチャンネルで、/invite @YourBotName と入力してボットを招待します。

任意: 利便性のため、デフォルトのチャンネルを設定できます。

echo 'SLACK_DEFAULT_CHANNEL=#marketing' >> .env

方法 1:Incoming Webhook

シンプルなテキストメッセージを送信する
curl -s -X POST "$SLACK_WEBHOOK_URL" \
  -H "Content-Type: application/json" \
  -d '{
    "text": "Hello from the marketing bot!"
  }'
ユーザー名とアイコンを上書きしてメッセージを送信する
curl -s -X POST "$SLACK_WEBHOOK_URL" \
  -H "Content-Type: application/json" \
  -d '{
    "text": "New blog post published!",
    "username": "Marketing Bot",
    "icon_emoji": ":mega:"
  }'
Block Kit を使ってメッセージを送信する(Webhook)
curl -s -X POST "$SLACK_WEBHOOK_URL" \
  -H "Content-Type: application/json" \
  -d '{
    "blocks": [
      {
        "type": "header",
        "text": {
          "type": "plain_text",
          "text": "New Product Launch"
        }
      },
      {
        "type": "section",
        "text": {
          "type": "mrkdwn",
          "text": "*Product X* is now live! Check out the announcement."
        }
      },
      {
        "type": "divider"
      },
      {
        "type": "section",
        "text": {
          "type": "mrkdwn",
          "text": "Read the full announcement on our blog."
        },
        "accessory": {
          "type": "button",
          "text": {
            "type": "plain_text",
            "text": "Read More"
          },
          "url": "https://example.com/blog/launch"
        }
      }
    ]
  }'

方法 2:Slack Web API(ボットトークン)

Web API を使うと、メッセージ配信、スレッド、チャンネル管理などをきめ細かく制御できます。

API のベース URL

すべてのリクエストは、ヘッダー Authorization: Bearer {SLACK_BOT_TOKEN} を指定して https://slack.com/api/ に送信します。

チャンネルにメッセージを投稿する
curl -s -X POST "https://slack.com/api/chat.postMessage" \
  -H "Authorization: Bearer ${SLACK_BOT_TOKEN}" \
  -H "Content-Type: application/json" \
  -d '{
    "channel": "#marketing",
    "text": "Weekly metrics report is ready!",
    "blocks": [
      {
        "type": "header",
        "text": {
          "type": "plain_text",
          "text": "Weekly Marketing Metrics"
        }
      },
      {
        "type": "section",
        "text": {
          "type": "mrkdwn",
          "text": "Here are the numbers for this week."
        }
      }
    ]
  }'

レスポンスには、メッセージを識別する ts(タイムスタンプ)フィールドが含まれます。スレッドへの返信に使うため、この値を保存しておきます。

# Post and capture the message timestamp for threading
RESPONSE=$(curl -s -X POST "https://slack.com/api/chat.postMessage" \
  -H "Authorization: Bearer ${SLACK_BOT_TOKEN}" \
  -H "Content-Type: application/json" \
  -d '{
    "channel": "#marketing",
    "text": "Thread parent message"
  }')

MESSAGE_TS=$(echo "$RESPONSE" | python3 -c "import json,sys; print(json.load(sys.stdin).get('ts',''))")
echo "Message timestamp: $MESSAGE_TS"
スレッドに返信する

thread_ts パラメーターを使って、既存のスレッドに返信します。

curl -s -X POST "https://slack.com/api/chat.postMessage" \
  -H "Authorization: Bearer ${SLACK_BOT_TOKEN}" \
  -H "Content-Type: application/json" \
  -d "{
    \"channel\": \"#marketing\",
    \"thread_ts\": \"${MESSAGE_TS}\",
    \"text\": \"This is a threaded reply with additional details.\"
  }"

返信をチャンネルにもブロードキャストして(メインの会話にも表示して)配信するには、"reply_broadcast": true を追加します。

既存のメッセージを更新する
curl -s -X POST "https://slack.com/api/chat.update" \
  -H "Authorization: Bearer ${SLACK_BOT_TOKEN}" \
  -H "Content-Type: application/json" \
  -d "{
    \"channel\": \"#marketing\",
    \"ts\": \"${MESSAGE_TS}\",
    \"text\": \"Updated message content.\",
    \"blocks\": []
  }"
メッセージを削除する
curl -s -X POST "https://slack.com/api/chat.delete" \
  -H "Authorization: Bearer ${SLACK_BOT_TOKEN}" \
  -H "Content-Type: application/json" \
  -d "{
    \"channel\": \"#marketing\",
    \"ts\": \"${MESSAGE_TS}\"
  }"
パブリックチャンネルを一覧表示する

投稿先のチャンネルを見つける際に便利です。

curl -s "https://slack.com/api/conversations.list?types=public_channel&limit=100" \
  -H "Authorization: Bearer ${SLACK_BOT_TOKEN}" | \
  python3 -c "
import json, sys
data = json.load(sys.stdin)
for ch in data.get('channels', []):
    members = ch.get('num_members', 0)
    print(f\"#{ch['name']}  |  Members: {members}  |  ID: {ch['id']}\")
"
チャンネルにファイルをアップロードする
curl -s -X POST "https://slack.com/api/files.uploadV2" \
  -H "Authorization: Bearer ${SLACK_BOT_TOKEN}" \
  -F "[email protected]" \
  -F "filename=weekly-report.pdf" \
  -F "channel_id=C0123456789" \
  -F "initial_comment=Here is this week's marketing report."
絵文字リアクションを追加する
curl -s -X POST "https://slack.com/api/reactions.add" \
  -H "Authorization: Bearer ${SLACK_BOT_TOKEN}" \
  -H "Content-Type: application/json" \
  -d "{
    \"channel\": \"C0123456789\",
    \"timestamp\": \"${MESSAGE_TS}\",
    \"name\": \"white_check_mark\"
  }"

Slack Block Kit リファレンス

Block Kit は、リッチでインタラクティブなメッセージを作成するための Slack の UI フレームワークです。メッセージはブロックの配列で構成され、それぞれに固有のタイプと構造があります。

ブロックタイプ
ブロックタイプ目的mrkdwn に対応
header大きく太字のタイトルテキストいいえ(plain_text のみ)
sectionテキストと任意のアクセサリーを含む主要コンテンツブロックはい
divider水平の区切り線該当なし
image代替テキスト付きの全幅画像該当なし
contextメタデータやタイムスタンプ用の、小さく控えめなテキストと画像はい
actionsインタラクティブ要素(ボタン、セレクト、日付ピッカー)の行該当なし
rich_text高度な書式設定テキスト(リスト、引用、コードブロック)該当なし
Header ブロック
{
  "type": "header",
  "text": {
    "type": "plain_text",
    "text": "Weekly Marketing Report",
    "emoji": true
  }
}
Section ブロック

プレーンテキストのセクション:

{
  "type": "section",
  "text": {
    "type": "mrkdwn",
    "text": "*Traffic is up 23%* this week compared to last week.\nOrganic search drove most of the growth."
  }
}

フィールド付きセクション(2 列レイアウト):

{
  "type": "section",
  "fields": [
    {
      "type": "mrkdwn",
      "text": "*Visitors*\n12,450"
    },
    {
      "type": "mrkdwn",
      "text": "*Signups*\n342"
    },
    {
      "type": "mrkdwn",
      "text": "*MRR*\n$28,500"
    },
    {
      "type": "mrkdwn",
      "text": "*Churn*\n1.2%"
    }
  ]
}

ボタンアクセサリー付きセクション:

{
  "type": "section",
  "text": {
    "type": "mrkdwn",
    "text": "New blog post: *How We Grew 10x in 6 Months*"
  },
  "accessory": {
    "type": "button",
    "text": {
      "type": "plain_text",
      "text": "Read Post"
    },
    "url": "https://example.com/blog/growth-story",
    "action_id": "read_blog_post"
  }
}

画像アクセサリー付きセクション:

{
  "type": "section",
  "text": {
    "type": "mrkdwn",
    "text": "*New Feature: Dark Mode*\nOur most requested feature is finally here."
  },
  "accessory": {
    "type": "image",
    "image_url": "https://example.com/images/dark-mode-preview.png",
    "alt_text": "Dark mode preview"
  }
}
Divider ブロック
{
  "type": "divider"
}
Image ブロック
{
  "type": "image",
  "image_url": "https://example.com/images/chart.png",
  "alt_text": "Weekly traffic chart",
  "title": {
    "type": "plain_text",
    "text": "Traffic Overview"
  }
}
Context ブロック
{
  "type": "context",
  "elements": [
    {
      "type": "mrkdwn",
      "text": "Posted by *Marketing Team* | Feb 10, 2026"
    },
    {
      "type": "image",
      "image_url": "https://example.com/logo-small.png",
      "alt_text": "Company logo"
    }
  ]
}
Actions ブロック(ボタン)
{
  "type": "actions",
  "elements": [
    {
      "type": "button",
      "text": {
        "type": "plain_text",
        "text": "Approve"
      },
      "style": "primary",
      "action_id": "approve_action",
      "value": "approved"
    },
    {
      "type": "button",
      "text": {
        "type": "plain_text",
        "text": "Reject"
      },
      "style": "danger",
      "action_id": "reject_action",
      "value": "rejected"
    },
    {
      "type": "button",
      "text": {
        "type": "plain_text",
        "text": "View Details"
      },
      "url": "https://example.com/details",
      "action_id": "view_details"
    }
  ]
}

ボタンのスタイル:"primary"(緑)、"danger"(赤)、または省略してデフォルト(グレー)。

インタラクティブ機能に関する注意: action_id(url なし)が設定されたボタンのクリックペイロードを受信するには、Slack App の設定で Interactivity & Shortcuts の下に Request URL を設定する必要があります。url フィールドがあるボタンはリンクを直接開くため、バックエンドは不要です。

Block Kit の制限
制限値
メッセージあたりのブロック数50
テキストブロックあたりの文字数3,000
ヘッダーあたりの文字数150
セクションあたりのフィールド数10
actions ブロックあたりの要素数25
context ブロックあたりの要素数10
Block Kit Builder

コーディングする前に、ビジュアルビルダーを使ってメッセージをデザインし、プレビューします: https://app.slack.com/block-kit-builder


Slack mrkdwn 書式ガイド

Slack では mrkdwn と呼ばれる独自の Markdown 形式を使用します。標準的な Markdown とはいくつかの点で異なります。

書式構文例
太字*text*太字のテキスト
斜体_text_斜体のテキスト
取り消し線~text~取り消し線
コード(インライン)`text`インラインコード
コードブロック```text```複数行のコードブロック
引用>text引用テキスト
リンク<https://url|display text>クリック可能なリンク
ユーザーへのメンション<@U0123456>@username
チャンネルへのメンション<#C0123456>#channel
絵文字:emoji_name::rocket:
箇条書きリスト行頭を - または * にする箇条書き項目
番号付きリスト行頭を 1. にする番号付き項目
改行JSON 文字列内の \n新しい行

標準的な Markdown との重要な違い:

  • 太字には二重の **bold** ではなく、単一のアスタリスク *bold* を使います。
  • 斜体には単一のアスタリスクではなく、アンダースコア _italic_ を使います。
  • リンクには [text](url) ではなく、パイプを使った <url|text> 形式を使います。
  • mrkdwn にヘッダーはありません。代わりに header ブロックタイプを使います。
  • mrkdwn に画像をインライン表示することはできません。代わりに image ブロックまたは accessory を使います。

メッセージテンプレート

テンプレート 1:製品発表
curl -s -X POST "$SLACK_WEBHOOK_URL" \
  -H "Content-Type: application/json" \
  -d '{
    "blocks": [
      {
        "type": "header",
        "text": {
          "type": "plain_text",
          "text": ":rocket: New Feature: [Feature Name]",
          "emoji": true
        }
      },
      {
        "type": "section",
        "text": {
          "type": "mrkdwn",
          "text": "We just shipped *[Feature Name]* — here is what it does and why it matters.\n\n:point_right: *What it does:* [One-sentence description]\n:point_right: *Why it matters:* [Key benefit for users]\n:point_right: *How to try it:* [Quick instructions or link]"
        }
      },
      {
        "type": "image",
        "image_url": "https://example.com/feature-screenshot.png",
        "alt_text": "Feature screenshot"
      },
      {
        "type": "divider"
      },
      {
        "type": "actions",
        "elements": [
          {
            "type": "button",
            "text": {
              "type": "plain_text",
              "text": ":newspaper: Read Announcement",
              "emoji": true
            },
            "url": "https://example.com/blog/feature-launch",
            "action_id": "read_announcement"
          },
          {
            "type": "button",
            "text": {
              "type": "plain_text",
              "text": ":play_or_pause_button: Watch Demo",
              "emoji": true
            },
            "url": "https://example.com/demo",
            "action_id": "watch_demo"
          }
        ]
      },
      {
        "type": "context",
        "elements": [
          {
            "type": "mrkdwn",
            "text": "Posted by *Product Team* | :speech_balloon: Reply in thread with questions"
          }
        ]
      }
    ]
  }'
テンプレート 2:週間指標レポート
curl -s -X POST "$SLACK_WEBHOOK_URL" \
  -H "Content-Type: application/json" \
  -d '{
    "blocks": [
      {
        "type": "header",
        "text": {
          "type": "plain_text",
          "text": ":bar_chart: Weekly Marketing Metrics — Feb 3-9, 2026",
          "emoji": true
        }
      },
      {
        "type": "section",
        "text": {
          "type": "mrkdwn",
          "text": "Here is this week'\''s performance snapshot."
        }
      },
      {
        "type": "divider"
      },
      {
        "type": "section",
        "text": {
          "type": "mrkdwn",
          "text": ":globe_with_meridians: *Website Traffic*"
        },
        "fields": [
          {
            "type": "mrkdwn",
            "text": "*Sessions*\n45,230 (:arrow_up: 12%)"
          },
          {
            "type": "mrkdwn",
            "text": "*Unique Visitors*\n31,870 (:arrow_up: 8%)"
          },
          {
            "type": "mrkdwn",
            "text": "*Bounce Rate*\n42.3% (:arrow_down: 2.1%)"
          },
          {
            "type": "mrkdwn",
            "text": "*Avg. Session Duration*\n3m 42s (:arrow_up: 15s)"
          }
        ]
      },
      {
        "type": "section",
        "text": {
          "type": "mrkdwn",
          "text": ":money_with_wings: *Conversion Metrics*"
        },
        "fields": [
          {
            "type": "mrkdwn",
            "text": "*Signups*\n487 (:arrow_up: 18%)"
          },
          {
            "type": "mrkdwn",
            "text": "*Trial-to-Paid*\n12.4% (:arrow_up: 1.2%)"
          },
          {
            "type": "mrkdwn",
            "text": "*MRR*\n$52,300 (:arrow_up: $3,200)"
          },
          {
            "type": "mrkdwn",
            "text": "*Churn*\n1.8% (:arrow_down: 0.3%)"
          }
        ]
      },
      {
        "type": "section",
        "text": {
          "type": "mrkdwn",
          "text": ":email: *Email Performance*"
        },
        "fields": [
          {
            "type": "mrkdwn",
            "text": "*Emails Sent*\n12,400"
          },
          {
            "type": "mrkdwn",
            "text": "*Open Rate*\n34.2%"
          },
          {
            "type": "mrkdwn",
            "text": "*Click Rate*\n4.8%"
          },
          {
            "type": "mrkdwn",
            "text": "*Unsubscribes*\n23"
          }
        ]
      },
      {
        "type": "divider"
      },
      {
        "type": "section",
        "text": {
          "type": "mrkdwn",
          "text": "*:bulb: Key Takeaways*\n- Organic traffic up 15% after publishing 3 new blog posts\n- Email welcome sequence A/B test: Variant B outperformed by 22%\n- Trial signup spike on Thursday correlated with Product Hunt feature"
        }
      },
      {
        "type": "actions",
        "elements": [
          {
            "type": "button",
            "text": {
              "type": "plain_text",
              "text": "Full Dashboard",
              "emoji": true
            },
            "url": "https://analytics.example.com/dashboard",
            "action_id": "view_dashboard"
          }
        ]
      },
      {
        "type": "context",
        "elements": [
          {
            "type": "mrkdwn",
            "text": "Auto-generated by Marketing Bot | Data from Google Analytics + Stripe"
          }
        ]
      }
    ]
  }'
テンプレート 3:ブログ記事の共有
curl -s -X POST "$SLACK_WEBHOOK_URL" \
  -H "Content-Type: application/json" \
  -d '{
    "blocks": [
      {
        "type": "header",
        "text": {
          "type": "plain_text",
          "text": ":pencil: New Blog Post Published",
          "emoji": true
        }
      },
      {
        "type": "section",
        "text": {
          "type": "mrkdwn",
          "text": "*<https://example.com/blog/post-slug|Blog Post Title Here>*\n\nA brief summary of what the post covers — keep it to 2-3 sentences that capture the key value and make people want to click through."
        },
        "accessory": {
          "type": "image",
          "image_url": "https://example.com/blog/post-og-image.png",
          "alt_text": "Blog post cover image"
        }
      },
      {
        "type": "context",
        "elements": [
          {
            "type": "mrkdwn",
            "text": ":bust_in_silhouette: Author: *Jane Smith* | :clock1: 6 min read | :label: SEO, Growth"
          }
        ]
      },
      {
        "type": "divider"
      },
      {
        "type": "section",
        "text": {
          "type": "mrkdwn",
          "text": ":mega: *Help us amplify!* Share this post on your socials. Here are ready-to-use snippets:\n\n*Twitter/X:* _Just published: [title]. [Key insight from the post]. Link in reply._\n\n*LinkedIn:* _We just published a deep dive on [topic]. Here is the #1 takeaway: [insight]._"
        }
      },
      {
        "type": "actions",
        "elements": [
          {
            "type": "button",
            "text": {
              "type": "plain_text",
              "text": "Read the Post",
              "emoji": true
            },
            "style": "primary",
            "url": "https://example.com/blog/post-slug",
            "action_id": "read_post"
          },
          {
            "type": "button",
            "text": {
              "type": "plain_text",
              "text": "Share on Twitter",
              "emoji": true
            },
            "url": "https://twitter.com/intent/tweet?text=Check%20out%20this%20post&url=https://example.com/blog/post-slug",
            "action_id": "share_twitter"
          },
          {
            "type": "button",
            "text": {
              "type": "plain_text",
              "text": "Share on LinkedIn",
              "emoji": true
            },
            "url": "https://www.linkedin.com/sharing/share-offsite/?url=https://example.com/blog/post-slug",
            "action_id": "share_linkedin"
          }
        ]
      }
    ]
  }'
テンプレート 4:チームの最新情報/スタンドアップ
curl -s -X POST "$SLACK_WEBHOOK_URL" \
  -H "Content-Type: application/json" \
  -d '{
    "blocks": [
      {
        "type": "header",
        "text": {
          "type": "plain_text",
          "text": ":clipboard: Marketing Team Update — Monday, Feb 10",
          "emoji": true
        }
      },
      {
        "type": "section",
        "text": {
          "type": "mrkdwn",
          "text": "*:white_check_mark: Completed Last Week*\n- Launched email welcome sequence v2\n- Published 3 blog posts (SEO, product, case study)\n- Set up Google Ads remarketing campaign\n- Shipped landing page A/B test (Variant B live)"
        }
      },
      {
        "type": "section",
        "text": {
          "type": "mrkdwn",
          "text": "*:construction: In Progress*\n- Content calendar for March (70% done)\n- Competitor analysis report (due Wednesday)\n- Social media campaign for Product Hunt launch"
        }
      },
      {
        "type": "section",
        "text": {
          "type": "mrkdwn",
          "text": "*:dart: This Week'\''s Priorities*\n1. Finalize Product Hunt launch assets\n2. Send weekly newsletter (Thursday 9am)\n3. Review and approve Q1 ad spend budget\n4. Onboard new content writer"
        }
      },
      {
        "type": "section",
        "text": {
          "type": "mrkdwn",
          "text": "*:warning: Blockers*\n- Waiting on design team for Product Hunt gallery images\n- Need legal review on new case study before publishing"
        }
      },
      {
        "type": "divider"
      },
      {
        "type": "context",
        "elements": [
          {
            "type": "mrkdwn",
            "text": ":speech_balloon: Reply in thread with your own updates or questions"
          }
        ]
      }
    ]
  }'
テンプレート 5:インシデント/緊急通知
curl -s -X POST "$SLACK_WEBHOOK_URL" \
  -H "Content-Type: application/json" \
  -d '{
    "blocks": [
      {
        "type": "header",
        "text": {
          "type": "plain_text",
          "text": ":rotating_light: Marketing Alert",
          "emoji": true
        }
      },
      {
        "type": "section",
        "text": {
          "type": "mrkdwn",
          "text": "*Issue:* [Brief description of the problem]\n*Impact:* [Who/what is affected]\n*Status:* :red_circle: Active\n*Owner:* <@U0123456>"
        }
      },
      {
        "type": "section",
        "text": {
          "type": "mrkdwn",
          "text": "*Details:*\n[Longer explanation. What happened, when it started, what we know so far.]"
        }
      },
      {
        "type": "section",
        "text": {
          "type": "mrkdwn",
          "text": "*Next Steps:*\n1. [Action item 1]\n2. [Action item 2]\n3. [Action item 3]"
        }
      },
      {
        "type": "actions",
        "elements": [
          {
            "type": "button",
            "text": {
              "type": "plain_text",
              "text": "Status Page"
            },
            "url": "https://status.example.com",
            "action_id": "status_page"
          }
        ]
      }
    ]
  }'

ワークフロー

ワークフロー 1:マーケティング告知を投稿する

ユーザーから Slack への告知、製品アップデート、またはニュースの投稿を依頼された場合:

  1. 詳細を確認する - 告知のタイトル、本文、リンク、画像 URL、投稿先チャンネルを尋ねます。
  2. テンプレートを選ぶ - 上記のテンプレートから選ぶか、カスタム Block Kit ペイロードを作成します。
  3. ペイロードを作成する - mrkdwn の書式を適切に使用して JSON を組み立てます。
  4. プレビューする - JSON ペイロード全体をユーザーに提示し、どのように表示されるか説明します。
  5. 確認する - 送信前にユーザーの承認を求めます。
  6. 送信する - curl コマンドを実行します。
  7. 報告する - API レスポンスを提示します。Web API の場合は、スレッド化に使う ts を取得します。
ワークフロー 2:週次指標を投稿する

ユーザーから指標レポートやダッシュボードを Slack に送信するよう依頼された場合:

  1. 指標を収集する - 数値を尋ねるか、分析ツールから取得するのを手伝います。
  2. フィールドで整形する - fields を含むセクションブロックを使い、2 列の指標レイアウトにします。
  3. 背景情報を加える - 矢印の絵文字を使って、前週との比較を含めます。
  4. 要点を加える - セクションブロックに 2~3 件の重要なインサイトをまとめます。
  5. ダッシュボードへのリンクを含める - 分析ダッシュボード全体へのボタンを追加します。
  6. 投稿してスレッドを作成する - メインレポートを投稿し、その後、詳細な内訳を返信としてスレッドに投稿します。
ワークフロー 3:ブログ記事を共有する

新しいブログ記事をチームに共有する必要がある場合:

  1. URL を取得する - ブログ記事の URL を尋ねるか、ブログから最新の記事を取得します。
  2. メタデータを抽出する - WebFetch を使って、タイトル、説明、著者、OG 画像を取得します。
  3. 共有メッセージを作成する - ソーシャルメディアでの拡散用の文面とともにテンプレート 3 を使います。
  4. 共有ボタンを追加する - 記事の内容があらかじめ入力された Twitter と LinkedIn のインテント URL を含めます。
  5. チャンネルに投稿する - チームのマーケティングチャンネルに送信します。
ワークフロー 4:コミュニティへの参加

Slack のコミュニティチャンネル(公開コミュニティ、顧客チャンネル)を管理する場合:

  1. ウェルカムメッセージ - 新しいメンバーが参加したら、ルールとリソースを記載したウェルカムメッセージを投稿します。
  2. 定期的な更新 - 人気のあるディスカッションや新しいリソースをまとめて、毎週投稿します。
  3. イベントのお知らせ - 今後のウェビナー、AMA、ミートアップを RSVP ボタンとともに共有します。
  4. アンケートとフィードバック - アクションブロックのボタンを使って、簡単なフィードバックを集めます。
  5. スレッドの管理 - 既存のスレッドに更新情報や回答を返信します。

動的コンテンツを含むメッセージの送信

シェル変数でペイロードを作成する
TITLE="Product X v2.0 Released"
DESCRIPTION="Version 2.0 includes dark mode, API improvements, and 3x faster performance."
LINK="https://example.com/changelog/v2"
IMAGE_URL="https://example.com/images/v2-banner.png"
CHANNEL="#announcements"

curl -s -X POST "https://slack.com/api/chat.postMessage" \
  -H "Authorization: Bearer ${SLACK_BOT_TOKEN}" \
  -H "Content-Type: application/json" \
  -d "$(python3 -c "
import json
payload = {
    'channel': '${CHANNEL}',
    'text': '${TITLE}',
    'blocks': [
        {
            'type': 'header',
            'text': {'type': 'plain_text', 'text': '${TITLE}', 'emoji': True}
        },
        {
            'type': 'section',
            'text': {'type': 'mrkdwn', 'text': '${DESCRIPTION}'}
        },
        {
            'type': 'image',
            'image_url': '${IMAGE_URL}',
            'alt_text': '${TITLE}'
        },
        {
            'type': 'actions',
            'elements': [{
                'type': 'button',
                'text': {'type': 'plain_text', 'text': 'Learn More'},
                'url': '${LINK}',
                'style': 'primary',
                'action_id': 'learn_more'
            }]
        }
    ]
}
print(json.dumps(payload))
")"
JSON ファイルからペイロードを作成する

複雑なメッセージの場合は、まずペイロードをファイルに書き込みます。

# Write the payload
cat > /tmp/slack-message.json << 'PAYLOAD'
{
  "channel": "#marketing",
  "text": "Fallback text for notifications",
  "blocks": [
    {
      "type": "header",
      "text": {
        "type": "plain_text",
        "text": "Message Title"
      }
    },
    {
      "type": "section",
      "text": {
        "type": "mrkdwn",
        "text": "Message body with *bold* and _italic_ formatting."
      }
    }
  ]
}
PAYLOAD

# Send it
curl -s -X POST "https://slack.com/api/chat.postMessage" \
  -H "Authorization: Bearer ${SLACK_BOT_TOKEN}" \
  -H "Content-Type: application/json" \
  -d @/tmp/slack-message.json

スケジュール済みメッセージ

chat.scheduleMessage を使って、指定した将来の時刻にメッセージを投稿します。

# Schedule a message for a specific Unix timestamp
# Use: date -d "2026-02-12 09:00:00" +%s (Linux) or date -j -f "%Y-%m-%d %H:%M:%S" "2026-02-12 09:00:00" +%s (macOS)
SEND_AT=$(date -j -f "%Y-%m-%d %H:%M:%S" "2026-02-12 09:00:00" +%s 2>/dev/null || date -d "2026-02-12 09:00:00" +%s)

curl -s -X POST "https://slack.com/api/chat.scheduleMessage" \
  -H "Authorization: Bearer ${SLACK_BOT_TOKEN}" \
  -H "Content-Type: application/json" \
  -d "{
    \"channel\": \"#marketing\",
    \"post_at\": ${SEND_AT},
    \"text\": \"Good morning team! Here is today's marketing agenda.\",
    \"blocks\": []
  }"

スケジュール済みメッセージを一覧表示します。

curl -s "https://slack.com/api/chat.scheduledMessages.list" \
  -H "Authorization: Bearer ${SLACK_BOT_TOKEN}" | \
  python3 -c "
import json, sys, datetime
data = json.load(sys.stdin)
for msg in data.get('scheduled_messages', []):
    ts = datetime.datetime.fromtimestamp(msg['post_at']).strftime('%Y-%m-%d %H:%M')
    print(f\"ID: {msg['id']}  |  Channel: {msg['channel_id']}  |  Scheduled: {ts}\")
"

スケジュール済みメッセージを削除します。

curl -s -X POST "https://slack.com/api/chat.deleteScheduledMessage" \
  -H "Authorization: Bearer ${SLACK_BOT_TOKEN}" \
  -H "Content-Type: application/json" \
  -d '{
    "channel": "C0123456789",
    "scheduled_message_id": "Q0123456789"
  }'

複数チャンネルへの投稿

同じメッセージを複数のチャンネルに投稿します。

CHANNELS=("#marketing" "#general" "#product")
MESSAGE='{"text":"Big announcement coming tomorrow!","blocks":[{"type":"section","text":{"type":"mrkdwn","text":":mega: *Big announcement coming tomorrow!* Stay tuned."}}]}'

for CHANNEL in "${CHANNELS[@]}"; do
  echo "Posting to ${CHANNEL}..."
  echo "$MESSAGE" | python3 -c "
import json, sys
msg = json.load(sys.stdin)
msg['channel'] = '${CHANNEL}'
print(json.dumps(msg))
" | curl -s -X POST "https://slack.com/api/chat.postMessage" \
    -H "Authorization: Bearer ${SLACK_BOT_TOKEN}" \
    -H "Content-Type: application/json" \
    -d @- | python3 -c "
import json, sys
r = json.load(sys.stdin)
if r.get('ok'):
    print(f'  Sent. ts={r[\"ts\"]}')
else:
    print(f'  Error: {r.get(\"error\", \"unknown\")}')
"
done

エラー処理

よくある API エラー
エラー原因修正方法
invalid_authトークンが無効、または期限切れSlack App の設定でボットトークンを再生成します
channel_not_foundボットがチャンネルに参加していない、またはチャンネル名が間違っている/invite @BotName でボットを招待するか、チャンネル ID を使います
not_in_channelボットが先にチャンネルに参加する必要があるボットを招待するか、chat:write.public スコープを使います
too_many_attachmentsブロックが 50 個を超えているメッセージを複数の投稿またはスレッドへの返信に分割します
msg_too_longテキストが 40,000 文字を超えているメッセージを短くするか、複数のパートに分割します
rate_limitedリクエストが多すぎるRetry-After ヘッダーに記載された秒数だけ待ちます
missing_scopeトークンに必要な権限がないOAuth & Permissions でスコープを追加し、アプリを再インストールします
レスポンスを検証する
RESPONSE=$(curl -s -X POST "https://slack.com/api/chat.postMessage" \
  -H "Authorization: Bearer ${SLACK_BOT_TOKEN}" \
  -H "Content-Type: application/json" \
  -d '{"channel":"#marketing","text":"Test message"}')

python3 -c "
import json, sys
r = json.loads('${RESPONSE}'.replace(\"'\", \"\"))
if r.get('ok'):
    print(f'Message sent successfully. ts={r[\"ts\"]} channel={r[\"channel\"]}')
else:
    print(f'Error: {r.get(\"error\", \"unknown\")}')
    if r.get('response_metadata', {}).get('messages'):
        for m in r['response_metadata']['messages']:
            print(f'  Detail: {m}')
" 2>/dev/null || echo "$RESPONSE"

一時ファイルを使う、より堅牢な方法:

RESPONSE_FILE=$(mktemp)
curl -s -X POST "https://slack.com/api/chat.postMessage" \
  -H "Authorization: Bearer ${SLACK_BOT_TOKEN}" \
  -H "Content-Type: application/json" \
  -d '{"channel":"#marketing","text":"Test message"}' \
  -o "$RESPONSE_FILE"

python3 -c "
import json
with open('${RESPONSE_FILE}') as f:
    r = json.load(f)
if r.get('ok'):
    print(f'Sent. ts={r[\"ts\"]}')
else:
    print(f'Error: {r.get(\"error\")}')
"
rm -f "$RESPONSE_FILE"

ヒント

  • 通知、スクリーンリーダー、Block Kit をサポートしていないクライアント向けのフォールバックとして機能するため、blocks とともに必ず text フィールドを含めてください。
  • curl コマンドを作成する前に、https://app.slack.com/block-kit-builder の Block Kit Builder を使って、メッセージを視覚的にデザインし、プレビューしてください。
  • 本番環境のワークフローでは、Webhook ではなく chat.postMessage(Web API)を使用してください。スレッドへの投稿、更新、削除に使用できるメッセージの ts が返されます。
  • 長いレポートはスレッドに投稿してください。チャンネルをすっきり保つため、親メッセージには要約を投稿し、詳細はスレッドの返信として投稿してください。
  • ヘッダーやボタンのラベルに絵文字を表示するには、plain_text フィールドで "emoji": true を指定して、:emoji: コードを使用してください。
  • mrkdwn の特殊文字はエスケープしてください。& は &amp;、< は &lt;、> は &gt; になります。
  • レート制限:Slack では、チャンネルごとにおよそ 1 秒あたり 1 メッセージまで投稿できます。一括投稿する場合は、リクエスト間に 1 秒の遅延を入れてください。
  • メトリクスを投稿する場合は、mrkdwn で表を整形しようとせず、セクションの fields を使って 2 列のレイアウトにしてください(Slack は表をサポートしていません)。
  • 投稿する前に、必ずメッセージのペイロード全体をユーザーに見せ、確認を求めてください。

コメント