Skip to main content
Trinity
Guides/Slack Integration

Slack Integration

Connect agents to Slack workspaces. Supports DMs, @mentions in channels, multi-agent routing, and thread continuity.

Key Concepts

•Channel Adapter — Pluggable abstraction for external messaging platforms. Slack, Telegram, and WhatsApp are implemented on the same interface.
•Socket Mode — Default transport using a WebSocket connection. No public URL required. Configured via a Slack App Token (xapp-...).
•Webhook Mode — HTTP webhook transport for production environments (fallback option).
•Multi-Agent Routing — Multiple agents can share one Slack workspace. Each agent is bound to a dedicated channel. DMs are routed to a default agent; @mentions route to the bound agent.
•Thread Tracking — The bot automatically responds to thread replies without requiring an @mention.

Platform Setup (Admin)

1

Create a Slack app at api.slack.com/apps. Give it the bot token scopes im:history, im:read, im:write, chat:write, chat:write.customize, users:read.email, app_mentions:read, channels:read, channels:manage and reactions:write; subscribe it to the message.im and app_mention events; enable Socket Mode and create an app-level token with connections:write; and add https://your-domain.com/api/public/slack/oauth/callback as an OAuth redirect URL. The same checklist is shown inline in Settings.

2

Go to Settings → Integrations and find the Slack Integration section.

3

Under OAuth Credentials, enter the app's Client ID, Client Secret and Signing Secret and click Save Credentials. The client secret, signing secret and app token are stored encrypted at rest (see Credential Management).

4

Under Transport Connection, paste the app-level token (xapp-...) and click Connect to start the Socket Mode transport. The badge shows Socket Mode, Webhook or Disconnected.

5

Click Install to Workspace (Reinstall to Workspace once a workspace is connected) to complete the platform-level OAuth and obtain the bot token. Then bind agents to channels from each agent's Sharing tab.

Per-Agent Channel Binding

1

Open the agent detail page and select the Sharing tab.

2

Under Channels, click Configure on the Slack row — the Slack configuration opens in a dialog. Click Create Channel.

3

A dedicated Slack channel is created and bound to this agent. All messages in that channel are routed to the bound agent.

4

To disconnect, click Unbind.

Changing the DM-Default Agent

DMs to the Slack bot are routed to the workspace's DM-default agent. By default the first agent bound to a workspace becomes the DM default, but you can reassign it at any time.

To reassign

1

Open the agent detail page for the agent you want to receive DMs

2

Go to the Sharing tab → Slack Channel section

3

Click Set as DM Default

4

The previous DM-default agent retains its channel binding but no longer receives DMs

Rules

•Only one agent per workspace can be the DM default at a time
•You cannot unbind the current DM-default agent while other agents are still bound to the workspace. Reassign the DM default to another agent first, then unbind
•Changing the DM default takes effect immediately — no restart required

Message Flow

Transport -> Adapter -> Router -> Agent -> Response
Message TypeRouting
DM to botDefault agent
@mention in channelBound agent for that channel
Thread reply (no @mention)Same agent that was originally mentioned

Inbound files.Files attached to a Slack message are downloaded through a host allow-list: the authenticated first request may only go to Slack's own API host, and a redirect is followed only to Slack's file and edge-CDN hosts, over HTTPS, with each hop re-checked and a bounded number of hops. A download to any other host is refused and logged as an error — so a file that fails to reach your agent is visible in the logs rather than silently dropped.

Agent Identity in Channels

•The agent sees who's talking and where. Channel (non-DM) messages reach the agent with an identity prefix such as [Channel: #engineering] / [From: John Smith (@johndoe)], so it can address people by name and adapt to the room. DMs stay clean — no prefix.
•The agent replies as itself. Replies post with the agent's name and its avatar as the per-message bot icon (via the chat:write.customize scope), so multiple agents in one workspace are visually distinct.

By default, every agent shares one workspace bot and is told apart by that per-message name and avatar — so a channel with several agents already reads as distinct voices.

Per-Agent Dedicated Bots (enterprise)

On the enterprise tier, an agent can have its own dedicated Slack bot identity instead of sharing the workspace bot: its own name and avatar, and — the part a shared bot can't do — a bot users can DM directly and @mention by name, right alongside other agents in the same channel. Configure it per agent from the Dedicated Slack botpanel on the agent's Sharing tab (enable/disable, replace tokens, remove). In a community build this panel is hidden and the shared-workspace-bot model above applies.

