Designing Operational Slack Messages With Block Kit Instead of Text Walls
Operational Slack alerts become unreadable as plain text. Block Kit lets you define structured messages with JSON blocks and interactive elements, separating presentation from backend logic for more reliable ops communication.
14 Mar 2026, 03:55 UTC

Operational alerts in Slack quickly become unreadable when teams rely on plain text. A single incident message can mix timestamps, severity, owners, and actions in a paragraph that wraps differently on desktop and mobile. The useful takeaway is to treat the message as a structured UI: Block Kit lets you define layout with JSON blocks and elements, while your backend handles the logic when users interact.
Block Kit is Slack’s UI framework for building rich, interactive messages and app surfaces. It uses a JSON schema of blocks for layout and elements for interactivity. The client enforces layout constraints and responsiveness, so you define structure, not pixel positions.
Why plain text breaks for ops workflows
Text messages have no semantic structure. A severity label, a runbook link, and an acknowledge button all compete for attention in the same line. On mobile the line wraps, on desktop it stretches, and the user must parse it manually. Blocks like section, divider, image, and context give you consistent placement across clients without custom CSS.
The separation is deliberate: the presentation layer is the JSON you send to chat.postMessage, and business logic lives on your server that receives payload events from interactive elements. That split makes messages easier to review and change without touching the handler code.
Building a compact incident summary
A practical pattern is a header section with key facts, a context line for metadata, and an actions block with buttons. Elements such as buttons, select menus, and date pickers are embedded inside blocks and trigger payload events to a backend endpoint you control.
Example payload shape for chat.postMessage. Replace placeholders with your own values. This is illustrative structure, not a tested call.
{
"channel": "",
"text": "Incident INC-1234 updated",
"blocks": [
{
"type": "section",
"text": {
"type": "mrkdwn",
"text": "*INC-1234* - API latency elevated\nSeverity: *high* | Started: 2026-10-16 14:10 UTC"
}
},
{
"type": "context",
"elements": [
{"type": "mrkdwn", "text": "Owner: @sre-oncall • Service: payments-api"}
]
},
{"type": "divider"},
{
"type": "actions",
"elements": [
{
"type": "button",
"text": {"type": "plain_text", "text": "Acknowledge"},
"action_id": "incident_ack",
"value": "INC-1234"
},
{
"type": "button",
"text": {"type": "plain_text", "text": "View runbook"},
"url": "https://runbooks.example.com/INC-1234"
}
]
}
]
}
To send from a terminal with a bot token that has chat:write scope:
curl -X POST https://slack.com/api/chat.postMessage \
-H "Authorization: Bearer $SLACK_BOT_TOKEN" \
-H "Content-type: application/json" \
-d @payload.json
Run this in a local shell where the token is set as an environment variable. Risk: exposing the token in shell history or logs. Check the response for the presence of an ok field and an error field, and verify the message appears in the target channel with the expected blocks.
Trade-offs and limits to plan for
Block Kit enforces strict limits on the number of blocks per message to prevent performance degradation. Complex nested elements can behave differently across Slack client versions, so test the same payload on desktop and mobile.
Interactive payloads must be verified. Slack signs requests with a signing secret. Your endpoint should verify the signature before processing any action_id. Skipping verification is a security risk.
A practical way to check results is to prototype with the Block Kit Builder to generate JSON, then deploy a minimal Bolt app in Node.js or Python to receive the interactive payload and log the action_id and value. Compare the received payload structure against the Slack API reference for chat.postMessage and interactions.
Start with one structured message type, keep blocks minimal, and add interactivity only where it reduces context switching. That keeps messages readable and maintainable without rebuilding the client rendering.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.