slack-bot について
Incoming Webhooks または Slack Web API を使って、Slack にメッセージや整形済みコンテンツを送るスキルです。Block Kit の告知やレポート、スレッド返信、ファイル投稿などの例を提供します。
主な機能
- 01Webhook と Web API による投稿
- 02Block Kit メッセージの整形
- 03スレッド返信とメッセージ更新
- 04チャンネル一覧とファイル投稿
- 05Slack mrkdwn の書式リファレンス
活用シーン
- 01整形したマーケティングレポートの投稿
- 02チャンネルでの告知共有
- 03既存メッセージへのスレッド返信
- 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 スコープは不要で、単一のチャンネルに限定されます。
- https://api.slack.com/apps にアクセスし、Create New App > From scratch をクリックします。
- アプリ名(例:「Marketing Bot」)を入力し、ワークスペースを選択します。
- 左サイドバーで Incoming Webhooks をクリックし、切り替えボタンを On にします。
- 下部にある Add New Webhook to Workspace をクリックします。
- 投稿先のチャンネルを選択し、Allow をクリックします。
- Webhook URL(
https://hooks.slack.com/services/...で始まる)をコピーします。 - 環境に追加します。
echo 'SLACK_WEBHOOK_URL=https://hooks.slack.com/services/T.../B.../xxxx' >> .env
制限事項: 1 チャンネルにつき Webhook は 1 つです。プログラムからメッセージの読み取り、チャンネルの一覧表示、スレッドへの返信はできません(事前の API レスポンスから thread_ts を取得しておく必要があります)。
オプション B:ボットトークン(全機能)
ボットトークンを使うと、Slack Web API の全機能にアクセスできます。ボットが参加している任意のチャンネルへの投稿、スレッドへの返信、チャンネルの一覧表示、ファイルのアップロードなどが可能です。
- https://api.slack.com/apps にアクセスし、Create New App > From scratch をクリックします。
- アプリ名を入力し、ワークスペースを選択します。
- 左サイドバーで OAuth & Permissions をクリックします。
- Bot Token Scopes で、次のスコープを追加します。
chat:write- メッセージの投稿chat:write.public- 参加していないチャンネルへの投稿channels:read- パブリックチャンネルの一覧表示files:write- ファイルのアップロード(任意。画像やレポート用)reactions:write- 絵文字リアクションの追加(任意)
- 上部の Install to Workspace をクリックし、認可します。
- Bot User OAuth Token(
xoxb-で始まる)をコピーします。 - 環境に追加します。
echo 'SLACK_BOT_TOKEN=xoxb-your-token-here' >> .env
- ボットが投稿するチャンネルで、
/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 への告知、製品アップデート、またはニュースの投稿を依頼された場合:
- 詳細を確認する - 告知のタイトル、本文、リンク、画像 URL、投稿先チャンネルを尋ねます。
- テンプレートを選ぶ - 上記のテンプレートから選ぶか、カスタム Block Kit ペイロードを作成します。
- ペイロードを作成する - mrkdwn の書式を適切に使用して JSON を組み立てます。
- プレビューする - JSON ペイロード全体をユーザーに提示し、どのように表示されるか説明します。
- 確認する - 送信前にユーザーの承認を求めます。
- 送信する - curl コマンドを実行します。
- 報告する - API レスポンスを提示します。Web API の場合は、スレッド化に使う
tsを取得します。
ワークフロー 2:週次指標を投稿する
ユーザーから指標レポートやダッシュボードを Slack に送信するよう依頼された場合:
- 指標を収集する - 数値を尋ねるか、分析ツールから取得するのを手伝います。
- フィールドで整形する -
fieldsを含むセクションブロックを使い、2 列の指標レイアウトにします。 - 背景情報を加える - 矢印の絵文字を使って、前週との比較を含めます。
- 要点を加える - セクションブロックに 2~3 件の重要なインサイトをまとめます。
- ダッシュボードへのリンクを含める - 分析ダッシュボード全体へのボタンを追加します。
- 投稿してスレッドを作成する - メインレポートを投稿し、その後、詳細な内訳を返信としてスレッドに投稿します。
ワークフロー 3:ブログ記事を共有する
新しいブログ記事をチームに共有する必要がある場合:
- URL を取得する - ブログ記事の URL を尋ねるか、ブログから最新の記事を取得します。
- メタデータを抽出する - WebFetch を使って、タイトル、説明、著者、OG 画像を取得します。
- 共有メッセージを作成する - ソーシャルメディアでの拡散用の文面とともにテンプレート 3 を使います。
- 共有ボタンを追加する - 記事の内容があらかじめ入力された Twitter と LinkedIn のインテント URL を含めます。
- チャンネルに投稿する - チームのマーケティングチャンネルに送信します。
ワークフロー 4:コミュニティへの参加
Slack のコミュニティチャンネル(公開コミュニティ、顧客チャンネル)を管理する場合:
- ウェルカムメッセージ - 新しいメンバーが参加したら、ルールとリソースを記載したウェルカムメッセージを投稿します。
- 定期的な更新 - 人気のあるディスカッションや新しいリソースをまとめて、毎週投稿します。
- イベントのお知らせ - 今後のウェビナー、AMA、ミートアップを RSVP ボタンとともに共有します。
- アンケートとフィードバック - アクションブロックのボタンを使って、簡単なフィードバックを集めます。
- スレッドの管理 - 既存のスレッドに更新情報や回答を返信します。
動的コンテンツを含むメッセージの送信
シェル変数でペイロードを作成する
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 の特殊文字はエスケープしてください。
&は&、<は<、>は>になります。 - レート制限:Slack では、チャンネルごとにおよそ 1 秒あたり 1 メッセージまで投稿できます。一括投稿する場合は、リクエスト間に 1 秒の遅延を入れてください。
- メトリクスを投稿する場合は、mrkdwn で表を整形しようとせず、セクションの
fieldsを使って 2 列のレイアウトにしてください(Slack は表をサポートしていません)。 - 投稿する前に、必ずメッセージのペイロード全体をユーザーに見せ、確認を求めてください。