Technical docs
Connect an AI Teammate to Slack
Overview
This reference explains how to connect one Alloy AI Teammate to Slack through a dedicated Slack App. Use it when a customer wants to message an AI Teammate from Slack DMs, channels, or private channels.
Requirements
- An Alloy AI Teammate already exists.
- A Slack workspace administrator can create or configure a Slack App and install it into the workspace.
- Alloy automatically creates and maintains a default workflow for each AI Teammate. A missing default workflow is
a rare exception, usually caused by a failed setup, migration, or data issue. Slack messages can register a chat before the workflow replies, but the AI will not respond until the chat is enabled and the default workflow is present and runnable.
1. Open the Slack tab in Alloy
- Open the AI Teammate detail page in Alloy.
- Open the `Slack` tab.
- Click `Connect` to reveal the numbered setup guide.
- In `Quick setup with a Slack app manifest`, click `Copy manifest`.
The copied manifest is JSON. It includes the AI Teammate app name, required bot token scopes, App Home direct-message settings, Slack event subscriptions, and the Alloy Events Request URL for this AI Teammate.
Required bot scopes are `app_mentions:read`, `channels:history`, `channels:read`, `chat:write`, `files:read`, `files:write`, `groups:history`, `groups:read`, `im:history`, `im:read`, `im:write`, `mpim:history`, and `users:read`. The manifest also subscribes to the `message.mpim` event so the bot can receive multi-party direct messages.
If the backend cannot provide the Events Request URL, `Copy manifest` is disabled and the tab explains that the backend Slack webhook configuration must be completed before copying a manifest.
The Slack tab also displays the `Events Request URL` inside the collapsed `Troubleshooting` accordion. It has this shape:
```text https://{api-domain}/webhooks/slack/events/{organizationId}/{employeeId} ```
2. Create the Slack App from the manifest
- Open Slack API `Your Apps`.
- Click `Create New App`.
- Choose `From an app manifest (JSON)`.
- Pick the customer's Slack workspace.
- Paste the manifest copied from Alloy.
- Review Slack's summary and create the app.
Use one dedicated Slack App per AI Teammate. Alloy uses the Slack bot user ID to prevent the same bot identity from being connected to multiple AI Teammates.
Slack verifies the Events Request URL while creating the app from the manifest. The manifest configures the bot token scopes, `app_mention`, direct-message, public-channel, and private-channel events, and enables direct messages in App Home.
3. Install the Slack App
- In the Slack App settings, open `OAuth & Permissions`.
- Click `Install to Workspace`, or `Reinstall to Workspace` if the app was installed earlier.
- Review the requested permissions and approve the installation.
Slack issues or refreshes the Bot User OAuth Token during this step. If any scopes or app messaging settings change later, reinstall the app again before copying the token into Alloy.
4. Copy Slack credentials into Alloy
In Slack:
- Open `OAuth & Permissions`.
- Copy the `Bot User OAuth Token`. It usually starts with `xoxb-`.
- Open `Basic Information`.
- Copy the `Signing Secret`.
Back in Alloy:
- Open the same AI Teammate `Slack` tab.
- Click `Connect`.
- Paste:
- the Bot User OAuth Token into the bot token field;
- the Signing Secret into the signing secret field.
- Save the connection.
Alloy validates the installed bot token with Slack `auth.test`, stores the Slack bot user ID and app name for display, and does not return the bot token or signing secret through the read API.
After connection, the Slack tab exposes `Check permissions`. Alloy compares the granted token scopes with the required scope list. If permissions are missing, the tab lists them and instructs the user to copy the updated manifest, reinstall the app in Slack, and check again. If Slack scope inspection is unavailable, the tab reports that permissions could not be verified without treating the app as ready.
5. Add the bot to Slack conversations
After the Slack App is connected:
- Add or invite the bot to the Slack channel, private channel, or DM where it should operate.
- Send a first message in that Slack conversation.
- Return to the AI Teammate `Slack` tab in Alloy.
- Find the newly discovered Slack chat.
- Enable it.
Newly discovered Slack chats are disabled by default. This gives an Alloy user a chance to review each DM, channel, or private channel before the AI Teammate can respond there.
6. Test the connection
For direct messages, send a message to the bot after the DM chat is enabled.
For channels and private channels:
- Mention the bot in a channel message.
- Confirm the AI replies in a thread.
- Continue in that thread. Later replies in a thread whose root message triggered the bot can continue without
repeating the mention. If a reply explicitly @-mentions a different AI bot, the sticky bot does not re-engage; the mentioned bot answers instead.
If the bot sees a directly addressed message before the chat is enabled, the chat appears in Alloy and the bot replies:
`This chat isn't enabled for this AI employee yet. Please ask your {brand} administrator to enable it in the employee's channel settings.`
DMs always count as directly addressed. In channels and private channels, the notice is sent only for an explicit bot mention and stays in the triggering thread when a thread target is available. The disabled chat does not start an AI workflow. Enable the chat and send another message to test the full flow.
Runtime behavior
- Slack Events webhook:
`POST /webhooks/slack/events/{organizationId}/{employeeId}`
- AI Teammate Slack settings:
- `GET /api/organizations/{orgId}/employees/{employeeId}/slack`
- `POST /api/organizations/{orgId}/employees/{employeeId}/slack`
- `DELETE /api/organizations/{orgId}/employees/{employeeId}/slack`
- `GET /api/organizations/{orgId}/employees/{employeeId}/slack/manifest`
- Slack settings responses include `required_bot_scopes`, `message_events`, `missing_bot_scopes`, and `scope_check_status` (`ready`, `missing`, or `unavailable`).
- Known Slack chats:
- `GET /api/organizations/{orgId}/employees/{employeeId}/slack/chats`
- `PUT /api/organizations/{orgId}/employees/{employeeId}/slack/chats/{chatId}/status`
The Slack webhook accepts Slack URL verification challenges before signature checks, so Slack can verify the request URL during app setup. Normal event callbacks are verified with the app signing secret using Slack's `X-Slack-Signature` and `X-Slack-Request-Timestamp` headers.
Inbound Slack events are accepted only when the AI Teammate has Slack credentials configured. Alloy ignores non-message events, Slack message subtypes, bot/self messages, duplicate Slack timestamps, and empty messages without downloadable attachments.
For accepted messages, Alloy starts the AI Teammate workflow only when:
- the Slack DM, channel, or private channel is enabled for that AI Teammate;
- direct messages are used, or a channel/private-channel message addresses the bot;
- automation is enabled for the conversation;
- the organization has available tokens;
- the AI Teammate default workflow is present and has a starting step.
The disabled-chat gate runs before attachment download, conversation/message persistence, and workflow creation. Alloy keeps the newly discovered chat row so an operator can enable it.
Attachments are capped at `10` files, `10 MB` per file, and `30 MB` total per inbound message. Image attachments can be forwarded into the workflow input. Non-image attachments can be saved with the message but are not passed into the AI input payload.
During AI reply generation, Alloy sets a best-effort Slack assistant thread typing status when a thread timestamp is available.
AI replies without files are sent as Slack-format Markdown when the reply text is 12,000 characters or fewer. Longer text-only replies fall back to the plain `text` field so the message still delivers.
When the persisted AI reply has attachments, Alloy handles up to `10` files with a combined maximum of `30 MB` and keeps the reply in the Slack thread when applicable. For replies that contain text, Alloy posts the native Markdown message first, privately uploads the files, then attaches the returned Slack file IDs to that message. Text above 12,000 characters uses the top-level plain `text` field. Attachment-only replies use direct file sharing.
If attachment preparation fails before delivery, Alloy attempts a text-only Markdown fallback when reply text exists. If the text message was posted but a later file upload or attachment step fails, the posted text remains delivered and Alloy does not duplicate it. An indeterminate file-only upload result is not retried as text because the files may already have reached Slack.
Troubleshooting
- If Slack cannot verify the Request URL, confirm the URL exactly matches the Alloy `Events Request URL`.
- If Alloy rejects the connection, confirm the value is the Bot User OAuth Token, not the Slack app client secret.
- If Slack returns the disabled-chat notice instead of an AI answer, enable the discovered chat in the AI Teammate `Slack` tab.
- If the chat is enabled but the AI still does not reply, confirm the teammate default workflow is present and runnable. A missing default workflow is a rare exception and should be treated as a setup or data issue.
- If channel messages are saved but do not trigger the AI, mention the bot or continue in a thread whose root
message already mentioned the bot. If the message @-mentions a different AI bot, the sticky bot yields to the mentioned bot.
- If Slack file messages do not affect the workflow, confirm the file is an image and under the attachment size
limit.