Skip to content

fix(slack): prefer live send adapter for Slack - #47547

Closed
replygirl wants to merge 1 commit into
NousResearch:mainfrom
replygirl:fix/slack-send-message-multi-token
Closed

replygirl wants to merge 1 commit into
NousResearch:mainfrom
replygirl:fix/slack-send-message-multi-token

Conversation

@replygirl

Copy link
Copy Markdown
Contributor

Summary

  • prefer the live Slack gateway adapter for send_message delivery when it is available, so gateway-context sends use the adapter's workspace/channel client routing
  • keep standalone Slack HTTP delivery for cron/CLI/out-of-process callers when no live adapter is present
  • split comma-separated Slack bot token lists into individual Web API attempts instead of sending the literal comma-joined value
  • include focused Slack send regressions that do not require optional Telegram test dependencies

Why

Multi-workspace Slack gateways can have SLACK_BOT_TOKEN as a comma-separated token list, and the live Slack adapter also knows which workspace/client owns each inbound channel. The old standalone send_message path bypassed that live adapter and passed the whole comma-joined token string to chat.postMessage, which Slack rejects as invalid_auth.

Duplicate check

Before opening, I checked current open PRs for this exact issue:

  • "send_message" "Slack" "multi" — related but no direct live-adapter / comma-token fix
  • "slack_tokens.json" "send_message" — no results
  • "invalid_auth" "Slack" — no results
  • "live adapter" "Slack" — related cron/slack PRs, no duplicate of this send_message path

Test plan

  • python -m pytest tests/tools/test_send_message_slack.py -q -o 'addopts='
  • git diff --check
  • python -m py_compile tools/send_message_tool.py tests/tools/test_send_message_slack.py

Copilot AI review requested due to automatic review settings June 17, 2026 01:47

Copilot AI 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.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@alt-glitch alt-glitch added type/bug Something isn't working P2 Medium — degraded but workaround exists platform/slack Slack app adapter comp/agent Core agent runtime: loop, agent_init, prompt builder, context-compression, responses endpoint labels Jun 17, 2026
@teknium1

Copy link
Copy Markdown
Collaborator

Thanks for identifying the multi-workspace Slack delivery gap. The underlying bug remains on current main: tools/send_message_tool.py:1051-1062 always selects Slack's standalone sender, bypassing the live adapter; and plugins/platforms/slack/adapter.py:4317-4346 sends a comma-separated token list as one Bearer token.

Problems

  • The PR predates 5600105478ffde29d7566b45421b100eaa29c4ef, which moved _send_slack into plugins/platforms/slack/adapter.py; current main records the removed helper at tools/send_message_tool.py:1428-1429. The proposed implementation and tests therefore do not apply to the current ownership boundary.
  • The current live routing belongs in SlackAdapter.send(): it resolves a workspace-specific client through _channel_team and _team_clients at plugins/platforms/slack/adapter.py:1345-1410.

Suggested changes

  • Port the Slack branch in tools/send_message_tool.py:1051-1062 to _send_via_adapter, which already prefers a live adapter and falls back to standalone_sender_fn at tools/send_message_tool.py:713-760.
  • Move the token-list and OAuth-token-file fallback into plugins/platforms/slack/adapter.py:_standalone_send, with tests against that current API.

Automated hermes-sweeper review.

@teknium1 teknium1 added sweeper:risk-message-delivery Sweeper risk: may drop, duplicate, misroute, or suppress messages sweeper:blast-moderate Sweeper blast radius: moderate — a subsystem or single platform labels Jul 14, 2026
teknium1 pushed a commit that referenced this pull request Jul 23, 2026
…ndividually

Two related Slack delivery fixes for send_message text sends:

- Route Slack text delivery through _send_via_adapter so the live
  in-process gateway adapter (multi-workspace aware, channel→client
  mapping, adapter-side gates) is preferred, with the plugin's
  _standalone_send as the out-of-process fallback — matching how the
  media path already behaves.
