feat(gateway): multi-workspace Socket Mode support for Slack adapter - #6686
Closed
jordanhubbard wants to merge 1 commit into
Closed
jordanhubbard wants to merge 1 commit into
jordanhubbard wants to merge 1 commit into
Conversation
Transforms the Slack adapter from single-workspace to N:N Socket Mode, incorporating robustness improvements from PR #3928. ## Multi-workspace Socket Mode (core feature) - New _load_accounts() reads ~/.hermes/slack_accounts.json; each entry gets its own AsyncApp + AsyncSocketModeHandler (true parallel receive) - Falls back to SLACK_BOT_TOKEN + SLACK_APP_TOKEN env vars (backward compat) - Extracted _register_app_handlers(app) to register all Bolt handlers identically on each per-account app instance - Per-app-token scoped locks; self._app retained as primary fallback - State: _handlers Dict[name→handler], _socket_mode_tasks Dict[name→task], _apps Dict[name→AsyncApp], _token_lock_identities list ## Robustness (from PR #3928) - Graceful token degradation: auth_test() failures warn and skip the account rather than aborting connect(); fails only if zero accounts work - Persisted channel→team routing via slack_channel_teams.json: routing survives gateway restarts, eliminating post-restart channel_not_found - _record_channel_team() replaces direct _channel_team[] writes and persists on every new mapping - Metadata-aware client selection: _get_client(chat_id, metadata) resolves team_id from metadata before falling back to learned routing; all send/upload methods pass metadata through ## New tests - test_connect_skips_stale_saved_tokens: revoked token doesn't block startup - test_send_uses_persisted_channel_team_route: routing loaded from disk - test_records_channel_route_on_inbound_message: inbound writes to disk Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
jordanhubbard
force-pushed
the
feature/multi-workspace-socket-mode
branch
from
April 10, 2026 00:39
4a8b158 to
e3fcefb
Compare
9 tasks
Contributor
Author
|
Superseded by #13837, which rebases this feature onto current upstream/main (conflict-free) and consolidates it with Signal reactions/editing, agent budget reset after compression, and a Ctrl+D readline fix. Closing this PR in favor of the consolidated one. |
Contributor
|
Superseded by #13837 which rebases this work and adds Signal reactions, budget reset, and Ctrl+D fix. |
1 similar comment
Contributor
|
Superseded by #13837 which rebases this work and adds Signal reactions, budget reset, and Ctrl+D fix. |
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 does this PR do?
Transforms the Slack adapter from single-workspace Socket Mode to multi-workspace Socket Mode, enabling an agent to receive and respond to events from multiple Slack workspaces simultaneously via independent Socket Mode connections.
Also incorporates robustness improvements from PR #3928 (graceful token degradation + persisted channel routing).
Currently, Hermes supports sending to multiple workspaces via comma-separated `SLACK_BOT_TOKEN` values, but can only receive events from a single workspace (the one with `SLACK_APP_TOKEN`). This PR makes it N:N — receive from N, send to N.
Related Issue
N/A — feature request from production multi-workspace deployments.
Type of Change
Changes Made
`gateway/platforms/slack.py`
Multi-workspace Socket Mode (core feature):
Robustness improvements (from PR #3928):
State changes:
`docs/slack_accounts.example.json` (new)
Example configuration file showing the multi-workspace JSON format.
`docs/plans/2026-04-08-multi-workspace-socket-mode.md` (new)
Design document covering architecture, configuration, backward compatibility, and edge cases.
How to Test
Single workspace (backward compat — no changes needed)
Multi-workspace
```json
[
{
"name": "workspace-one",
"bot_token": "xoxb-...",
"app_token": "xapp-...",
"signing_secret": "..."
},
{
"name": "workspace-two",
"bot_token": "xoxb-...",
"app_token": "xapp-...",
"signing_secret": "..."
}
]
```
Robustness
Checklist
Code
Documentation & Housekeeping
Relation to other PRs
This PR supersedes the approach in PR #3928 (single Socket Mode + fixes) by solving the root cause: true N:N Socket Mode connections. It also incorporates the robustness patterns from #3928 (graceful token degradation, persisted routing, metadata-aware client selection).