การส่งข้อความและบล็อกแบบ Rich
ข้อความธรรมดา มาร์กดาวน์ และ JSON ของ Block Kit — การจัดรูปแบบข้อความ Slack
การส่งข้อความและบล็อกแบบ Rich เป็นบทเรียน AI Agents ฟรีบน CoddyKit นี่คือบทเรียนที่ 3 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน AI Agents และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส AI Agents มีบทเรียนทั้งหมด 4 บทเรียน
ข้อความตัวอักษรอย่างง่ายด้วย say()
วิธีที่ง่ายที่สุดในการโพสต์ข้อความ Slack คือ say(text) ข้อความรองรับ mrkdwn ซึ่งเป็นรูปแบบมาร์กดาวน์ของ Slack ใช้ *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 สำหรับสร้างข้อความที่มีเนื้อหาครบถ้วนและโต้ตอบได้ แทนที่จะใช้ข้อความธรรมดา คุณสามารถประกอบข้อความจากบล็อกที่มีประเภทต่าง ๆ ได้แก่ section, header, divider, actions และ context ส่งบล็อกเป็นรายการให้กับพารามิเตอร์ blocks ของ say() หรือ chat_postMessage()
@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
)บล็อกส่วนที่มีฟิลด์ข้อความ
บล็อก ส่วน มีความยืดหยุ่นมากที่สุด สามารถแสดงข้อความ (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)
บล็อกส่วนหัวและตัวแบ่ง
ใช้บล็อก ส่วนหัว สำหรับชื่อส่วนขนาดใหญ่ และใช้บล็อก ตัวแบ่ง เพื่อแยกเนื้อหาให้เห็นได้ชัดเจน บล็อกส่วนหัวรองรับเฉพาะ 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_id (ใช้กำหนดเส้นทางการคลิกไปยังตัวจัดการ) มี text และอาจมี value สำหรับส่งข้อมูล ใช้ style: 'primary' สำหรับ CTA หลัก และใช้ 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)
บล็อกบริบทสำหรับข้อมูลกำกับ
บล็อก บริบท ใช้แสดงข้อความขนาดเล็กที่มีความสำคัญรองลงมาด้านล่างของข้อความ เหมาะสำหรับข้อมูลกำกับ เช่น การประทับเวลา แหล่งที่มา หรือข้อมูลเวอร์ชันของเอเจนต์ บล็อกเหล่านี้รองรับ 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 ในฟิลด์ข้อความ
mrkdwn ของ Slack รองรับมาร์กดาวน์เพียงบางส่วน ตัวเลือกการจัดรูปแบบสำคัญสำหรับข้อความของเอเจนต์ ได้แก่ ตัวหนา ตัวเอียง โค้ด ลิงก์ การกล่าวถึงช่อง การกล่าวถึงผู้ใช้ และรายการ ใช้ตัวเลือกเหล่านี้เพื่อทำให้เนื้อหาที่สร้างโดย 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() (คำสั่งสแลช) หรือ 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)
)การอัปเดตข้อความหลังส่ง
หลังจากโพสต์ข้อความแล้ว คุณสามารถอัปเดตข้อความนั้นได้โดยใช้ client.chat_update() พร้อมช่องและการประทับเวลาของข้อความ (ts) วิธีนี้เหมาะสำหรับการอัปเดตความคืบหน้า เช่น โพสต์ข้อความเริ่มต้นว่า 'กำลังประมวลผล...' แล้วอัปเดตเป็นผลลัพธ์เมื่อดำเนินการเสร็จ
@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)
ตรวจสอบความเข้าใจอย่างรวดเร็ว: ประเภทบล็อก
ทดสอบความเข้าใจเกี่ยวกับ Block Kit ของ Slack
สรุปข้อความแบบครบถ้วน
ตอนนี้เอเจนต์ของคุณสามารถโพสต์ข้อความ Slack ที่ดูเป็นมืออาชีพและโต้ตอบได้:
- say(text) — ข้อความ mrkdwn อย่างง่าย รองรับ *ตัวหนา*, _ตัวเอียง_, `โค้ด` และการกล่าวถึง
- say(blocks=[...]) — Block Kit สำหรับการจัดวางแบบมีโครงสร้าง
- ส่วนหัว — ชื่อส่วนขนาดใหญ่ รองรับ plain_text เท่านั้น
- ส่วน — เนื้อหาข้อความพร้อมฟิลด์เสริม (ตารางคีย์-ค่า) หรือองค์ประกอบเสริมหนึ่งรายการ
- ตัวแบ่ง — เส้นคั่นแนวนอน
- การกระทำ — ตัวครอบสำหรับปุ่มและองค์ประกอบแบบโต้ตอบ
- บริบท — ข้อความข้อมูลกำกับขนาดเล็กด้านล่าง
- respond(response_type='ephemeral') — ข้อความที่มองเห็นได้เฉพาะผู้ใช้ที่เรียกใช้
- chat_update(ts=...) — อัปเดตข้อความที่โพสต์ไว้ก่อนหน้าด้วยเนื้อหาใหม่
คำถามที่พบบ่อย
บทเรียน “การส่งข้อความและบล็อกแบบ Rich” ฟรีหรือไม่
ใช่ — ข้อความเต็มของ “การส่งข้อความและบล็อกแบบ Rich” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส AI Agents ให้อัปเกรดเป็น CoddyKit PRO คอร์ส AI Agents มีบทเรียนทั้งหมด 4 บทเรียน
คุณจะเรียนรู้อะไรในบทเรียน “การส่งข้อความและบล็อกแบบ Rich”
ข้อความธรรมดา มาร์กดาวน์ และ JSON ของ Block Kit — การจัดรูปแบบข้อความ Slack คุณปฏิบัติ AI Agents ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน
คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน AI Agents หรือไม่
ไม่จำเป็นต้องมีประสบการณ์มาก่อน AI Agents บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 3 จากทั้งหมด 4 บทเรียน
บทเรียน “การส่งข้อความและบล็อกแบบ Rich” ใช้เวลานานแค่ไหน
บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย
ฉันเขียนและรันโค้ดในบทเรียน AI Agents นี้ได้ไหม
ได้ บทเรียน AI Agents ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ
บทเรียนทั้งหมดในหลักสูตรนี้
- พื้นฐาน Slack Bolt SDK
- การรับฟังเหตุการณ์และคำสั่งแบบเฉือน
- การส่งข้อความและบล็อกแบบ Rich
- การสร้างบอตแจ้งเตือนทีม