From 11757fecd45b598e2876ae86905adbdc07df522d Mon Sep 17 00:00:00 2001 From: Ayaan Gazali Date: Wed, 5 Aug 2026 16:02:57 -0700 Subject: [PATCH] docs(slack): document retired Socket Mode tuning cleanup (#119328) * docs(slack): drop retired socketMode transport tuning channels.slack.socketMode is rejected by Slack config validation, pinned by the 'rejects retired Socket Mode ping/pong transport tuning' schema test, and the client pong timeout is now a hardcoded 15s constant. The page still told operators to configure it. * fix(slack): migrate retired socketMode with doctor instead of hand-editing The retired object fails schema validation at root and account scope, so the docs previously left manual removal as the only recovery. Slack already owns legacyConfigRules and normalizeCompatibilityConfig, so the strip belongs there. * test(slack): narrow the doctor contract config record for check-test-types normalizeCompatibilityConfig returns a possibly-absent channel entry, so the socketMode assertions need expectDefined before indexing. * docs(slack): describe socketMode retirement by observed behavior openclaw config validate reports a config carrying the retired object as valid, so the earlier 'validation rejects it / fails to load' wording was wrong. The observable facts are that it is not read and that doctor --fix removes it. * revert(slack): drop the duplicate socketMode doctor migration Core already strips channels.slack.socketMode at root and account scope in legacy-config-migrations.runtime.retired.ts via visitChannelEntries, so the plugin-side rule was duplicate policy. Keeps this PR to the docs correction. * docs(slack): state what doctor actually cleans up for socketMode Doctor flags retired layout knobs with a general notice, and --fix removes the three named fields and drops the object only once empty, so an unknown key inside it survives. --- docs/channels/slack.md | 46 +++++++++++++----------------------------- 1 file changed, 14 insertions(+), 32 deletions(-) diff --git a/docs/channels/slack.md b/docs/channels/slack.md index 69fad2d42599..dae0b8b0a255 100644 --- a/docs/channels/slack.md +++ b/docs/channels/slack.md @@ -23,17 +23,17 @@ Slack support covers DMs and channels via Slack app integrations. Default transp Socket Mode and HTTP Request URLs reach feature parity for messaging, slash commands, App Home, and interactivity. Pick by deployment shape, not features. -| Concern | Socket Mode (default) | HTTP Request URLs | -| ---------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------- | -| Public Gateway URL | Not required | Required (DNS, TLS, reverse proxy or tunnel) | -| Outbound network | Outbound WSS to `wss-primary.slack.com` must be reachable | No outbound WS; inbound HTTPS only | -| Tokens needed | Bot identity: bot token + App-Level Token with `connections:write`; user identity: user token + App-Level Token | Bot identity: bot token + Signing Secret; user identity: user token + Signing Secret | -| Dev laptop / behind firewall | Works as-is | Needs a public tunnel (ngrok, Cloudflare Tunnel, Tailscale Funnel) or staging Gateway | -| Horizontal scaling | One Socket Mode session per app per host; multiple Gateways need separate Slack apps | Stateless POST handler; multiple Gateway replicas can share one app behind a load balancer | -| Multi-account on one Gateway | Supported; each account opens its own WS | Supported; each account needs a unique `webhookPath` (default `/slack/events`) so registrations do not collide | -| Slash command transport | Delivered over the WS connection; `slash_commands[].url` is ignored | Slack POSTs to `slash_commands[].url`; field is required for the command to dispatch | -| Request signing | Not used (auth is the App-Level Token) | Slack signs every request; OpenClaw verifies with `signingSecret` | -| Recovery on connection drop | Slack SDK auto-reconnect is enabled; OpenClaw also restarts failed Socket Mode sessions with bounded backoff. Pong-timeout transport tuning applies. | No persistent connection to drop; retries are per-request from Slack | +| Concern | Socket Mode (default) | HTTP Request URLs | +| ---------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------ | -------------------------------------------------------------------------------------------------------------- | +| Public Gateway URL | Not required | Required (DNS, TLS, reverse proxy or tunnel) | +| Outbound network | Outbound WSS to `wss-primary.slack.com` must be reachable | No outbound WS; inbound HTTPS only | +| Tokens needed | Bot identity: bot token + App-Level Token with `connections:write`; user identity: user token + App-Level Token | Bot identity: bot token + Signing Secret; user identity: user token + Signing Secret | +| Dev laptop / behind firewall | Works as-is | Needs a public tunnel (ngrok, Cloudflare Tunnel, Tailscale Funnel) or staging Gateway | +| Horizontal scaling | One Socket Mode session per app per host; multiple Gateways need separate Slack apps | Stateless POST handler; multiple Gateway replicas can share one app behind a load balancer | +| Multi-account on one Gateway | Supported; each account opens its own WS | Supported; each account needs a unique `webhookPath` (default `/slack/events`) so registrations do not collide | +| Slash command transport | Delivered over the WS connection; `slash_commands[].url` is ignored | Slack POSTs to `slash_commands[].url`; field is required for the command to dispatch | +| Request signing | Not used (auth is the App-Level Token) | Slack signs every request; OpenClaw verifies with `signingSecret` | +| Recovery on connection drop | Slack SDK auto-reconnect is enabled; OpenClaw also restarts failed Socket Mode sessions with bounded backoff. A fixed 15s client pong timeout applies. | No persistent connection to drop; retries are per-request from Slack | **Pick Socket Mode** for single-Gateway hosts, dev laptops, and on-prem networks that can reach `*.slack.com` outbound but cannot accept inbound HTTPS. @@ -806,30 +806,12 @@ OpenClaw automatically drops user-scope message events authored by the resolved ## Socket Mode transport tuning -OpenClaw sets the Slack SDK client pong timeout to 15 seconds by default for Socket Mode. Override the transport settings only when you need workspace- or host-specific tuning: - -```json5 -{ - channels: { - slack: { - mode: "socket", - socketMode: { - clientPingTimeout: 20000, - serverPingTimeout: 30000, - pingPongLoggingEnabled: false, - }, - }, - }, -} -``` - -Use this only for Socket Mode workspaces that log Slack websocket pong/server-ping timeouts or run on hosts with known event-loop starvation. `clientPingTimeout` is the pong wait after the SDK sends a client ping; `serverPingTimeout` is the wait for Slack server pings. App messages and events remain application state, not transport liveness signals. +OpenClaw sets the Slack SDK client pong timeout to 15 seconds for Socket Mode. This is a fixed internal default and is not operator-configurable. Notes: -- `socketMode` is ignored in HTTP Request URL mode. -- Base `channels.slack.socketMode` settings apply to all Slack accounts unless overridden. Per-account overrides use `channels.slack.accounts..socketMode`; because this is an object override, include every socket tuning field you want for that account. -- Only `clientPingTimeout` has an OpenClaw default (`15000`). `serverPingTimeout` and `pingPongLoggingEnabled` are passed to the Slack SDK only when configured. +- The `channels.slack.socketMode` object, including `clientPingTimeout`, `serverPingTimeout`, and `pingPongLoggingEnabled`, is retired and is no longer read at runtime. `openclaw doctor` flags retired layout tuning knobs with a general notice rather than a per-key path. `openclaw doctor --fix` removes those three fields wherever they appear, at the channel root and under `accounts.`, and drops the `socketMode` object once it is empty. Any other key you added inside it is left alone, so delete it by hand. +- App messages and events remain application state, not transport liveness signals. - Socket Mode restart backoff starts around 2 seconds and caps around 30 seconds. Recoverable start, start-wait, and disconnect failures retry until the channel stops. Permanent account and credential errors such as invalid auth, revoked tokens, or missing scopes fail fast instead of retrying forever. ## Manifest and scope checklist