# Slack (/docs/workflows/integrations/slack)

> For the complete documentation index, see [llms.txt](https://docs.tandemcx.ai/llms.txt). Any page on this site can be fetched as Markdown by appending `.md` to its URL.

The Slack integration lets a workflow or an AI agent post messages into your Slack
workspace: alerting a team when a call comes in, logging a completed transaction,
escalating a stuck conversation.

Tandem connects using **your own Slack app**, so you control which workspace it
posts to and exactly what it is allowed to do. Creating that app is a one-time
setup, described below.

## Setup

### 1. Create a Slack app

In [Slack's app directory](https://api.slack.com/apps), choose **Create New App →
From scratch**, name it, and pick the workspace it should post to.

### 2. Add the bot token scopes

Under **OAuth & Permissions → Scopes → Bot Token Scopes**, add:

| Scope                  | Needed for                                                      |
| ---------------------- | --------------------------------------------------------------- |
| `chat:write`           | Posting messages. Required.                                     |
| `channels:read`        | Listing **public** channels in the node's channel dropdown.     |
| `groups:read`          | Listing **private** channels in the same dropdown.              |
| `chat:write.customize` | Only if you use the node's Sender Name / Sender Icon overrides. |
| `users:read`           | Listing people for a direct message.                            |
| `im:write`             | Sending a direct message.                                       |

Without `channels:read` and `groups:read` the node still sends. You just have to
type the channel instead of picking it from a list.

### 3. Install the app and copy the token

Under **OAuth & Permissions**, click **Install to Workspace** and approve. Copy
the **Bot User OAuth Token** — it starts with `xoxb-`.

### 4. Connect it in Tandem

On the **Integrations** page, add a Slack integration, give it a name, and paste
the `xoxb-` token. Tandem validates the token against Slack before saving, so a
typo is rejected immediately rather than surfacing later as a failed send.

### 5. Invite the bot to each channel

In Slack, run `/invite @your-app-name` in every channel the workflow will post
to. A bot that has not been invited cannot post, even with `chat:write`.

<Callout type="warn">
    **Adding a scope later requires reinstalling the app, and reinstalling issues a new bot token.**
    These fail in opposite, equally confusing ways: add `channels:read` without reinstalling and
    nothing changes, because the old token still carries the old scopes; reinstall without pasting
    the new token into Tandem and a previously working node starts failing. Whenever you change
    scopes, do both: reinstall, then update the token on the integration.
</Callout>

## What you can do

- **Post a message** — send text to any public or private channel the bot has
  been invited to.
- **Build the message from the flow** — the message text is `$(variable)`
  interpolated, so it can carry caller details, results from earlier nodes, and
  so on.
- **Choose the channel at runtime** — pick a channel from the dropdown, or type a
  `$(variable)` to route the message based on what happened in the flow.
- **Capture the result** — save `$.ts` (the message timestamp) and `$.channel`
  (the resolved channel id) into variables.

## Giving it to an AI agent

On an agent's **Tools**, add a tool of kind **Integration** and pick your Slack app from the
target list, where connected Slack apps appear under a **Slack** heading. Picking one swaps the
method and path fields for an **Action** (**Send Message**) and a destination.

Under **Post To**, choose **Channel** or **Direct Message** and pick where messages go. You set
the destination, the **Name**, and the **Description**; the model writes only the message text.
The description is what the model reads to decide when to post, so write it for that: _"Posts a
note to #support when a caller asks for a callback you cannot schedule."_

See [Add an integration tool](/docs/agents/voice-agents/tools#slack) for the full reference.

## Troubleshooting

| What you see                                 | What it means                                                                                            |
| -------------------------------------------- | -------------------------------------------------------------------------------------------------------- |
| The bot is not a member of that channel      | Run `/invite @your-app-name` in that channel.                                                            |
| The Slack app is missing a scope             | Add it under **Bot Token Scopes**, reinstall, and paste the new `xoxb-` token into the integration.      |
| That Slack channel does not exist            | The name is wrong, or it's a private channel the bot has not been invited to.                            |
| The bot token is invalid or has been revoked | The app was reinstalled or the token rotated — paste the current token into the integration.             |
| The channel dropdown is empty or partial     | Missing `channels:read` (public) or `groups:read` (private). Add the scope, reinstall, update the token. |

<Callout>
    Use **Test Connection** on the integration to check the stored token at any time. It validates
    the token itself. It can't tell you whether the bot has been invited to a particular channel.
</Callout>

## Nodes

The **Send Slack Message** node is rolling out; its reference page appears here
once it is generally available.

<IntegrationNodes provider="slack" />
