<@U090ER7JPHA> When OpenHands agent is called from...
# slackbot-chatter
c
@nutritious-balloon-65098 When OpenHands agent is called from slack, it will respond in the same slack thread. If the user sends another message in that thread, it goes to the same conversation, and the agent responds again in the same thread. But if the user goes to the Web UI, finds that conversation, and sends a message to it, then the application does the same: it sends agent's response still on Slack too in that thread. I think it shouldn't: once the user started to talk in the presumed privacy of a conversation via other means, it should STOP responding in slack thread. Investigate the codebase, create an issue on this and propose a fix, both sketch it in the issue and propose a PR on it.
n
I'm on it! can track my progress here.
## Final Summary ### What Was Done I investigated and fixed a privacy issue with the Slack integration where agent responses were still being posted to Slack even after a user moved their conversation to the Web UI. ### Deliverables Created 1. GitHub Issue [#12863](https://github.com/OpenHands/OpenHands/issues/12863) - Documents the privacy concern with technical analysis and proposed solution 2. Pull Request [#12864](https://github.com/OpenHands/OpenHands/pull/12864) - Implements the fix (already pushed to
fix/slack-privacy-callback
branch) ### Checklist - ✅ Investigated the codebase to understand how Slack callbacks work - ✅ Created a GitHub issue documenting the problem - ✅ Proposed a fix in the issue description - ✅ Implemented the fix in a PR - ✅ Changes are concise and focused only on the privacy fix - ✅ Added tests for the new functionality - ✅ Code passes syntax validation - ✅ Pushed changes to remote branch ### Changes Made (5 files) | File | Change | |------|--------| |
slack_callback_processor.py
| Added
last_slack_message_content
field + privacy check | |
slack_view.py
| Track message content when sending follow-up messages from Slack | |
slack_manager.py
| Set initial message content when registering new callbacks | |
conversation_callback_utils.py
| Added
update_callback_processor()
utility function | |
test_slack_callback_processor.py
| Added 3 test cases for the privacy feature | ### Note The fix applies to V0 conversations only. V1 conversations use a different callback system (
SlackV1CallbackProcessor
) and would need a similar fix in a follow-up PR if the same behavior exists there.
c
@nutritious-balloon-65098 actually please make sure you document in the issue how to fix it on V1, and open a new PR from main, with a V1 fix. Ultrathink. V1 matters, the rest is actually legacy
n
## Final Summary I've completed the investigation and implementation of the Slack callback privacy fix for both the V1 (current) and V0 (legacy) systems. ### Deliverables | Item | Link | |------|------| | Issue | [#12863](https://github.com/OpenHands/OpenHands/issues/12863) - Privacy: Slack callback should stop responding when user continues conversation via Web UI | | V1 PR (Priority) | [#12866](https://github.com/OpenHands/OpenHands/pull/12866) - fix(slack): add V1 privacy check for Slack callback responses | | V0 PR (Legacy) | [#12864](https://github.com/OpenHands/OpenHands/pull/12864) - fix(slack): stop Slack responses when user continues conversation via Web UI | ### Checklist - [x] Investigated the codebase to understand the Slack callback mechanism - [x] Created GitHub issue documenting the privacy concern with technical analysis - [x] Implemented V1 fix (priority - current system): - [x] Added
_should_respond_to_slack()
and
_get_last_user_message()
methods - [x] Added privacy check in
__call__
before sending to Slack - [x] Updated callback creation to track message content - [x] Updated follow-up message handling to update callback - [x] Added 4 tests for V1 - [x] Implemented V0 fix (legacy system): - [x] Added
last_slack_message_content
field and privacy check - [x] Added
update_callback_processor
utility function - [x] Added 3 tests for V0 - [x] Both fixes maintain backward compatibility - [x] Updated issue with V1 fix documentation - [x] Both branches pushed and PRs created ### How the Fix Works When a message is sent from Slack, its content is stored in the callback processor. When the callback fires (agent finishes), it compares the last user message with what was stored. If they don't match (user sent via Web UI), the callback skips posting to Slack, protecting user privacy.
c
@nutritious-balloon-65098 Out of curiosity, another LLM, GPT-5, asks why don’t we store a simple boolean if we really need to store something? Think about it, and tell me if that won’t work. GPT-5 could be wrong!
n
## Summary I've fully addressed the Slack callback privacy issue with the following deliverables: ### Issue Created [#12863](https://github.com/OpenHands/OpenHands/issues/12863) - Documents the privacy concern where Slack responses continue even when user switches to Web UI ### Pull Requests Created V1 Fix (Priority): [#12866](https://github.com/OpenHands/OpenHands/pull/12866) -
fix/slack-v1-privacy-callback
branch - Files modified:
slack_v1_callback_processor.py
,
slack_view.py
,
test_slack_v1_callback_processor.py
- Adds
_should_respond_to_slack()
and
_get_last_user_message()
methods - Tracks
last_slack_message_content
in
slack_view_data
- Updates callback when follow-up messages sent from Slack V0 Fix (Legacy): [#12864](https://github.com/OpenHands/OpenHands/pull/12864) -
fix/slack-privacy-callback
branch - Files modified:
slack_callback_processor.py
,
slack_view.py
,
slack_manager.py
,
conversation_callback_utils.py
,
test_slack_callback_processor.py
- Adds
last_slack_message_content
field to processor - Adds
update_callback_processor()
utility function ### Key Design Decision As discussed with GPT-5's question: The fix uses content comparison rather than a simple boolean because non-Slack sources (Web UI) don't know about Slack callbacks. Content comparison allows the callback to independently verify the message source without requiring coordination from other components. ### All Changes Pushed Both branches have been pushed to the remote repository with the PRs created.
c
@nutritious-balloon-65098 when you wrote the V0 PR, did you modify any files that had on top a comment about “V0 Legacy” or something like that? There are a dozen lines of comments on top of legacy files.
n
## Summary of Work ### Issue Created - [#12863](https://github.com/OpenHands/OpenHands/issues/12863) - Documented the privacy issue where Slack callbacks continue sending responses even when users switch to Web UI ### Pull Requests Created #### V1 Fix (Priority) - Already Pushed - [#12866](https://github.com/OpenHands/OpenHands/pull/12866) -
fix/slack-v1-privacy-callback
branch - Modifies
SlackV1CallbackProcessor
to check if last message originated from Slack before sending responses - Adds
_should_respond_to_slack()
and
_get_last_user_message()
methods - Updates
slack_view.py
to track message content when creating/updating V1 callbacks - Includes 4 new tests for the privacy feature #### V0 Fix (Legacy) - Already Pushed - [#12864](https://github.com/OpenHands/OpenHands/pull/12864) -
fix/slack-privacy-callback
branch - Similar approach for the V0
SlackCallbackProcessor
- Note: You indicated V1 matters and V0 is legacy - this PR may not be needed ### Open Question Should I close PR #12864 (V0 fix) since V0 is legacy? The enterprise files I modified don't have explicit "LEGACY V0" header comments, but they do contain V0-specific code paths (
SlackCallbackProcessor
,
send_message_to_v0_conversation
) that are legacy. ### Technical Note I also explained why content comparison is the right approach vs. a simple boolean: a boolean would require all message sources (Web UI, etc.) to know about and update Slack callbacks, whereas content comparison allows the Slack callback to independently verify the message source without coupling other components to the Slack integration.
## Summary ### Issue Created [#12863](https://github.com/OpenHands/OpenHands/issues/12863) - Documented the privacy concern where Slack callbacks continue to respond when users continue conversations via Web UI. ### Pull Request [#12866](https://github.com/OpenHands/OpenHands/pull/12866) - V1 fix for Slack callback privacy (already pushed) Files changed: -
enterprise/integrations/slack/slack_v1_callback_processor.py
- Added privacy check methods -
enterprise/integrations/slack/slack_view.py
- Updated to track message content -
enterprise/tests/unit/integrations/slack/test_slack_v1_callback_processor.py
- Added privacy tests ### Key Design Decision Used content comparison instead of a simple boolean because: - The Web UI (and other message sources) don't know about Slack callbacks - A boolean would require all message sources to update the Slack callback when sending messages - Content comparison allows the callback to independently verify by fetching the actual last message - no coordination needed ### Closed PR #12864 (V0 fix) - Closed as V0 is legacy and being phased out. ### Checklist - ✅ Investigated the issue and understood the architecture - ✅ Created GitHub issue with detailed analysis - ✅ Implemented V1 fix with privacy check - ✅ Added tests for the privacy feature - ✅ Documented V1 fix approach in issue comments - ✅ Closed unnecessary V0 PR per user's direction - ✅ All changes pushed to
fix/slack-v1-privacy-callback
branch
## Summary ### What was accomplished: 1. Created Issue [#12863](https://github.com/OpenHands/OpenHands/issues/12863) documenting the Slack privacy concern - when users continue a Slack-initiated conversation via Web UI, responses should not be posted back to Slack. 2. Created PR [#12866](https://github.com/OpenHands/OpenHands/pull/12866) with the V1 fix (the current, non-legacy system). 3. Closed PR #12864 (V0 fix) at your request, since V0 is legacy and being phased out. ### Outstanding issue: You correctly identified a bug in PR #12866 - the check:
Copy code
python
if last_user_message == summary_instruction:
    return True
