Slack Stop button on the progress message (CHOO-2589) - #374
Open
abeldantas wants to merge 1 commit into
Open
Conversation
An agent's Slack progress surface now carries a Stop button that interrupts the running turn, wired to the same `!interrupt` path the room command uses. The button appears on both the native streaming card (as a button-only message beside it) and the posted working message (agent_sessions: false path), and is cleaned up when the turn ends so a stale button never lingers. The adapter handles `block_actions` interactive payloads via Socket Mode (interactivity is already enabled in the manifest). A click after the turn has ended returns a soft "that turn already finished" rather than firing a command.
abeldantas
requested review from
amaudruz and
christian-mcdermott
as code owners
September 4, 2026 16:34
Contributor
There was a problem hiding this comment.
🟡 Changes recommended
The Slack Stop button implementation currently breaks/degenerates in key flows (non-session-card turns and indicator repositioning), and the docs edits are under docs/official/ which is generated and will be overwritten.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Pull request overview
This PR adds an interactive Stop control to Slack’s agent progress surfaces so operators can interrupt a running turn via a message button, and introduces a capability flag (supports_interactive_stop) to advertise that support at the adapter level.
Changes:
- Adds a Slack Block Kit Stop button to both the native streaming card path (via a minimal companion message) and the non-card “working” message path.
- Routes Slack Socket Mode
interactive/block_actionspayloads to the existing interrupt command flow. - Introduces
supports_interactive_stopcapability on the base collaboration adapter and exposes it via the collaboration lifecycle service.
File summaries
| File | Description |
|---|---|
| docs/official/resources/room-commands.md | Documents the Slack Stop button as an alternative to !interrupt. |
| docs/official/deploy/messaging-apps/slack.md | Updates Slack progress documentation to mention the Stop button. |
| core/tests/switch_core/bridges/collaboration/test_slack_agent_sessions.py | Adds/updates tests asserting Stop button blocks, interactive handling, and cleanup behavior. |
| core/switch_core/bridges/collaboration/slack/adapter.py | Implements Stop button blocks, block action routing, and streaming/non-streaming progress updates. |
| core/switch_core/bridges/collaboration/lifecycle_service.py | Adds a supports_interactive_stop(...) capability query. |
| core/switch_core/bridges/collaboration/adapter.py | Declares the base supports_interactive_stop capability (default False). |
Review details
- Files reviewed: 6/6 changed files
- Comments generated: 5
- Review effort level: Lite
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Comment on lines
+767
to
+770
| existing = self._working_msg.get(key) | ||
| if existing is not None and existing.body == "": | ||
| # Already have a button-only message; nothing to do. | ||
| return |
Comment on lines
787
to
791
| body = self._working_body(detail, deeplink_url) | ||
| blocks = self._stop_button_blocks(agent_name, body) | ||
| existing = self._working_msg.get(key) | ||
| if existing is not None: | ||
| # Refresh the live message in place with the latest activity. |
Comment on lines
+1371
to
+1380
| agent_name = str(action.get("value") or "") or self._session_owner.get( | ||
| (channel_id, thread_ts), "" | ||
| ) | ||
| if not agent_name or (channel_id, thread_ts) not in self._session_owner: | ||
| await self.admin_message( | ||
| channel_id, | ||
| "That turn already finished.", | ||
| thread_root_id=f"{channel_id}:{thread_ts}", | ||
| ) | ||
| return |
| While an agent is working, Slack draws a live progress card under the agent's own name and icon, linking back to the session in Switch Console. It's an indicator rather than a record, so it goes when the turn ends. This is what declaring the app an **Agent** in the manifest buys you. | ||
|
|
||
| Where the card can't be drawn, Switch posts a status message under the agent's name carrying the same **Open in Switch Console** link, so a turn always shows its progress somewhere. | ||
| Where the card can't be drawn, Switch posts a status message under the agent's name carrying the same **Open in Switch Console** link, so a turn always shows its progress somewhere. In both cases the progress message carries a **Stop** button that interrupts the running turn (no manifest change needed — interactivity is already enabled). |
| !interrupt @agent-name | ||
| ``` | ||
|
|
||
| On Slack, the agent's progress message carries a **Stop** button that does the same thing — click it instead of typing the command. |
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.
Summary
block_actionsinteractive payloads via Socket Mode, routingswitch_interruptclicks to the existing!interruptcommand pathsupports_interactive_stopon the base adapter (False) and sets it True on Slack only, following the existing capability family patternBefore / Now
Before: interrupting a turn from Slack required typing
!interrupt @agentor/interrupt @agentin the channel.Now: the agent's progress message carries a red Stop button. Click it and the turn stops within a beat. Clicking after the turn ended gives a soft "that turn already finished" response. No Slack app manifest change needed.
Test plan
uv run pytest core/tests/switch_core/bridges/collaboration/ -q-- 994 passedruff format --check .andruff check .-- cleanmypy-- clean