Skip to content
Guides

OpenClaw Slack charts, tables and approvals

Native data visualisation blocks and their limits, the two-charts-per-message rule, native data tables with typed cells, the text fallback that never drops rows, plugin-owned modal submissions, and Slack-native exec and plugin approvals

7 min read

A chart in a Slack message used to mean rendering an image somewhere and uploading it. Slack now has native Block Kit blocks for charts and tables, and OpenClaw maps its portable presentation blocks straight onto them, with a text version riding along for everything that cannot draw a block. Here are the two native blocks with their limits and fallbacks, the modal path for plugins, and the approval buttons that let Slack act as an approval client.

Native charts

  • Slack's public data visualisation block renders line, bar, area and pie charts in messages, and OpenClaw maps the portable chart block, with a chart type, a title, categories, named series and an optional axis label, to that native shape with no extra OAuth scope, file upload, image renderer or Slack configuration beyond normal message access.
  • Slack's limits are enforced before native rendering: titles and axis labels at 50 characters, one to twelve positive segments for a pie, one to twelve uniquely named series and one to twenty shared categories for line, bar and area, labels at 20 characters, and one finite value per category in every series, with negatives allowed outside pies.
  • Every native chart carries a top-level text representation for screen readers, notifications, session mirroring and clients that cannot render the block, other channels receive that same deterministic chart data as text unless they advertise native chart support, and when Slack rejects a chart with an invalid-blocks error OpenClaw removes the rejected data blocks, keeps sibling controls and sends the complete chart as visible text.
  • Slack accepts at most two data visualisation blocks per message, a limit its public reference does not document, so a presentation with more valid charts keeps their order and continues native rendering in follow-up messages with no more than two per message; the developer launch documents the block as an app-facing feature with no paid-plan restriction, the Business Plus and Enterprise language applies to Slackbot's own AI chart generation, and charts are message-only blocks, not App Home, modal or Canvas content.
Only explicit presentation table blocks are promoted to native tables.

Native tables

Slack's current data table block renders rows and columns in messages, and OpenClaw maps an explicit portable table block, with a caption, headers, rows and an optional row-header column index, to it rather than to the legacy table block, again with no extra scope. Header and string cells become raw text cells, numeric cells become raw number cells with the finite value preserved for native sorting and filtering, and the row-header index marks that zero-based column as Slack row headers. The published limits are enforced first: one to twenty columns, one to a hundred data rows plus the header row, the same number of cells in every row, and at most ten thousand aggregate characters across all cells in one message. Several valid tables can render natively while the message stays inside that envelope; a table that cannot becomes complete deterministic text instead of losing rows or cells, text that exceeds one message goes out as ordered chunks for sends and slash responses, and a table edit fails with an explicit size error rather than silently truncating rows in an existing message. Every native table also carries its text representation, raw chart and table values stay literal in the fallback so a user mention in a cell does not become a real mention, and when Slack rejects native chart or table blocks OpenClaw removes every native data block in one bounded recovery step, retains valid siblings such as buttons and selects, and sends the complete text with Slack formatting disabled; slash-command delivery tracks Slack's five-call response budget and picks a complete plan that fits the remaining calls before each batch. Only explicit presentation table blocks are promoted, Markdown pipe tables remain authored text because OpenClaw does not guess at structure or cell types, trusted Slack-native producers can still pass raw blocks through the channel data with fallback text derived from valid raw cells, and pasted spreadsheet content arriving as a legacy table block is rendered as delimiter-safe TSV for agent input, thread context and read actions, with only native table blocks admitted from ordinary attachments.

Modals and approvals

  • Slack plugins with an interactive handler can receive modal submission and closed events before OpenClaw compacts the payload, by setting the callback ID to an openclaw-prefixed namespace and payload or by putting plugin interactive data in the modal's private metadata; the handler gets the interaction kind, normalised inputs and the raw state values, callback-ID routing alone invokes it, the user and session routing fields in the private metadata make the modal also produce an agent-visible event, and the agent receives a compact redacted interaction event that can carry a summary, a reference and data from the handler without the full form payload.
  • Slack can act as a native approval client with interactive buttons instead of falling back to the Web UI or the terminal: exec and plugin approvals render as Block Kit prompts, exec approval DMs go to the configured approvers or the command owners, plugin approvals use Slack-native buttons when Slack is the native client for the originating session or when plugin approvals route to a Slack session or target with approvers drawn from the channel allowlist, a named account's allowlist or the account default route, and exec-only approvers cannot approve plugin requests unless they are plugin approvers too.
  • The config path is the exec-approvals block with enabled, optional approvers falling back to the command owners, a target of dm, channel or both with dm as default, and agent and session filters; native exec approvals need enabled true or auto plus at least one resolved approver, leaving it unset or false disables native exec delivery without disabling native plugin approvals, shared exec and plugin forwarding stay separate and are suppressed only when Slack handles the request natively, the same-chat approve command still works where commands do, and for Enterprise Grid the originating event's validated workspace is retained for the prompt, the DM, the button callback and the final update, failing closed when the org-installed account lacks that scope.

OpenClaw on Slack is the channel post these surfaces extend, and OpenClaw Slack message behaviour the card and preview model they sit inside.

Why the text always rides along

A chart that only exists as a block disappears from notifications, screen readers and every other channel the session is mirrored to, which is why the deterministic text version is not optional and why a rejected block degrades to that text rather than to nothing. OpenClaw exec approvals covers the approval model these buttons drive, and OpenClaw Telegram rich messages and approvals the equivalent rich surfaces on Telegram.

On Diali

Slack is one of the channels Diali connects from the dashboard, with the runtime config generated and replaced at each release, so a hosted agent's charts, tables and approval prompts behave as described here without settings to edit by hand. Slack on Diali is the channel on Diali and Diali security the boundary that applies to every action a bot can take.

  • Two charts per message; extra charts spill into follow-ups.
  • A table that breaks the envelope becomes complete text, never fewer rows.
  • Approval buttons are the primary UX; the approve command is the fallback.
Get started

Stop reading about it, build one

Set up an agent, pick a channel, and have it working inside the app you already keep open.