Voice Replies (Outbound)

The agent can speak its replies as inline MP3 voice clips uploaded into the thread (Slack renders MP3 with a built-in player). Enable the shared Voice replies toggle inside the Slack dialog — see Voice Replies.

Proactive Channel Messages

Agents can post to their bound Slack channels without waiting to be mentioned — for scheduled digests, alerts, or follow-ups:

•MCP tools: list_channel_groups(channel_type: "slack") discovers the agent's bound channels; send_group_message(channel_type: "slack", chat_id, message, thread_ts?) posts to one, optionally into an existing thread via thread_ts.
•REST: GET /api/agents/{name}/slack/channels lists bound channels; POST /api/agents/{name}/slack/channels/{channel_id}/messages posts (owner-gated).
•Proactive posts carry the agent's identity (name + avatar icon), same as replies.

Per-Channel Proactive Consent

Posting proactively to a Slack channel requires a per-channel consent toggle — distinct from the per-recipient consent that governs proactive DMs. Binding an agent to a channel is not itself consent: a newly bound channel denies proactive posts by default. The owner enables it in the Slack channel panel, or via PUT /api/agents/{name}/slack/channels/{channel_id}/proactive.

•A denied proactive attempt returns a named "not allowed" error (403), kept distinct from not bound (404) and rate-capped (429), so the agent can relay why the post did not land.
•Replying inline to a user's own message never needs consent — this gate applies only to agent-initiated posts.

Completion Report-Back

When an agent starts a long-running or delegated job that inherited Slack channel context, it posts a short note back to the originating channel/threadon completion — so the room sees the outcome without re-asking.

•Gated on the same per-channel proactive consent above; a channel that denies proactive posts gets no completion note.
•The completion text is credential-sanitized before it is posted.
•A normal inline Slack reply is never double-reported — the report-back fires only for jobs that finish out of band.

Proactive Rate Limits

Proactive channel posts are rate-limited over a rolling 1-hour window. The caps are defaults, admin-configurable in Settings (0 = unlimited):

CapDefault
Messages per channel per hour10
Messages per agent per hour100

Message body cap: 4,000 characters. Read or update the caps via GET /api/settings/proactive-rate-limits and PUT /api/settings/proactive-rate-limits (per-key integer, 0..max).

Rate Limiting

SettingDefault
Messages per window per Slack user30
Window duration60 seconds
Execution timeout120 seconds
Allowed toolsWebSearch, WebFetch

Rate limit and tool values are configurable via settings (channel_rate_limit_max, channel_rate_limit_window, channel_allowed_tools); Read is added automatically when the message carries readable files.

Slack API

EndpointMethodDescription
/api/settings/slack/statusGETConnection state
/api/settings/slack/connectPOSTStart Socket Mode
/api/settings/slack/disconnectPOSTStop transport
/api/settings/slack/installPOSTOAuth install
/api/agents/{name}/slack/channelGETChannel binding status
/api/agents/{name}/slack/channelPOSTCreate and bind channel
/api/agents/{name}/slack/channelDELETEUnbind channel
/api/agents/{name}/slack/channel/dm-defaultPUTSet this agent as the DM default for its workspace
/api/agents/{name}/slack/channelsGETList channels bound to this agent (for proactive messaging)
/api/agents/{name}/slack/channels/{channel_id}/messagesPOSTPost a proactive message to a bound channel (owner-gated, rate-limited)
/api/agents/{name}/slack/channels/{channel_id}/proactivePUTToggle per-channel proactive consent (owner-gated)
/api/settings/proactive-rate-limitsGETRead proactive rate-limit caps
/api/settings/proactive-rate-limitsPUTUpdate proactive rate-limit caps (admin; per-key integer 0..max, 0 = unlimited)

Full request/response schemas are in the backend's Swagger docs (http://localhost:8000/docs when running locally).

Limitations

•Only one Slack workspace can be connected per Trinity instance.
•Webhook Mode requires a publicly accessible URL.
•Thread tracking applies only to threads started by a bot message or @mention.
•Rate limits are per Slack user, not per agent.