fix(slack): thread team_id to chat.startStream for Enterprise Grid (#95)#176
Conversation
chat.startStream fails with `team_not_found` on Enterprise Grid orgs because the per-workspace bot token alone isn't enough to disambiguate the team — Grid requires an explicit workspace `team_id`. Non-streaming chat.postMessage succeeds without it, so only the streaming path regressed: `stream()` built its `chat_stream(...)` kwargs from channel / thread_ts / recipient_user_id / recipient_team_id / task_display_mode and never passed a workspace `team_id`. Fix: thread `team_id=options.recipient_team_id` into the chat_stream call. slack_sdk's AsyncChatStream stashes unknown kwargs in `_stream_args` and forwards them to BOTH chat.startStream call sites (the eager first-flush path and the lazy stop-without-flush path), so this reaches the only API call that needs it. chat.appendStream / chat.stopStream don't receive `_stream_args` and don't require `team_id`. recipient_team_id is the team.id extracted on the inbound path (the workspace where the interaction happened = the streaming target workspace). Harmless on non-Grid workspaces — a correct team_id is always valid. Tests: a Grid regression in tests/test_slack_api.py simulating an Enterprise Grid workspace where post_message succeeds without team_id but the streaming start raises team_not_found when team_id is absent and succeeds when present; plus a mutation-guard test proving the simulation fails without team_id. Both use a local SlackApiError stand-in so they don't depend on slack_sdk being installed (the dev group doesn't pull it in; a fake module is injected under CI). Also refreshes scripts/fidelity_baseline.json ts_parity 4.30.0 -> 4.31.0 (stale since the 0.4.31 release; content already 0-missing) and adds a Known Non-Parity row to docs/UPSTREAM_SYNC.md documenting that upstream has the same Grid gap. Live Grid verification needs a real Enterprise Grid workspace; the unit test simulates it.
|
Warning Review limit reached
More reviews will be available in 59 minutes and 56 seconds. Learn how PR review limits work. Your organization has used up its prepaid credits, and credit purchases are no longer available. Enable the review add-on in the billing tab to keep reviews running — you're only billed for reviews past your plan's rate limits ($0.25/file). ⌛ How to resolve this issue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based credits. 🚦 How do rate limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan refill rate. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, the refill rate gradually slows as usage increases. The highest same-day bursts are limited more strictly. Please see our Fair Usage Limits Policy for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: Repository UI Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (4)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Code Review
This pull request resolves Enterprise Grid issue #95 by passing the workspace team_id (sourced from options.recipient_team_id) into client.chat_stream(...) in the Slack adapter, preventing team_not_found errors during streaming. The changes also include updating the upstream sync documentation, bumping the ts_parity version in the fidelity baseline to chat@4.31.0, and adding robust unit tests with a mock _FakeSlackApiError to verify the fix. There are no review comments, so I have no feedback to provide.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
Python-only patch on 4.31.0 (UPSTREAM_PARITY unchanged). - Slack #138: empty-DM thread_ts fetch routes to conversations.history (PR #175) - Slack #95: thread team_id to chat.startStream for Enterprise Grid (PR #176) - docs: mark Linear agent-sessions mode experimental (unverified vs live tenant, #151) - version 0.4.31 -> 0.4.31.1; CHANGELOG; CLAUDE.md mapping
Summary
Fixes Slack issue #95 —
chat.startStreamfails withteam_not_foundon Enterprise Grid workspaces, even with a non-emptythread_ts. Non-streamingchat.postMessagesucceeds on the same workspace; onlychat.startStreamregressed.Root cause: On Grid orgs
chat.startStreamrequires an explicit workspaceteam_idto disambiguate the team (the per-workspace bot token alone isn't sufficient).stream()built itschat_stream(...)kwargs fromchannel/thread_ts/recipient_user_id/recipient_team_id/task_display_modeand never passed a workspaceteam_id.Fix
src/chat_sdk/adapters/slack/adapter.pystream()— threadteam_id=options.recipient_team_idinto thechat_stream(...)kwargs:recipient_team_idis theteam.idextracted on the inbound path (the workspace where the interaction happened = the streaming-target workspace). Harmless on non-Grid workspaces — a correctteam_idis always valid. The empty-thread_tsDM degrade-to-post_messagepath is unchanged.slack_sdk investigation (how
team_idreaches the API)Verified against installed
slack-sdk==3.42.0:AsyncWebClient.chat_stream(...)has noteam_idparam of its own, but stashes unknown**kwargsintoAsyncChatStream._stream_args._stream_argsis forwarded only to the twochat.startStreamcall sites insideAsyncChatStream— the eager first-flush path (_flush_buffer) and the lazy stop-without-flush path (stop). Both use**self._stream_args.chat.startStream/chat.appendStream/chat.stopStreamall forward their**kwargsstraight toapi_call(..., json=kwargs), soteam_idis a real, forwarded API param.team_idtochat_stream(...)threads it through tochat.startStream(the only call that fails per Slack: chat.startStream fails with team_not_found on Enterprise Grid workspaces #95).chat.appendStream/chat.stopStreamdo not receive_stream_argsand do not needteam_idon Grid.Tests
tests/test_slack_api.py::TestStream:test_stream_threads_team_id_to_chat_stream_for_grid— simulates a Grid workspace:post_messagesucceeds with noteam_id; the streamer's lazychat.startStreamraisesteam_not_foundwhenteam_idis absent and succeeds when present. Asserts the fix passesteam_id == recipient_team_idtochat_stream. Mutation-proven: drop theteam_idline and this test fails withteam_not_found.test_stream_raises_team_not_found_without_team_id_on_grid— mutation guard proving the Grid simulation isn't vacuous (strippingteam_idalways raises).Both use a local
_FakeSlackApiErrorstand-in (mirroringSlackApiError's.responsedict + message) so they don't depend onslack_sdkbeing installed — the dev group doesn't pull it in, andtest_slack_client_cache.pyinjects a bareslack_sdkModuleType with noerrorssubmodule under CI.Divergence doc
Adds a Known Non-Parity row to
docs/UPSTREAM_SYNC.md(cites #95): Gridchat.startStreamneedsteam_id; we threadrecipient_team_idas the workspace team. Upstream has the same gap — itsstream()never threadsteam_id, so streaming is broken on Grid while non-streaming posts work.Env limitation
Live Grid verification needs a real Enterprise Grid workspace; the unit test simulates it (raises
team_not_foundfrom the streamer's lazychat.startStreamwhenteam_idis absent).Also included
scripts/fidelity_baseline.jsonts_parityrefreshedchat@4.30.0->chat@4.31.0(stale since the 0.4.31 release; content already 0-missing). This unblocksverify_test_fidelity.py's parity gate, which fails on any branch off currentmain.Gauntlet
ruff check: OKruff format --check: OKaudit_test_quality.py: 0 hard failurespyrefly check src/: 0 errorsverify_test_fidelity.py --strict(TS_ROOT=chat@4.31.0): 732/732 matched, 0 missingpytest tests/: 5248 passed, 4 skipped (run withslack_sdkuninstalled to mirror CI)