This is flawed because it could allow summaries to always be sent to Slack if the summary instruction ends up as the last user message, defeating the privacy check entirely. ### Next step needed: I should update PR #12866 to remove that problematic check before it can be merged. The fix is simple - just delete those 3 lines. I have NOT pushed this fix yet - awaiting your confirmation to proceed with updating the PR.
## Summary ### Completed Work 1. Created Issue [#12863](https://github.com/OpenHands/OpenHands/issues/12863) - Documenting the Slack callback privacy concern where responses continue to be posted to Slack even when users move to the Web UI. 2. Closed PR [#12864](https://github.com/OpenHands/OpenHands/pull/12864) (V0 fix) - As you noted, V0 is legacy and shouldn't be invested in. 3. Created PR [#12866](https://github.com/OpenHands/OpenHands/pull/12866) (V1 fix) - Initial implementation pushed. ### Issues Identified During Review The V1 PR (#12866) has known issues we identified that still need to be fixed: 1. Flawed summary instruction check - The code
if last_user_message == summary_instruction: return True
would allow summaries to be sent even when they shouldn't. This needs to be removed. 2. Inefficient event fetching - Fetching 50 events (
limit: 50
) when we only need the last user message. 3. Duplicate summary prevention - Since summary instructions are sent as "user messages", we need a mechanism to: - Skip summary instructions when finding the "last real user message" - Prevent duplicate summaries (proposed: use sentinel value
''
to mark "already processed") ### Current Status PR #12866 should NOT be merged yet. We were actively discussing the proper solution when this summary was requested. The proposed fix involves: - Removing the flawed summary instruction check - Adding a sentinel value (
''
) to mark when we've already responded - Filtering out summary instructions when fetching the last user message - Reducing the event limit Would you like me to implement these fixes and update the PR?
## Final Summary ### What Was Done Issue Created: - [#12863](https://github.com/OpenHands/OpenHands/issues/12863) - Documents the privacy concern where Slack responses continue even when users switch to Web UI PRs Created and Closed: - #12864 (V0) - Closed because V0 is legacy - #12866 (V1) - Closed because the content-comparison approach has fundamental flaws ### Why the Initial Approach Failed Through discussion, we identified that comparing message content won't work because: 1. Summary instructions are user messages - The callback's "Please summarize..." request pollutes the "last user message" check 2. The summary instruction check was backwards - My code
if last_user_message == summary_instruction: return True
would have caused summaries to ALWAYS be sent to Slack, defeating the privacy protection entirely 3. A simple boolean won't work - As I correctly identified, the Web UI doesn't know about Slack callbacks and can't update them ### Current State The issue (#12863) now contains a detailed proposal with three alternative approaches: - Option A (Recommended): Add
trigger_source
field to SDK's MessageEvent ('slack', 'web_ui', 'callback', etc.) - Option B: Conversation-level
last_user_interaction_source
tracking in AppConversationInfo - Option C: Callback self-disabling after responding (limited, doesn't fully solve privacy) ### No Code to Push All branches with my changes have been closed. The issue is open for design discussion before any implementation proceeds. The team needs to decide on the right architectural approach before code is written.