Class SlackChannel

java.lang.Object
com.tnsai.channels.slack.SlackChannel
All Implemented Interfaces:
ChannelAdapter

@Channel(id="slack", displayName="Slack") public class SlackChannel extends Object implements ChannelAdapter
Slack channel adapter using Socket Mode (TNS-350).

Inbound: opens a WebSocket via Slack's Socket Mode protocol. The adapter calls POST /apps.connections.open with the xapp-... app token to obtain a WSS URL, then connects and listens for events_api envelopes. Every envelope is immediately acked with the matching envelope_id, and the message sub-events are converted into UnifiedMessage before being delivered via ChannelContext.onMessage(com.tnsai.channels.api.UnifiedMessage).

Outbound: each UnifiedResponse becomes a POST /chat.postMessage call with the xoxb-... bot token in the Authorization header. The Slack conversationId (channel ID) is sent as the channel field; the optional thread_ts field is populated when the original message's metadata identified a thread root, keeping replies threaded.

Why Socket Mode and not the Events API webhook (deviation from the TNS-350 spec): the framework deliberately has no embedded HTTP server in tnsai-channels; every existing adapter pulls from its platform rather than accepting inbound HTTP. Socket Mode keeps that invariant intact and means the agent can run behind NAT without exposing a public URL — a hard requirement for a homelab deployment topology. See SlackChannelConfig for the detailed rationale.

Thread safety: send(com.tnsai.channels.api.UnifiedResponse) can be invoked from any agent thread concurrently with the inbound WebSocket callback; both routes share the immutable config and a single OkHttp client instance, so there's no mutable adapter state to guard.