Skip to content

feat(slack): add gateway.slack.unfurl to suppress link previews - #34302

Open
davecazz wants to merge 1 commit into
NousResearch:mainfrom
davecazz:dave/slack-disable-unfurl
Open

feat(slack): add gateway.slack.unfurl to suppress link previews#34302
davecazz wants to merge 1 commit into
NousResearch:mainfrom
davecazz:dave/slack-disable-unfurl

Conversation

@davecazz

Copy link
Copy Markdown

Summary

Bot accounts that post a lot of URLs — news feeds, digests, alerts — flood channels with Slack's link/media preview cards, and there's currently no way to turn that off. chat.postMessage is always called without unfurl flags, so Slack applies its default unfurling.

This adds a gateway.slack.unfurl option (default true, so existing behavior is unchanged). When set to false, the bot's posts pass unfurl_links=False / unfurl_media=False and posted URLs no longer expand into preview cards.

Changes

  • gateway/config.py — bridge the top-level slack.unfurl key into PlatformConfig.extra (mirrors reply_in_thread / require_mention). The canonical platforms.slack.extra.unfurl form also works.
  • gateway/platforms/slack.pysend() reads extra.unfurl (default true) and only sets the unfurl flags when disabled, so the default path is byte-for-byte unchanged.
  • tests/gateway/test_slack.py — send behavior with unfurl off vs. default (no flags), plus a YAML→extra bridge test.
  • website/docs/user-guide/messaging/slack.md — new "Link Previews" section.

Config

platforms:
  slack:
    extra:
      unfurl: false   # default: true

(or the top-level slack.unfurl: false shorthand)

Testing

pytest tests/gateway/test_slack.py tests/tools/test_send_message_tool.py
# 311 passed

🤖 Generated with Claude Code

Bot accounts that post many URLs (news feeds, digests, alerts) flood
channels with Slack's link/media preview cards, and there's currently no
way to turn that off — chat.postMessage is always called without unfurl
flags, so Slack applies its default unfurling.

Add a gateway.slack.unfurl option (default true, so existing behavior is
unchanged). When false, the bot's posts pass unfurl_links/unfurl_media
False and posted URLs no longer expand into preview cards.

- config.py: bridge top-level slack.unfurl into PlatformConfig.extra
  (mirrors reply_in_thread/require_mention); platforms.slack.extra.unfurl
  also works
- platforms/slack.py: send() honors the flag, default true
- tests: send behavior (off/default) + YAML->extra bridge
- docs: "Link Previews" section in slack.md

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@alt-glitch alt-glitch added type/feature New feature or request comp/gateway Gateway runner, session dispatch, delivery platform/slack Slack app adapter area/config Config system, migrations, profiles P3 Low — cosmetic, nice to have labels May 29, 2026

@teknium1 teknium1 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the focused, backward-compatible Slack configuration proposal. The need still exists on current main: plugins/platforms/slack/adapter.py:1397-1410 posts regular messages without unfurl_links or unfurl_media.

Problems

  • The patch targets gateway/platforms/slack.py, but commit 5600105478ffde29d7566b45421b100eaa29c4ef migrated Slack into plugins/platforms/slack/adapter.py; the current send implementation is at plugins/platforms/slack/adapter.py:1352-1433.
  • Slack-specific top-level YAML translation now belongs to the plugin hook at plugins/platforms/slack/adapter.py:4485-4519, dispatched by gateway/config.py:1269-1304; the proposed core config bridge should move there.
  • plugins/platforms/slack/adapter.py:4297-4354 separately posts out-of-process deliver=slack cron messages. It also needs the resolved option so cron posts do not bypass the setting.

Suggested changes

  • Port the setting and tests to the plugin adapter, including _standalone_send() and the plugin YAML bridge. Preserve omitted Slack API kwargs for the default behavior.

Automated hermes-sweeper review.

Comment thread gateway/config.py
bridged["reply_in_thread"] = platform_cfg["reply_in_thread"]
if "require_mention" in platform_cfg:
bridged["require_mention"] = platform_cfg["require_mention"]
if plat == Platform.SLACK and "unfurl" in platform_cfg:

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Current main moved Slack-specific YAML translation into the Slack plugin hook (plugins/platforms/slack/adapter.py::_apply_yaml_config); port this shorthand bridge there rather than adding a new Slack exception back to gateway core.

