fix(slack): thread-parent context, multi-workspace cache key, Slack Connect files#16200
Merged
Conversation
…arent
The Slack thread-context fetcher used to drop every message with a
bot_id, which silently erased the thread parent whenever a cron job (or
any other bot) had posted it. As a result, replies to a cron-posted
summary lost all context and the agent answered as if from a blank
thread.
Changes:
1. gateway/platforms/slack.py::_fetch_thread_context
- Keep the thread parent even when it was posted by a bot
(e.g. cron summaries, third-party integrations).
- Only skip *our own* prior bot replies to avoid circular context,
matching the per-workspace bot user id via _team_bot_user_ids so
multi-workspace deployments stay correct.
- Keep non-self bot children (useful third-party context).
2. gateway/platforms/slack.py::_handle_slack_message
- Populate MessageEvent.reply_to_text for thread replies (parity
with Telegram/Discord/Feishu/WeCom). gateway.run uses this field
to inject a [Replying to: "..."] prefix when the parent is not
already in the session history, which is exactly the scenario
triggered by cron-generated thread parents.
- New helper _fetch_thread_parent_text reuses the existing thread-
context cache (and its 60s TTL) to avoid duplicate
conversations.replies calls; falls back to a cheap limit=1 fetch
when the cache is cold.
Tests:
- Updated TestSlackThreadContext::test_skips_bot_messages to reflect
the new behaviour (self-bot child dropped, third-party bot kept).
- Added:
* test_fetch_thread_context_includes_bot_parent
* test_fetch_thread_context_excludes_self_bot_replies
* test_fetch_thread_context_multi_workspace
* test_fetch_thread_context_current_ts_excluded (regression guard)
* test_fetch_thread_parent_text_from_cache
* test_slack_reply_to_text_set_on_thread_reply
* test_slack_reply_to_text_none_for_top_level_message
Full Slack suite: 176 passed (was 169).
Slack Connect channels return file objects with file_access="check_file_info" and no url_private_download field (see https://docs.slack.dev/reference/objects/file-object/#slack_connect_files). These stub objects must be resolved via files.info before download can proceed. Without this the agent silently skips attachments posted in Slack Connect channels. Call files.info on every file whose file_access is check_file_info, replace the stub with the full file object, and let the existing download path continue. Warn and skip on files.info failures. Closes #11095.
This was referenced Apr 26, 2026
12 tasks
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.
Three independent Slack thread-context bugs fixed together.
Changes
1. Thread parent preserved when cron/bot posted it (@Satoshi-agi, #12561)
_fetch_thread_contextunconditionally skipped any message withbot_id, dropping cron-posted thread parents. Now skips only our own prior bot replies (using per-workspace_team_bot_user_ids.get(team)for multi-workspace correctness) — the parent is preserved even if it was posted by a bot, and non-self bot children (alerts/webhooks) are kept as useful context. Also populatesMessageEvent.reply_to_texton thread replies so gateway.run's shared[Replying to: "..."]injection works on Slack (parity with Telegram/Discord/Feishu/WeCom). New_fetch_thread_parent_text()reuses the thread-context cache; falls back toconversations.replies(limit=1, inclusive=True).2. Multi-workspace cache correctness (@flobo3, #12502)
Thread-context cache key didn't include
team_id. In multi-workspace Slack mode, a lookup from workspace B could receive stale context that was rendered with workspace A's bot identity and user-name resolution. Include team_id in the cache key for both_fetch_thread_contextand_fetch_thread_parent_text.3. Slack Connect attachments (@kunlabs, #11111)
Slack Connect channels return file objects with
file_access="check_file_info"and nourl_private_download— stub objects that require afiles.infocall to resolve. Previously the agent silently skipped them. Now callsfiles.infoon any such stub, replaces it with the full object, and lets the existing download path continue.Validation
test_slack.py+test_slack_approval_buttons.py+test_slack_mention.pyCredits
reply_to_textparity._fetch_thread_parent_textcache key stays consistent.Also closes as already-fixed
Closes #2950
Closes #11095
Closes #12421