原始内容
name: "slack-block-kit" description: "Create and send native Slack Block Kit messages, including tables, code cards, structured layouts, buttons, inputs, and rich Slack blocks."
Slack Block Kit
Use this skill when Slack needs formatting beyond plain mrkdwn.
Use OpenClaw message(..., presentation=...) for portable rich replies:
- Text, context, dividers, buttons, and selects
- Cross-channel degradation when the same reply may be reused outside Slack
Use native Slack Block Kit samples or Slack API calls for Slack-specific layouts:
- Native tables and dashboards
- Syntax-highlighted code cards
- Structured layouts with headers, fields, images, inputs, and actions
- New Slack layout blocks such as containers with nested
child_blocks - Raw or experimental Slack blocks that are not part of OpenClaw portable
presentation.blocks - Local sample validation before publishing or sharing
Rule
Use plain Slack mrkdwn for ordinary prose. Use native Block Kit when structure matters.
Use the OpenClaw message tool with presentation for portable rich messages: text, context, dividers, buttons, and selects. Slack renders those as Block Kit where supported, and other channels can degrade them.
Do not put raw Slack Block Kit JSON inside OpenClaw portable presentation.blocks. The presentation schema is semantic and only accepts text, context, divider, buttons, and select blocks; it is not a Slack block pass-through. For raw or experimental Slack blocks such as tables, containers, charts, rich code cards, Markdown blocks, images, inputs, and agent-only blocks, call Slack chat.postMessage directly or use a Slack-specific plugin path.
Always include text as the notification/accessibility fallback when posting blocks.
Samples
Copy from the smallest matching sample first, then customize.
samples/blocks/header.jsonsamples/blocks/section.jsonsamples/blocks/divider.jsonsamples/blocks/image.jsonsamples/blocks/context.jsonsamples/blocks/actions.jsonsamples/blocks/input.jsonsamples/blocks/markdown.jsonsamples/blocks/agents/plan.jsonsamples/blocks/agents/task_card.jsonsamples/blocks/agents/message_feedback.jsonsamples/blocks/rich_text.jsonsamples/blocks/table.jsonsamples/blocks/data_table/basic.jsonsamples/blocks/data_table/paginated.jsonsamples/blocks/data_table/numeric_sort.jsonsamples/blocks/data_visualization/line_single.jsonsamples/blocks/data_visualization/line_multi.jsonsamples/blocks/data_visualization/line_negative.jsonsamples/blocks/data_visualization/bar_single.jsonsamples/blocks/data_visualization/bar_multi.jsonsamples/blocks/data_visualization/bar_negative.jsonsamples/blocks/data_visualization/area_single.jsonsamples/blocks/data_visualization/area_multi.jsonsamples/blocks/data_visualization/area_negative.jsonsamples/blocks/data_visualization/pie_multi_segment.jsonsamples/blocks/data_visualization/pie_dominant_segment.jsonsamples/blocks/video.jsonsamples/blocks/callout.jsonsamples/blocks/contact_card.jsonsamples/blocks/container/standard.jsonsamples/blocks/container/full_width.jsonsamples/blocks/container/collapsible.jsonsamples/blocks/container/icon_subtitle.jsonsamples/blocks/container/media_preview.jsonsamples/blocks/container/with_callout.jsonsamples/blocks/container/with_image.jsonsamples/elements/button.jsonsamples/elements/selects.jsonsamples/elements/overflow.jsonsamples/elements/date_time.jsonsamples/elements/checkboxes_radios.jsonsamples/elements/plain_text_input.json
For complete Slack API details, prefer the official docs for the specific block or element after choosing a local sample.
Validation
After adding or editing samples, run:
node <skill_dir>/scripts/validate-samples.mjs
This walks samples/**/*.json, parses each file, and runs lightweight local checks for common mistakes: malformed raw_text and rich_text, table/data-table row shape, minimum data-visualization fields, duplicate block_id/action_id, wrapped or HTML-encoded URL fields, and missing container/image essentials. It is not a full Slack schema validator.
Markdown Blocks
Use type: "markdown" for Slack's newer Markdown block when the content needs common Markdown features such as headings, horizontal rules, fenced code blocks, tables, blockquotes, and inline formatting.
This is distinct from legacy mrkdwn text objects used inside section and context blocks. Use samples/blocks/markdown.json for a compact mixed example.
Agent Blocks
Use samples/blocks/agents/ for agent-facing Slack blocks such as plans, task cards, and feedback controls.
Common blocks:
plan: groups multiple task steps under a shared goaltask_card: shows one task with status, details, output, and sourcesmessage_feedback: compact feedback controls; the underlying Slack block type iscontext_actions
Normalize source and link URLs to plain strings before posting.
Containers
Containers are wrapper blocks with child_blocks. Use them for grouped layouts that need a title, subtitle, icon, width control, or collapsible body.
Common fields:
type: "container"title: plain text titlesubtitle: optional plain text subtitleicon: optional image iconwidth:standardorfullis_collapsible: true when the container can collapsedefault_collapsed: initial collapsed statechild_blocks: nested Slack blocks
Nested child blocks still need valid block_id values when they are referenced by interactions or diagnostics.
Data Visualization
Use data_visualization for native Slack charts.
Common fields:
type: "data_visualization"block_id: stable chart block idtitle: chart title stringchart.type: chart type, such asline,bar,area, orpiechart.series: one or more named series for axis-based chartschart.series[].data: label/value points for axis-based chartschart.axis_config.categories: x-axis category order for axis-based chartschart.axis_config.x_labelandchart.axis_config.y_label: axis labels for axis-based chartschart.segments: label/value segments for pie charts
Use separate samples for single-series, multi-series, and negative-value charts. Negative values are valid for line, bar, and area examples. Pie charts use segments, not series or axis_config.
Posting
For portable rich replies, use message(action="send", presentation=...). Current OpenClaw docs describe Slack message tool sends with presentation as Slack-rendered Block Kit sends.
For raw Slack Block Kit JSON, use Slack chat.postMessage directly. The OpenClaw message tool schema accepts presentation, not a top-level raw blocks array.
curl -s -X POST https://slack.com/api/chat.postMessage \
-H "Authorization: Bearer $SLACK_BOT_TOKEN" \
-H "Content-Type: application/json" \
-d "$(jq -n \
--arg channel "$CHANNEL_ID" \
--arg thread "$THREAD_TS" \
--arg text "JavaScript code block" \
--argjson blocks "$(cat samples/blocks/rich_text.json)" \
'{
channel: $channel,
thread_ts: $thread,
text: $text,
blocks: $blocks
}')"
Resolve the Slack bot token from the configured Slack account. OpenClaw supports channels.slack.botToken, per-account channels.slack.accounts.<accountId>.botToken, SecretRefs, and the default-account SLACK_BOT_TOKEN env fallback. The token needs chat:write, and the bot must be in the channel.
Do not print token values while copying or debugging the curl sample.
For portable Slack thread replies through the message tool, pass threadId or replyTo. Add replyBroadcast: true only when the thread reply should also appear in the parent channel; it maps to Slack reply_broadcast and is not supported for media uploads. Use topLevel: true or threadId: null to opt out of inherited Slack thread routing. For raw chat.postMessage, use Slack's thread_ts and reply_broadcast fields directly.
After sending, verify with Slack readback when this is a test or incident investigation. Prefer the OpenClaw message action read when available; otherwise use Slack API readback with the same channel and thread identifiers.
Tables
- Tabular data in Slack: financial summaries, comparison grids, status dashboards
- Markdown tables render poorly or not at all in Slack
- Use
scripts/table.mjsfor non-trivial tables - Use
tablefor compact rich-text tables - Use
data_tablefor larger datasets, paginated-style tables, or typed numeric values - Use
raw_numbercells insidedata_tablewhen Slack should sort numbers by value instead of text
Generate
Generate table JSON from headers + rows:
node <skill_dir>/scripts/table.mjs \
--headers '["Source","Amount","Status"]' \
--rows '[["Mochary","$11K","Pending"],["MHC","$13.4K","Invoiced"]]' \
--align '1:right' \
--compact --blocks-only
Options:
--headers '["H1","H2"]'- first row, bold by default--rows '[["a","b"],["c","d"]]'- data rows--json '{"headers":[...],"rows":[...]}'- single JSON input--stdin- read JSON from stdin--align '<col>:<left|center|right>,...'- column alignment, 0-indexed--wrap '<col>,...'- columns to wrap text--bold-headers- bold headers; this is the default--no-bold-headers- plain text headers--compact- minified JSON--blocks-only- output just the blocks array for API calls
Generated empty cells are converted to zero-width space automatically. For manual JSON, raw_text.text must be non-empty.
Constraints
scripts/table.mjsemits 1 table block per payload- Max 100 rows, max 20 columns; the generator enforces these limits
- Rows must all have the same column count
- Cells:
raw_textplain cells orrich_textrich cells - Empty text is not allowed; use zero-width space automatically
data_tablerows can mixraw_text,rich_text, and typed values such asraw_number
Combining Text + Table
Post your text message first via the message tool, then post the table in the same thread via Slack API. Or include a section block before the table in the native blocks array.
Gotchas
- Block Kit caps messages at 50 blocks; big tables/layouts may need splitting across multiple messages.
chat.postMessage.textis the notification/accessibility fallback; always include it even when sendingblocks.- Rich-text approximations do not scale to real columns; use
table,data_table, orscripts/table.mjsfor non-trivial tables. - For thread replies after subagent completion or session resume, pass the original
thread_tsexplicitly; do not rely on inherited routing. - Actions and inputs need unique
block_idandaction_idvalues when interactivity matters. - Confirm destructive or externally visible interactive workflows before wiring live buttons.
- Slack examples sometimes wrap URLs in mrkdwn angle brackets or encode
&; JSON payloads should use plain URL strings.
Manual Block Kit JSON
For non-table blocks or custom layouts, construct the JSON directly from the samples.
Cell with bold text:
{"type":"rich_text","elements":[{"type":"rich_text_section","elements":[{"type":"text","text":"Bold","style":{"bold":true}}]}]}
Plain text cell:
{"type":"raw_text","text":"Plain"}