fix(slack): use Block Kit markdown block type instead of legacy mrkdwn - #8554
fix(slack): use Block Kit markdown block type instead of legacy mrkdwn#8554shivasymbl wants to merge 1 commit into
Conversation
The Slack platform adapter was sending messages using the legacy mrkdwn
format which does not support tables. format_message() was converting
standard markdown (bold, links, headers) to mrkdwn before sending,
which corrupted the content when used with Block Kit markdown blocks.
Changes:
- send(): Use blocks=[{type: "markdown", text: raw_content}] for
rendering, keep format_message() output only as text fallback for
notifications and search
- edit_message(): Add blocks parameter to chat_update so streaming
response edits also use the markdown block type
- send_message_tool.py: Remove format_message() pre-conversion for
Slack, use markdown block in _send_slack() payload
The markdown block type natively renders standard markdown including
tables, bold, italic, code blocks, and links. Slack auto-translates
it to rich_text + table blocks on the client side.
Fixes NousResearch#8552
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
This is a great quality of life improvement, nice addition! Cherry picking this into my agent until it is merged, great job @shivasymbl |
|
The max message of a markdown block is 12,000 https://docs.slack.dev/reference/block-kit/blocks/markdown-block But, I don't think truncating a markdown message via I think the best way is to remove |
I've been using this as a cherry pick on top of my agent and you are definitely right, I have been able to prompt and give it memories such it respects that limit, but that's not a great use of precious memory/context, and the (somewhat) more deterministic fix (at least one that doesn't use memory slots) is def the right one. @shivasymbl - happy to make the change if you want or help you test |
|
Sure that would be great
…On Mon, Apr 20, 2026 at 1:07 AM Basit Mustafa ***@***.***> wrote:
*24601* left a comment (NousResearch/hermes-agent#8554)
<#8554?email_source=notifications&email_token=BTWU4LXZPA6CEXWYOSELUBL4WUTIVA5CNFSNUABFM5UWIORPF5TWS5BNNB2WEL2JONZXKZKDN5WW2ZLOOQXTIMRXGY3DMMZZGM42M4TFMFZW63VHNVSW45DJN5XKKZLWMVXHJNLQOJPWG33NNVSW45C7N5YGK3S7MNWGSY3L#issuecomment-4276663939>
The max message of a markdown block is 12,000 We need to update the
MAX_MESSAGE_LENGTH to be lower than this.
docs.slack.dev/reference/block-kit/blocks/markdown-block
But, I don't think truncating a markdown message via truncate_message is
a good idea. as it may break the markdown rendering. imagine the LLM is
sending a large table in markdown and you truncate it into multi parts and
send each by each.
I think the best way is to remove truncate_message also, just tell the
LLM that the message limit is 12,000 and let it break itself, also tell it
to send a csv file instead of large table. this way is simpler and safer.
I've been using this as a cherry pick on top of my agent and you are
definitely right, I have been able to prompt and give it memories such it
respects that limit, but that's not a great use of precious memory/context,
and the deterministic fix here is def the right one. @shivasymbl
<https://github.com/shivasymbl> - happy to make the change if you want or
help you test
—
Reply to this email directly, view it on GitHub
<#8554?email_source=notifications&email_token=BTWU4LXZPA6CEXWYOSELUBL4WUTIVA5CNFSNUABFM5UWIORPF5TWS5BNNB2WEL2JONZXKZKDN5WW2ZLOOQXTIMRXGY3DMMZZGM42M4TFMFZW63VHNVSW45DJN5XKKZLWMVXHJNLQOJPWG33NNVSW45C7N5YGK3S7MNWGSY3L#issuecomment-4276663939>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/BTWU4LWAGLSMHNKWTJLNYRT4WUTIVAVCNFSM6AAAAACXWIB4BKVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHM2DENZWGY3DGOJTHE>
.
You are receiving this because you were mentioned.Message ID:
***@***.***>
|
|
Thanks for the clear rendering diagnosis. The underlying default mrkdwn path still exists, but this patch needs substantial salvage on current main. Problems
Suggested changes
Automated hermes-sweeper review. |
Re-triage: the patch edits retired |
…arkdown Slack's Block Kit `markdown` block accepts standard markdown (tables, headers, task lists, fenced code with syntax highlighting, links) and lets Slack translate it natively — eliminating the lossy markdown→mrkdwn conversion for the rendered layout. Enable via platforms.slack.extra.markdown_blocks. Safety rails added on top of the original design: * opt-in (default off) — Slack documents the block for 'apps that use platform AI features' and does not guarantee availability across all app types / surfaces, so unconditional adoption is not safe yet * the mrkdwn-converted text field is ALWAYS kept as the notification/search/accessibility fallback * content over Slack's 12k cumulative markdown-block cap declines to the rich_blocks renderer / plain text path * the existing block-rejection retry (invalid_blocks / msg_too_long / too_many_blocks) re-sends the plain mrkdwn payload, so an unsupported surface degrades gracefully instead of dropping the message * when both modes are enabled, markdown_blocks is preferred over the local rich_blocks renderer; rich_blocks remains the fallback Adapted from #8554 by @shivasymbl — the original patched the deleted gateway/platforms/slack.py and switched unconditionally; reimplemented against the plugin adapter's _maybe_blocks/sanitize_blocks pipeline. Fixes #8552.
…arkdown Slack's Block Kit `markdown` block accepts standard markdown (tables, headers, task lists, fenced code with syntax highlighting, links) and lets Slack translate it natively — eliminating the lossy markdown→mrkdwn conversion for the rendered layout. Enable via platforms.slack.extra.markdown_blocks. Safety rails added on top of the original design: * opt-in (default off) — Slack documents the block for 'apps that use platform AI features' and does not guarantee availability across all app types / surfaces, so unconditional adoption is not safe yet * the mrkdwn-converted text field is ALWAYS kept as the notification/search/accessibility fallback * content over Slack's 12k cumulative markdown-block cap declines to the rich_blocks renderer / plain text path * the existing block-rejection retry (invalid_blocks / msg_too_long / too_many_blocks) re-sends the plain mrkdwn payload, so an unsupported surface degrades gracefully instead of dropping the message * when both modes are enabled, markdown_blocks is preferred over the local rich_blocks renderer; rich_blocks remains the fallback Adapted from #8554 by @shivasymbl — the original patched the deleted gateway/platforms/slack.py and switched unconditionally; reimplemented against the plugin adapter's _maybe_blocks/sanitize_blocks pipeline. Fixes #8552.
…arkdown Slack's Block Kit `markdown` block accepts standard markdown (tables, headers, task lists, fenced code with syntax highlighting, links) and lets Slack translate it natively — eliminating the lossy markdown→mrkdwn conversion for the rendered layout. Enable via platforms.slack.extra.markdown_blocks. Safety rails added on top of the original design: * opt-in (default off) — Slack documents the block for 'apps that use platform AI features' and does not guarantee availability across all app types / surfaces, so unconditional adoption is not safe yet * the mrkdwn-converted text field is ALWAYS kept as the notification/search/accessibility fallback * content over Slack's 12k cumulative markdown-block cap declines to the rich_blocks renderer / plain text path * the existing block-rejection retry (invalid_blocks / msg_too_long / too_many_blocks) re-sends the plain mrkdwn payload, so an unsupported surface degrades gracefully instead of dropping the message * when both modes are enabled, markdown_blocks is preferred over the local rich_blocks renderer; rich_blocks remains the fallback Adapted from #8554 by @shivasymbl — the original patched the deleted gateway/platforms/slack.py and switched unconditionally; reimplemented against the plugin adapter's _maybe_blocks/sanitize_blocks pipeline. Fixes #8552.
|
Merged via #70191 — your commit was cherry-picked/reapplied onto current main with your authorship preserved in git history: your markdown-block adoption landed as the opt-in markdown_blocks mode with your authorship — mrkdwn kept as default/fallback per plan-tier caveats. Thanks for the contribution! |
…arkdown Slack's Block Kit `markdown` block accepts standard markdown (tables, headers, task lists, fenced code with syntax highlighting, links) and lets Slack translate it natively — eliminating the lossy markdown→mrkdwn conversion for the rendered layout. Enable via platforms.slack.extra.markdown_blocks. Safety rails added on top of the original design: * opt-in (default off) — Slack documents the block for 'apps that use platform AI features' and does not guarantee availability across all app types / surfaces, so unconditional adoption is not safe yet * the mrkdwn-converted text field is ALWAYS kept as the notification/search/accessibility fallback * content over Slack's 12k cumulative markdown-block cap declines to the rich_blocks renderer / plain text path * the existing block-rejection retry (invalid_blocks / msg_too_long / too_many_blocks) re-sends the plain mrkdwn payload, so an unsupported surface degrades gracefully instead of dropping the message * when both modes are enabled, markdown_blocks is preferred over the local rich_blocks renderer; rich_blocks remains the fallback Adapted from NousResearch#8554 by @shivasymbl — the original patched the deleted gateway/platforms/slack.py and switched unconditionally; reimplemented against the plugin adapter's _maybe_blocks/sanitize_blocks pipeline. Fixes NousResearch#8552.
Summary
markdownblock type for Slack message rendering instead of legacymrkdwnformat_message()output only astextfallback for notifications/searchedit_message()to includeblocksinchat_update(streaming responses were bypassing the fix)format_message()pre-conversion insend_message_tool.pyfor SlackProblem
format_message()converts standard markdown to Slack's legacymrkdwnformat before sending:**bold**→*bold*[text](url)→<url|text>| table | rows |→ stripped/broken*bold*The legacy
mrkdwnformat does not support tables. Themarkdownblock type in Block Kit natively renders standard markdown including tables.The critical issue was that
edit_message()(used by the stream consumer to update responses in-place) was sending onlytextwith noblocks, so even after fixingsend(), the final streamed response reverted to legacy rendering.Changes
gateway/platforms/slack.pysend()blocks,format_message()→textfallback onlygateway/platforms/slack.pyedit_message()blocks=[{type: "markdown", text: content}]tochat_updatetools/send_message_tool.py_send_to_platform()format_message()call for Slacktools/send_message_tool.py_send_slack()mrkdwn: True→blocks: [{type: "markdown", text: message}]Test plan
thread_tsin blocks payloadedit_message()textfallbackFixes #8552
🤖 Generated with Claude Code