for i, chunk in enumerate(chunks):
kwargs = {
"channel": chat_id,
"text": chunk,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This adapter path was moved to plugins/platforms/slack/adapter.py by 560010547; port the send change there and also cover that plugin's _standalone_send() cron delivery path.

@teknium1 teknium1 added sweeper:risk-message-delivery Sweeper risk: may drop, duplicate, misroute, or suppress messages sweeper:risk-compatibility Sweeper risk: may break existing users, config, migrations, defaults, or upgrades sweeper:blast-moderate Sweeper blast radius: moderate — a subsystem or single platform labels Jul 13, 2026

@GottZ GottZ left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was generated by AI during triage.

Summary

Two PRs address Slack link-preview suppression: #34302 adds one backward-compatible unfurl switch that disables both Slack unfurl kwargs, while #46482 adds separate unfurl_links and unfurl_media controls. Both diffs target the pre-plugin Slack send path and therefore require porting to the current adapter to resolve the reported cause on current main.

Related pull requests

  • #34302 related — (+75/-1) — keep open and update: The diff directly addresses the cause by conditionally passing unfurl_links=False and unfurl_media=False, with config bridging, tests, and documentation, but it modifies the retired gateway/platforms/slack.py path. Consistent with the contributor keep_open review, it must be ported to plugins/platforms/slack/adapter.py, including the plugin YAML bridge and _standalone_send() cron path, before merge.
  • #46482 [closed] duplicate — (+50/-0) — closed duplicate, still relevant as an alternative implementation reference: The diff independently controls unfurl_links and unfurl_media and preserves Slack defaults when omitted, but it also modifies the retired gateway adapter and does not cover the current plugin or standalone cron send path. Its author closed it after the contributor identified it as duplicating the earlier #34302.

Duplicates

#34302 and #46482 implement substantially the same Slack unfurl configuration; #46482 is the later, already-closed duplicate of #34302.

Suggested consolidation

Update and merge #34302 as the consolidation target after porting the implementation and tests to the current Slack plugin adapter, covering both regular and standalone cron sends while preserving omitted kwargs by default. Keep #46482 closed as a duplicate; its separate-link/media option design can be considered while revising #34302, but its stale-path diff should not be merged independently.

Complex graph

flowchart LR
    classDef open fill:#dbeafe,stroke:#1d4ed8,color:#1e3a8a
    classDef merged fill:#dcfce7,stroke:#15803d,color:#14532d
    classDef closed fill:#e5e7eb,stroke:#6b7280,color:#1f2937
    classDef unverified fill:#f3f4f6,stroke:#9ca3af,color:#374151
    classDef best stroke-width:3px,stroke:#b45309
    classDef target stroke-width:3px,stroke:#4338ca
    subgraph Dup34302 ["PRs duplicating each other"]
        P34302["PR #34302 (open)"]
        P46482["PR #46482 (closed)"]
    end
    class P34302 open
    class P46482 closed
    class P34302 target
    click P34302 "https://github.com/NousResearch/hermes-agent/pull/34302"
    click P46482 "https://github.com/NousResearch/hermes-agent/pull/46482"
Loading

Graph: solid arrow = fixes / best fix, dashed arrow = partial or unverified (see edge label); boxed group = PRs duplicating each other; amber border = best fix; indigo border = target; gray node = closed or no verify verdict yet (state tag in the node label).

Cross-PR triage: Reviewed 2 pull requests and 0 issues in this complex. Each diff was read against this issue; Assessment working set: 13 kB of PR diffs, 4 kB of issue/PR text, 2 kB of discussion (4 comments), 1 verify verdict. verdicts reflect diff content, not PR titles. Part of an automated triage batch.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/config Config system, migrations, profiles comp/gateway Gateway runner, session dispatch, delivery P3 Low — cosmetic, nice to have platform/slack Slack app adapter sweeper:blast-moderate Sweeper blast radius: moderate — a subsystem or single platform sweeper:risk-compatibility Sweeper risk: may break existing users, config, migrations, defaults, or upgrades sweeper:risk-message-delivery Sweeper risk: may drop, duplicate, misroute, or suppress messages type/feature New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants