メッセージとリッチブロックの送信
プレーンテキスト、Markdown、Block Kit JSONでSlackメッセージを整形します。
「メッセージとリッチブロックの送信」はCoddyKit上の無料AI Agentsレッスンです。 これはレッスン3/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはAI Agents学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 AI Agentsコースには全4レッスンが含まれています。
say() によるシンプルなテキストメッセージ
Slack メッセージを投稿する最も簡単な方法は say(text) です。テキストは Slack 独自の Markdown 形式である mrkdwn に対応しています。*bold*、_italic_、~strike~、`code`、<@USERID> のようなメンションを使用できます。
@app.event('app_mention')
def handle_mention(event, say):
user = event['user']
# Simple text response with mrkdwn formatting
say(
text=(
f'Hello <@{user}>!\n'
'*Agent Report:*\n'
'- Tasks completed: `42`\n'
'- Errors: `0`\n'
'- _Runtime: 3.2 seconds_'
),
mrkdwn=True # enabled by default
)
# Slack mentions
say(f'<@{user}> your request is being processed')
say('Posting to <!channel>: all hands meeting tomorrow')Block Kit の概要
Block Kit は、リッチでインタラクティブなメッセージを構築するための Slack の UI フレームワークです。プレーンテキストだけでなく、型付きの ブロック(section、header、divider、actions、context)を組み合わせてメッセージを作成します。ブロックはリストとして、say() または chat_postMessage() の blocks パラメーターに渡します。
@app.event('app_mention')
def handle_mention(event, say):
blocks = [
{
'type': 'header',
'text': {'type': 'plain_text', 'text': 'Agent Status Report'}
},
{
'type': 'divider'
},
{
'type': 'section',
'text': {
'type': 'mrkdwn',
'text': '*Status:* Running\n*Tasks:* 42 completed'
}
}
]
say(
text='Agent Status Report', # fallback for notifications
blocks=blocks
)テキストフィールドを持つ section ブロック
section ブロックは最も柔軟性に優れています。テキスト(mrkdwn または plain_text)、キーと値のペアのリスト、またはアクセサリ要素(ボタン、画像、オーバーフローメニュー)を表示できます。キーと値のペアを横並びで表示するには fields を使用します。ダッシュボードに最適です。
def build_task_summary_blocks(tasks):
blocks = [
{
'type': 'header',
'text': {'type': 'plain_text', 'text': 'Daily Task Summary'}
},
{
'type': 'section',
'text': {
'type': 'mrkdwn',
'text': f'Processed *{len(tasks)} tasks* today.'
}
},
{
'type': 'section',
'fields': [
{'type': 'mrkdwn', 'text': f'*Completed:*\n{sum(1 for t in tasks if t["status"]=="done")}'},
{'type': 'mrkdwn', 'text': f'*Failed:*\n{sum(1 for t in tasks if t["status"]=="error")}'},
{'type': 'mrkdwn', 'text': f'*Pending:*\n{sum(1 for t in tasks if t["status"]=="pending")}'},
{'type': 'mrkdwn', 'text': f'*Avg Time:*\n3.2s'}
]
}
]
return blocks
# --- demo ---
tasks = [
{'status': 'done'}, {'status': 'done'}, {'status': 'error'}, {'status': 'pending'}
]
blocks = build_task_summary_blocks(tasks)
for b in blocks:
print(b)
header ブロックと divider ブロック
大きなセクションタイトルには header ブロックを、視覚的な区切りには divider ブロックを使用します。header ブロックが対応するのは plain_text のみで、mrkdwn には対応していません。これらを組み合わせると、構造の整ったレポートメッセージを作成できます。
def build_report_message(title, sections):
blocks = []
# Header
blocks.append({
'type': 'header',
'text': {'type': 'plain_text', 'text': title, 'emoji': True}
})
for section_title, content in sections:
# Divider between sections
blocks.append({'type': 'divider'})
# Section header as bold mrkdwn
blocks.append({
'type': 'section',
'text': {'type': 'mrkdwn', 'text': f'*{section_title}*\n{content}'}
})
return blocks
blocks = build_report_message(
title='Weekly Agent Report',
sections=[
('Emails Processed', '142 emails classified, 38 replies drafted'),
('Tasks Completed', '89 tasks completed, 3 failures logged')
]
)
# --- demo ---
for b in blocks:
print(b)
ボタン付きの action ブロック
actions ブロックにはボタンなどのインタラクティブ要素を配置します。各ボタンには、クリックをハンドラーに振り分けるための action_id、text、そしてデータを保持する任意の value があります。主要な CTA には style: 'primary' を、破壊的なアクションには style: 'danger' を使用します。
def build_approval_message(task_id, task_description):
blocks = [
{
'type': 'section',
'text': {
'type': 'mrkdwn',
'text': f'*Task ready for approval:*\n{task_description}'
}
},
{
'type': 'actions',
'elements': [
{
'type': 'button',
'text': {'type': 'plain_text', 'text': 'Approve'},
'style': 'primary',
'action_id': 'approve_task',
'value': task_id
},
{
'type': 'button',
'text': {'type': 'plain_text', 'text': 'Reject'},
'style': 'danger',
'action_id': 'reject_task',
'value': task_id
}
]
}
]
return blocks
# --- demo ---
blocks = build_approval_message('task_42', 'Deploy backend v2.3 to production')
for b in blocks:
print(b)
メタデータ用の context ブロック
Context ブロックは、メッセージの下部に小さな補足テキストを表示します。タイムスタンプ、ソース、エージェントのバージョン情報などのメタデータに最適です。mrkdwn と画像(小さなアイコン用)に対応しています。
import datetime
def add_context_footer(blocks, agent_version='v1.2'):
timestamp = datetime.datetime.now().strftime('%Y-%m-%d %H:%M UTC')
blocks.append({
'type': 'context',
'elements': [
{
'type': 'mrkdwn',
'text': f'Generated by Agent {agent_version} | {timestamp}'
}
]
})
return blocks
# Full message with context footer
blocks = [
{
'type': 'section',
'text': {'type': 'mrkdwn', 'text': 'Analysis complete. See results below.'}
}
]
blocks = add_context_footer(blocks)
print(f'Message has {len(blocks)} blocks')テキストフィールドでの mrkdwn
Slack の mrkdwn は Markdown の一部に対応しています。エージェントのメッセージで使用できる主な書式には、太字、斜体、コード、リンク、チャンネルメンション、ユーザーメンション、リストがあります。これらを使うと、AI が生成したコンテンツを Slack で読みやすくできます。
def format_ai_response_as_mrkdwn(title, bullet_points, code_snippet=None):
lines = [f'*{title}*']
for point in bullet_points:
lines.append(f'• {point}')
if code_snippet:
lines.append(f'```{code_snippet}```') # code block
return '\n'.join(lines)
content = format_ai_response_as_mrkdwn(
title='Security Issues Found',
bullet_points=[
'SQL injection risk in `user_search()` function',
'Hardcoded API key in `config.py` line 42',
'Missing HTTPS on login endpoint'
],
code_snippet='SELECT * FROM users WHERE id = " + userId + "\n# ^ UNSAFE: use parameterized queries'
)
print(content)respond() によるエフェメラルメッセージ
エフェメラルメッセージ は、アクションを実行したユーザーだけに表示され、他のチャンネルメンバーには表示されません。チャンネルを不要なメッセージで埋めたくないステータス更新、エラーメッセージ、確認などに使用します。respond()(Slash コマンド)または chat_postEphemeral() からのみ利用できます。
@app.command('/check-status')
def handle_status(ack, respond, body, client):
ack()
user_id = body['user_id']
channel_id = body['channel_id']
# Ephemeral: only the user who ran /check-status sees this
respond(
text='Checking agent status...',
response_type='ephemeral'
)
status = get_agent_status()
# Or use chat_postEphemeral for more control
client.chat_postEphemeral(
channel=channel_id,
user=user_id,
text=f'Agent Status: {status}',
blocks=build_status_blocks(status)
)送信後のメッセージの更新
メッセージを投稿した後、チャンネルとメッセージのタイムスタンプ(ts)を指定して client.chat_update() を使用すると、メッセージを更新できます。進捗状況の更新に便利です。最初に「Processing...」というメッセージを投稿し、処理が完了したら結果で更新します。
@app.command('/analyze')
def handle_analyze(ack, say, respond, body, client):
ack()
text = body.get('text', '')
channel = body['channel_id']
# Post initial message
initial = client.chat_postMessage(
channel=channel,
text='Analyzing... this may take a moment.'
)
message_ts = initial['ts']
# Do the work
import threading
def do_work():
result = slow_ai_analysis(text)
# Update the original message with the result
client.chat_update(
channel=channel,
ts=message_ts,
text=f'Analysis complete: {result}',
blocks=build_result_blocks(result)
)
threading.Thread(target=do_work, daemon=True).start()特定のチャンネルへの投稿
client.chat_postMessage(channel=channel_id, text=...) を使用すると、ボットがアクセスできる任意のチャンネルに投稿できます。チャンネル ID は Slack API で確認するか、チャンネルを右クリックして取得します。プログラムから名前でチャンネルを検索するには、conversations_list() を使用します。
def post_alert_to_channel(client, channel_name, alert_message):
# Look up channel ID by name
result = client.conversations_list(
types='public_channel,private_channel',
limit=200
)
channel_id = None
for ch in result['channels']:
if ch['name'] == channel_name:
channel_id = ch['id']
break
if not channel_id:
print(f'Channel #{channel_name} not found')
return None
# Post the alert
response = client.chat_postMessage(
channel=channel_id,
text=alert_message,
unfurl_links=False, # don't expand URLs
unfurl_media=False
)
print(f'Posted to #{channel_name}: ts={response["ts"]}')
return response
# --- demo: minimal stand-in for the Slack client ---
class _FakeClient:
def conversations_list(self, **kwargs):
return {'channels': [{'name': 'alerts', 'id': 'C123'}, {'name': 'general', 'id': 'C456'}]}
def chat_postMessage(self, **kwargs):
print(f"[slack] postMessage to {kwargs['channel']}: {kwargs['text']}")
return {'ts': '1699999999.000100'}
post_alert_to_channel(_FakeClient(), 'alerts', 'Disk usage above 90% on web-1')
Block Kit メッセージビルダーパターン
データを受け取り、ブロックのリストを返すビルダー関数を使用します。これにより、メッセージの書式設定とビジネスロジックを分離でき、異なるイベントハンドラー間でブロックを再利用しやすくなります。
def build_alert_blocks(level, title, details, link=None):
level_emoji = {'info': ':information_source:',
'warning': ':warning:', 'error': ':x:'}.get(level, '')
blocks = [
{
'type': 'header',
'text': {'type': 'plain_text', 'text': f'{level_emoji} {title}'}
},
{
'type': 'section',
'text': {'type': 'mrkdwn', 'text': details}
}
]
if link:
blocks.append({
'type': 'actions',
'elements': [{
'type': 'button',
'text': {'type': 'plain_text', 'text': 'View Details'},
'url': link,
'action_id': 'view_details'
}]
})
import datetime
blocks.append({
'type': 'context',
'elements': [{'type': 'mrkdwn',
'text': datetime.datetime.now().strftime('%Y-%m-%d %H:%M UTC')}]
})
return blocks
# --- demo ---
blocks = build_alert_blocks('warning', 'High latency', 'p95 latency is 3.2s', link='https://dash.example.com')
for b in blocks:
print(b)
クイックチェック: ブロックの種類
Slack Block Kit についての理解度を確認します。
リッチメッセージのまとめ
これでエージェントは、プロフェッショナルでインタラクティブな Slack メッセージを投稿できるようになりました。
- say(text) — シンプルな mrkdwn テキストです。*bold*、_italic_、`code`、メンションに対応しています
- say(blocks=[...]) — 構造化されたレイアウトに Block Kit を使用します
- header — 大きなセクションタイトルです(plain_text のみ)
- section — 任意の fields(キーと値のグリッド)または 1 つのアクセサリを持つテキスト本文です
- divider — 水平方向の区切り線です
- actions — ボタンやインタラクティブ要素を配置するコンテナーです
- context — 下部に表示する小さなメタデータテキストです
- respond(response_type='ephemeral') — トリガーしたユーザーだけに表示されるメッセージです
- chat_update(ts=...) — 投稿済みのメッセージを新しい内容で更新します
よくある質問
「メッセージとリッチブロックの送信」レッスンは無料ですか?
はい。「メッセージとリッチブロックの送信」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、AI Agentsコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 AI Agentsコースには全4レッスンが含まれています。
「メッセージとリッチブロックの送信」で何を学びますか?
プレーンテキスト、Markdown、Block Kit JSONでSlackメッセージを整形します。 ブラウザで直接実行するハンズオンコードでAI Agentsを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。
AI Agentsを始めるのに経験は必要ですか?
事前経験は必要ありません。CoddyKitのAI Agentsは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン3/4です。
「メッセージとリッチブロックの送信」レッスンにはどのくらい時間がかかりますか?
ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。
このAI Agentsレッスンでコードを書いて実行できますか?
はい。すべてのAI Agentsレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。
このコースのすべてのレッスン
- Slack Bolt SDKの基礎
- イベントとスラッシュコマンドの受信
- メッセージとリッチブロックの送信
- チーム通知ボットの構築