feat(slack): implement on_broadcast and fix message tool hints - #2113
Conversation
There was a problem hiding this comment.
Code Review
This pull request implements the on_broadcast functionality for the Slack channel, enabling the agent to send proactive messages. It introduces helper functions for target resolution and payload construction, adds unit tests for these helpers, and updates the MessageTool schema description. A review comment suggests tracking these broadcasted messages in the active threads registry to ensure the agent can correctly handle subsequent replies in those threads.
| .unwrap_or_else(|| "unknown".to_string()) | ||
| )); | ||
| } | ||
|
|
There was a problem hiding this comment.
Proactive messages sent via on_broadcast should be tracked in the active threads registry, similar to how on_respond handles them. This ensures that if a user replies to the proactive message, the agent will be able to receive and process the reply even if it isn't explicitly mentioned (as the bot is now a participant in that thread).
| if let Some(ts) = response.thread_id.as_deref().or(slack_response.ts.as_deref()) { | |
| track_active_thread(&target, ts)?; | |
| } | |
45a28f1 to
27a994e
Compare
Implement the on_broadcast callback for the Slack WASM channel, enabling proactive message delivery to Slack channels/users via the message tool. Previously this was a stub returning "not implemented". The implementation: - Uses the user_id parameter as the broadcast target (channel ID or user ID) - Strips leading # from targets for convenience - Warns when target doesn't look like a Slack ID (C/U/D/G prefix) - Posts via chat.postMessage with host-injected Bearer token - Tracks active threads for broadcast replies (consistent with on_respond) Also fixes the message tool's channel parameter description to list 'slack' alongside 'slack-relay' and clarifies that Slack targets must be IDs. [skip-regression-check] Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
27a994e to
c61e279
Compare
Address review findings on the slack broadcast implementation: - Extract `post_slack_message()` shared by `on_respond` and `on_broadcast`, eliminating ~40 lines of duplicated HTTP-call-then-parse logic. - Log `track_active_thread` errors at Warn level instead of silently swallowing them with `let _ =` (restores observability lost in original). - Make non-ID broadcast targets a hard error instead of a soft warning — consistent with the message tool schema that says "must be an ID, not a name". - Fix empty-target error message to not assume a name was provided. - `resolve_broadcast_target` now returns `&str` (avoids allocation). - Add 2 tests covering the resolve+validate pipeline end-to-end. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Address Gemini review: broadcast messages now track the Slack-returned timestamp as an active thread (falling back from response.thread_id to the posted message ts). This ensures that if a user replies to a broadcast, the agent recognizes the reply as an active thread. Also fix stale doc comment on looks_like_slack_id (was missing W prefix). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Code reviewFound 6 issues:
Recommendation: Validate entire string with full alphanumeric check or use regex like
Recommendation: Remove the second
|
…i#2113) * feat(slack): implement on_broadcast and fix message tool channel hints Implement the on_broadcast callback for the Slack WASM channel, enabling proactive message delivery to Slack channels/users via the message tool. Previously this was a stub returning "not implemented". The implementation: - Uses the user_id parameter as the broadcast target (channel ID or user ID) - Strips leading # from targets for convenience - Warns when target doesn't look like a Slack ID (C/U/D/G prefix) - Posts via chat.postMessage with host-injected Bearer token - Tracks active threads for broadcast replies (consistent with on_respond) Also fixes the message tool's channel parameter description to list 'slack' alongside 'slack-relay' and clarifies that Slack targets must be IDs. [skip-regression-check] Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix(slack): extract shared post helper, harden broadcast validation Address review findings on the slack broadcast implementation: - Extract `post_slack_message()` shared by `on_respond` and `on_broadcast`, eliminating ~40 lines of duplicated HTTP-call-then-parse logic. - Log `track_active_thread` errors at Warn level instead of silently swallowing them with `let _ =` (restores observability lost in original). - Make non-ID broadcast targets a hard error instead of a soft warning — consistent with the message tool schema that says "must be an ID, not a name". - Fix empty-target error message to not assume a name was provided. - `resolve_broadcast_target` now returns `&str` (avoids allocation). - Add 2 tests covering the resolve+validate pipeline end-to-end. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix(slack): track broadcast message ts so replies are recognized Address Gemini review: broadcast messages now track the Slack-returned timestamp as an active thread (falling back from response.thread_id to the posted message ts). This ensures that if a user replies to a broadcast, the agent recognizes the reply as an active thread. Also fix stale doc comment on looks_like_slack_id (was missing W prefix). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Summary
on_broadcastin the Slack WASM channel (channels-src/slack/src/lib.rs): the agent can now send proactive messages to arbitrary Slack channels/users via themessagetool. Theuser_idparameter carries the broadcast target (e.g.#general,C0123ABC,U0123); a leading#is stripped since the Slack API expects bare names or IDs.src/tools/builtin/message.rs): replace'slack-relay'with'slack'and clarify that "target" refers to Slack channels (not "Slack channel ID").resolve_broadcast_target,build_broadcast_payload).Test plan
cargo testinchannels-src/slack/passes (16 tests including 5 new)cargo clippyinchannels-src/slack/passes with zero warningscargo fmtinchannels-src/slack/passescargo clippy --all --benches --tests --examples --all-featurespasses in main repocargo testpasses in main repo (pre-existinge2e_spot_checksSIGABRT confirmed on staging)messagetool targeting a Slack channel to verify end-to-end🤖 Generated with Claude Code