- _standalone_send: SLACK_BOT_TOKEN can be a comma-separated list in
  multi-workspace installs and slack_tokens.json carries OAuth
  per-workspace tokens; the standalone Web-API path used to send the
  literal comma-joined string, which Slack rejects as invalid_auth.
  Try each token individually, retrying on token-scoped errors
  (invalid_auth / not_in_channel / channel_not_found …) and stopping on
  terminal ones. User-DM resolution (U…/W… targets) also tries each
  token.

Adapted from #47547 by @replygirl — the original patched the legacy
tools/send_message_tool.py::_send_slack helper, which moved to the
Slack plugin's _standalone_send in #41112.

Salvaged from #47547
teknium1 pushed a commit that referenced this pull request Jul 23, 2026
…ndividually

Two related Slack delivery fixes for send_message text sends:

- Route Slack text delivery through _send_via_adapter so the live
  in-process gateway adapter (multi-workspace aware, channel→client
  mapping, adapter-side gates) is preferred, with the plugin's
  _standalone_send as the out-of-process fallback — matching how the
  media path already behaves.
- _standalone_send: SLACK_BOT_TOKEN can be a comma-separated list in
  multi-workspace installs and slack_tokens.json carries OAuth
  per-workspace tokens; the standalone Web-API path used to send the
  literal comma-joined string, which Slack rejects as invalid_auth.
  Try each token individually, retrying on token-scoped errors
  (invalid_auth / not_in_channel / channel_not_found …) and stopping on
  terminal ones. User-DM resolution (U…/W… targets) also tries each
  token.

Adapted from #47547 by @replygirl — the original patched the legacy
tools/send_message_tool.py::_send_slack helper, which moved to the
Slack plugin's _standalone_send in #41112.

Salvaged from #47547
teknium1 pushed a commit that referenced this pull request Jul 23, 2026
…ndividually

Two related Slack delivery fixes for send_message text sends:

- Route Slack text delivery through _send_via_adapter so the live
  in-process gateway adapter (multi-workspace aware, channel→client
  mapping, adapter-side gates) is preferred, with the plugin's
  _standalone_send as the out-of-process fallback — matching how the
  media path already behaves.
- _standalone_send: SLACK_BOT_TOKEN can be a comma-separated list in
  multi-workspace installs and slack_tokens.json carries OAuth
  per-workspace tokens; the standalone Web-API path used to send the
  literal comma-joined string, which Slack rejects as invalid_auth.
  Try each token individually, retrying on token-scoped errors
  (invalid_auth / not_in_channel / channel_not_found …) and stopping on
  terminal ones. User-DM resolution (U…/W… targets) also tries each
  token.

Adapted from #47547 by @replygirl — the original patched the legacy
tools/send_message_tool.py::_send_slack helper, which moved to the
Slack plugin's _standalone_send in #41112.

Salvaged from #47547
teknium1 pushed a commit that referenced this pull request Jul 23, 2026
…ndividually

Two related Slack delivery fixes for send_message text sends:

- Route Slack text delivery through _send_via_adapter so the live
  in-process gateway adapter (multi-workspace aware, channel→client
  mapping, adapter-side gates) is preferred, with the plugin's
  _standalone_send as the out-of-process fallback — matching how the
  media path already behaves.
- _standalone_send: SLACK_BOT_TOKEN can be a comma-separated list in
  multi-workspace installs and slack_tokens.json carries OAuth
  per-workspace tokens; the standalone Web-API path used to send the
  literal comma-joined string, which Slack rejects as invalid_auth.
  Try each token individually, retrying on token-scoped errors
  (invalid_auth / not_in_channel / channel_not_found …) and stopping on
  terminal ones. User-DM resolution (U…/W… targets) also tries each
  token.

Adapted from #47547 by @replygirl — the original patched the legacy
tools/send_message_tool.py::_send_slack helper, which moved to the
Slack plugin's _standalone_send in #41112.

Salvaged from #47547
@teknium1

Copy link
Copy Markdown
Collaborator

Closing as superseded by #70196 (merged): already fixed on main — the send-path selection this targeted was reworked in the earlier waves (evidence in the PR report).

