Skip to content

feat(slack): expose webClientOptions to configure the underlying WebClient#602

Open
aqt-dev wants to merge 1 commit into
vercel:mainfrom
aqt-dev:feat/slack-web-client-options
Open

feat(slack): expose webClientOptions to configure the underlying WebClient#602
aqt-dev wants to merge 1 commit into
vercel:mainfrom
aqt-dev:feat/slack-web-client-options

Conversation

@aqt-dev

@aqt-dev aqt-dev commented Jun 9, 2026

Copy link
Copy Markdown

Problem

The Slack adapter constructs its @slack/web-api WebClient(s) with only slackApiUrl — no retry or timeout configuration:

this._client = new WebClient(undefined, {
  ...(this.slackApiUrl ? { slackApiUrl: this.slackApiUrl } : {}),
});

So both the default client and the per-token clients (getClientForToken, used for multi-workspace requests) inherit @slack/web-api's default retry policy, retryPolicies.tenRetriesInAboutThirtyMinutes. Under sustained rate limiting, a single chat.update / chat.postMessage blocks for ~30 minutes while the WebClient sleeps on Retry-After and retries.

For bots that stream responses (a placeholder message edited repeatedly via chat.update), a burst of activity in one channel exhausts the per-channel rate limit and a single hung delivery can stall an entire turn — and there is currently no way to tune this from outside the adapter, since createSlackAdapter doesn't surface any WebClient options beyond apiUrl.

Change

Add an optional webClientOptions?: WebClientOptions to SlackAdapterConfig, forwarded into both WebClient constructions (default + per-token). Callers can now pass retryConfig, timeout, rejectRateLimited, etc.:

import { retryPolicies } from "@slack/web-api";

createSlackAdapter({
  signingSecret,
  webClientOptions: {
    retryConfig: retryPolicies.fiveRetriesInFiveMinutes,
    timeout: 15_000,
  },
});
  • Purely additive and non-breaking — default behavior is unchanged when webClientOptions is omitted.
  • apiUrl continues to take precedence over webClientOptions.slackApiUrl (the dedicated field wins).
  • The options are spread into both clients so multi-workspace deployments get the same tuning as single-workspace.

Tests

Added two tests under direct WebClient access via adapter.client:

  • forwards webClientOptions to the bound WebClient
  • apiUrl takes precedence over webClientOptions.slackApiUrl

pnpm --filter @chat-adapter/slack test478 passed. typecheck, biome check, and konsistent all clean. Changeset included (minor).

…lient

The adapter constructs its `@slack/web-api` WebClient(s) with no retry/timeout
configuration, so they inherit the SDK default `tenRetriesInAboutThirtyMinutes`
retry policy. Under sustained rate limiting a single `chat.update`/
`chat.postMessage` can block for ~30 minutes, which stalls callers that stream
frequent edits (a hung delivery can hold up a whole turn) and there is currently
no way to tune it from outside the adapter.

Add an optional `webClientOptions: WebClientOptions` field to
`SlackAdapterConfig`, forwarded into both the default client and the per-token
clients used for multi-workspace requests. Callers can now pass `retryConfig`,
`timeout`, etc. `apiUrl` continues to take precedence over
`webClientOptions.slackApiUrl`.
@aqt-dev aqt-dev requested a review from a team as a code owner June 9, 2026 21:38
@vercel

vercel Bot commented Jun 9, 2026

Copy link
Copy Markdown
Contributor

@aqt-dev is attempting to deploy a commit to the Vercel Team on Vercel.

A member of the Team first needs to authorize it.

@aqt-dev

aqt-dev commented Jun 10, 2026

Copy link
Copy Markdown
Author

Hi @dancer (cc @gr2m) — thanks for all the recent work on the Slack adapter, it's been great to build on.

I ran into a case where the adapter's WebClient is constructed without a retryConfig or timeout, so it inherits the SDK default (tenRetriesInAboutThirtyMinutes). Under sustained rate limiting a single chat.update can block for ~30 min, which stalls a streaming bot, and there's currently no way to tune it from outside the adapter.

This PR just adds an optional webClientOptions passthrough on SlackAdapterConfig (forwarded to both the default and per-token clients) so callers can set retryConfig/timeout. It's additive and non-breaking, default behavior is unchanged. Tests and a changeset are included.

No rush at all, but would love your eyes on it whenever you have a moment. Happy to adjust the approach if you'd prefer it shaped differently.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant