← Back to PRs

#14720: fix(slack): pass threadId in plugin read action (#14706)

by lailoo open 2026-02-12 14:59 View on GitHub →
channel: slack stale size: S trusted-contributor
## Summary - **Bug**: Slack plugin's `handleAction` for `action === "read"` silently drops the `threadId` parameter, so thread replies can never be fetched. - **Root cause**: The `read` branch in `extensions/slack/src/channel.ts` constructs the `handleSlackAction` params without reading `threadId` from the tool params. The core `slack-actions.ts` already supports `threadId` in `readMessages`, but the extension layer never passes it. - **Fix**: Read `threadId` from params and include it in the `handleSlackAction` call for the `read` action. Fixes #14706 ## Problem When calling `message(action="read", channel="slack", target="<channel>", threadId="<ts>", limit=N)`, the `threadId` is silently dropped by the Slack plugin extension. The internal `readSlackMessages` function falls through to `conversations.history` (channel-level messages) instead of `conversations.replies` (thread replies). The bug is in `extensions/slack/src/channel.ts` lines 356-368. The `read` branch reads `limit`, `before`, `after`, and `accountId`, but not `threadId`. Compare with the `send` branch (line 304) which correctly reads `threadId`. The core code in `src/agents/tools/slack-actions.ts` (line 230) already reads `threadId` and passes it to `readSlackMessages` — the extension layer just never provides it. **Before fix (reproduced on main via integration test):** ``` pnpm vitest run extensions/slack/src/channel.read-threadid.test.ts ❌ FAIL passes threadId to handleSlackAction when provided AssertionError: expected undefined to be '1234567890.123456' ``` The test directly calls `slackPlugin.actions.handleAction` with `threadId: "1234567890.123456"` and asserts the param is passed to `handleSlackAction`. On main, it's `undefined`. ## Changes - `extensions/slack/src/channel.ts` — Read `threadId` from params via `readStringParam` and pass it as `threadId: threadId ?? undefined` to `handleSlackAction` in the `read` branch (+2 lines) - `extensions/slack/src/channel.read-threadid.test.ts` — New regression test: imports real `slackPlugin`, mocks `getSlackRuntime`, calls `handleAction` with `action="read"` and asserts `threadId` is forwarded - `CHANGELOG.md` — Add fix entry **After fix (verified on fix branch):** ``` pnpm vitest run extensions/slack/src/channel.read-threadid.test.ts ✓ passes threadId to handleSlackAction when provided ✓ does not include threadId when not provided Test Files 1 passed (1) Tests 2 passed (2) ``` ## Test plan - [x] New test: `threadId` passed to `handleSlackAction` when provided (integration test calling real extension code) - [x] New test: `threadId` is `undefined` when not provided (no regression) - [x] All 22 existing slack-actions tests pass (`pnpm vitest run src/agents/tools/slack-actions.test.ts`) - [x] Lint passes (`pnpm lint`) - [x] Bug reproduced on main: test fails with `expected undefined to be '1234567890.123456'` - [x] Fix verified on fix branch: both tests pass ## Effect on User Experience **Before:** When an agent calls `message(action="read", threadId="...")` on Slack, it always gets channel-level messages instead of thread replies. Users cannot read Slack thread conversations. **After:** Thread replies are correctly fetched when `threadId` is provided. Channel-level reads (without `threadId`) continue to work as before (no regression). <!-- greptile_comment --> <h2>Greptile Overview</h2> <h3>Greptile Summary</h3> This PR fixes Slack extension message reads for threads by passing the `threadId` tool parameter through the Slack plugin’s `handleAction` read branch (`extensions/slack/src/channel.ts`) into the core Slack action handler (`action: "readMessages"`). Core logic in `src/agents/tools/slack-actions.ts` already supports `threadId` and routes to thread replies when present; this change unblocks that behavior by ensuring the extension layer doesn’t drop the parameter. Also adds a changelog entry for the user-facing behavior fix. <h3>Confidence Score: 5/5</h3> - This PR is safe to merge with minimal risk. - The change is a narrow parameter pass-through in the Slack extension layer, and it matches the existing core handler contract (`threadId` is already parsed and forwarded to `readSlackMessages`). No behavioral change occurs when `threadId` is absent, and the added changelog line is straightforward. - No files require special attention <!-- greptile_other_comments_section --> <!-- /greptile_comment -->

Most Similar PRs