Thanks for the work — it's credited in #70196's summary.

@teknium1 teknium1 closed this Jul 23, 2026
randlee pushed a commit to randlee/hermes-agent that referenced this pull request Aug 11, 2026
…ndividually

Two related Slack delivery fixes for send_message text sends:

- Route Slack text delivery through _send_via_adapter so the live
  in-process gateway adapter (multi-workspace aware, channel→client
  mapping, adapter-side gates) is preferred, with the plugin's
  _standalone_send as the out-of-process fallback — matching how the
  media path already behaves.
- _standalone_send: SLACK_BOT_TOKEN can be a comma-separated list in
  multi-workspace installs and slack_tokens.json carries OAuth
  per-workspace tokens; the standalone Web-API path used to send the
  literal comma-joined string, which Slack rejects as invalid_auth.
  Try each token individually, retrying on token-scoped errors
  (invalid_auth / not_in_channel / channel_not_found …) and stopping on
  terminal ones. User-DM resolution (U…/W… targets) also tries each
  token.

Adapted from NousResearch#47547 by @replygirl — the original patched the legacy
tools/send_message_tool.py::_send_slack helper, which moved to the
Slack plugin's _standalone_send in NousResearch#41112.

Salvaged from NousResearch#47547
prmartinow pushed a commit to prmartinow/hermes-agent that referenced this pull request Aug 26, 2026
…ndividually

Two related Slack delivery fixes for send_message text sends:

- Route Slack text delivery through _send_via_adapter so the live
  in-process gateway adapter (multi-workspace aware, channel→client
  mapping, adapter-side gates) is preferred, with the plugin's
  _standalone_send as the out-of-process fallback — matching how the
  media path already behaves.
- _standalone_send: SLACK_BOT_TOKEN can be a comma-separated list in
  multi-workspace installs and slack_tokens.json carries OAuth
  per-workspace tokens; the standalone Web-API path used to send the
  literal comma-joined string, which Slack rejects as invalid_auth.
  Try each token individually, retrying on token-scoped errors
  (invalid_auth / not_in_channel / channel_not_found …) and stopping on
  terminal ones. User-DM resolution (U…/W… targets) also tries each
  token.

Adapted from NousResearch#47547 by @replygirl — the original patched the legacy
tools/send_message_tool.py::_send_slack helper, which moved to the
Slack plugin's _standalone_send in NousResearch#41112.

Salvaged from NousResearch#47547
melon-xf added a commit to melon-xf/hermes-agent that referenced this pull request Sep 3, 2026
…ndividually

Two related Slack delivery fixes for send_message text sends:

- Route Slack text delivery through _send_via_adapter so the live
  in-process gateway adapter (multi-workspace aware, channel→client
  mapping, adapter-side gates) is preferred, with the plugin's
  _standalone_send as the out-of-process fallback — matching how the
  media path already behaves.
- _standalone_send: SLACK_BOT_TOKEN can be a comma-separated list in
  multi-workspace installs and slack_tokens.json carries OAuth
  per-workspace tokens; the standalone Web-API path used to send the
  literal comma-joined string, which Slack rejects as invalid_auth.
  Try each token individually, retrying on token-scoped errors
  (invalid_auth / not_in_channel / channel_not_found …) and stopping on
  terminal ones. User-DM resolution (U…/W… targets) also tries each
  token.

Adapted from NousResearch#47547 by @replygirl — the original patched the legacy
tools/send_message_tool.py::_send_slack helper, which moved to the
Slack plugin's _standalone_send in NousResearch#41112.

Salvaged from NousResearch#47547
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

comp/agent Core agent runtime: loop, agent_init, prompt builder, context-compression, responses endpoint P2 Medium — degraded but workaround exists platform/slack Slack app adapter sweeper:blast-moderate Sweeper blast radius: moderate — a subsystem or single platform sweeper:risk-message-delivery Sweeper risk: may drop, duplicate, misroute, or suppress messages type/bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants