feat(slack): opt-in Block Kit rendering for agent messages - #56090
Closed
benbarclay wants to merge 2 commits into
Closed
feat(slack): opt-in Block Kit rendering for agent messages#56090benbarclay wants to merge 2 commits into
benbarclay wants to merge 2 commits into
Conversation
Add platforms.slack.extra.rich_blocks (default off). When enabled, the final agent message is sent as Slack Block Kit blocks — section headers, dividers, and true nested lists via rich_text — instead of flat mrkdwn. - New plugins/platforms/slack/block_kit.py: pure markdown->blocks renderer (headers, dividers, nested ordered/bullet lists, blockquotes, fenced code; pipe-tables as aligned monospace since Block Kit has no robust table block). Enforces Slack's 50-block / 3000-char section limits and returns None to fall back to plain text on empty/oversized/unexpected input. Never raises. - adapter.send(): render blocks on the single-chunk primary message; a text= fallback is ALWAYS sent alongside (notifications/accessibility). - adapter.edit_message(): blocks only on finalize=True, so intermediate streaming edits stay plain mrkdwn (no per-flush block re-derivation). - Docs (EN + zh-Hans) + config example. Send-side only: no app reinstall. Tests: pure-renderer unit suite + adapter integration suite (blocks present when on, plain text when off, text fallback always set, finalize gating, multi-chunk fallback). Prove-failed against a stubbed renderer.
Replace the interim monospace table fallback with Slack's native `table` block (rows of rich_text cells). Addresses the core ask in #18918. - _table_block(): builds type:"table" with rich_text cells, so inline formatting (bold, links, code) renders inside cells. - Column alignment parsed from the markdown separator row (:---, :-:, --:) into column_settings (left = default/null-skip, center/right emitted). - Escaped pipes (\\|) are not treated as column separators. - Respects Slack's table limits (100 rows / 20 cols / 10k aggregate chars); oversized or unparseable tables gracefully fall back to aligned monospace (rich_text_preformatted), so a big table never breaks the message. Docs (EN + zh-Hans) updated to describe native tables + the fallback. Tests: native table shape, alignment->column_settings, inline-formatted cells, oversized/too-wide monospace fallback, escaped-pipe cell. Prove- failed against a stubbed _table_block (native-table tests fail, fallback tests stay green). All existing Slack tests still pass.
Contributor
hashbender
added a commit
to hashbender/hermes-agent
that referenced
this pull request
Jul 1, 2026
…ousResearch#56090) (#182) Co-authored-by: qbit-mirror-bot <qbit-mirror-bot@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Opt-in Slack Block Kit rendering for agent messages. Today every Slack reply goes out as flat mrkdwn
text. Teams that use Slack blocks heavily in their workflows want the richer structure — section headers, dividers, true nested lists, and native tables. This adds that behind a config flag.Renders the primary agent message as structured blocks (headers, dividers,
rich_textnested lists, blockquotes, code, and nativetableblocks). Also fixes the long-standing #18918 (render Markdown pipe tables as native Slack tables — 13 👍).Enable it:
platforms.slack.extra.rich_blocks: true(default off — zero behavior change unless flipped).How
plugins/platforms/slack/block_kit.py— a pure, self-containedrender_blocks(markdown)function (no adapter state, no Slack client). Renders:#headers →headerblocks---→dividerblocksrich_text_listwith true nesting (indent levels)rich_text_quoterich_text_preformattedtableblocks (see below)adapter.send()renders blocks on the single-chunk primary message; atext=fallback is always sent alongside (notifications / accessibility / old clients).adapter.edit_message()renders blocks only onfinalize=True, so intermediate streaming edits stay plain mrkdwn — no per-flush block re-derivation, no streaming jank.None(→ plain-text fallback) on empty / oversized / unexpected input. It never raises — a rendering bug can never drop a message.Tables (native
tableblock)Markdown pipe tables render as Slack's native
tableblock — real grid cells, not monospace text:rich_text, so inline formatting works inside a cell (bold, links, code, emoji).:---/:-:/--:) intocolumn_settings(left is the default and emitted asnullto skip; center/right emitted explicitly).\|) are kept as literal cell content, not column separators.rich_text_preformatted), so a large table never breaks the message.Scope / caveats
send()path and render fully. With streaming on, blocks apply on the final edit only.Follow-up (optional)
Slack also has a newer
markdownblock that renders GFM directly (including tables). Not used here — the explicittable-block path gives deterministic control over alignment, cell formatting, and the over-limit fallback — but it's a viable alternative worth a look if we ever want Slack to own more of the markdown rendering.Tests
tests/gateway/test_slack_block_kit.py— pure-renderer unit suite (headers, dividers, nested-list indent contract, ordered/bullet distinction, inline styling; native table shape, alignment→column_settings, inline-formatted cells, oversized/too-wide → monospace fallback, escaped-pipe cell; 50-block/3000-char limits; never-raises-on-garbage).tests/gateway/test_slack_block_kit_adapter.py— adapter integration: blocks present when on, no blocks + plain text when off,textfallback always set,finalizegating on edits, multi-chunk fallback, string-"true"coercion.render_blocksand_table_block): the relevant assertions fail without the real code; fallback-path tests correctly stay green. All 216 existing Slack tests still pass.rich_blocksoff cleanly reverts to plain mrkdwn.Docs
website/docs/user-guide/messaging/slack.md+ zh-Hans i18n: config example + key-table row, describing native tables and the monospace fallback.Closes #18918.