# Slack

> Connect Slack to your agents for messaging, channels, and events.

**URL:** https://inference.sh/docs/credentials/slack
**Last updated:** 2026-10-31

---

Connect Slack to your agents for messaging, channels, and events.

---

## Overview

Slack credentials let your agents send messages, read channels, respond to events, and interact with your Slack workspace.

### Why "Bring Your Own Key" (BYOK)?

By using your own Slack app, you get complete control over events and triggers. Events only come from workspaces where your app is installed—no noise from other users.

**Benefits:**

- **Isolated events** — only receive events from your workspaces
- **Full control** — configure exactly which events to subscribe to
- **Bot tokens** — send messages as your custom bot
- **Webhook verification** — secure event delivery with your signing secret

---

## Prerequisites

Before connecting, you'll need:

1. A Slack workspace where you have admin permissions (or can request app approval)
2. A Slack account to create the app

---

## Step 1: Create a Slack App

1. Go to the [Slack API portal](https://api.slack.com/apps)
2. Click **Create New App**
3. Choose **From scratch**
4. Name your app (e.g., "Inference Agent")
5. Select your workspace
6. Click **Create App**

Pick **From scratch**, not the "AI agent" or "Starter app" templates — those scaffold
slash commands and event listeners you do not need for sending messages.

### Faster: create it from a manifest

**From a manifest** on the same screen sets the name, bot user, scopes and redirect URL
in one step, so you can skip Steps 2 and 3. Paste this, then adjust the name and scopes:

```yaml
display_information:
  name: inference agent
  description: Agent messages from inference shell
features:
  bot_user:
    display_name: inference agent
    always_online: false
oauth_config:
  redirect_urls:
    - https://app.inference.sh/settings/secrets/oauth/slack
  scopes:
    bot:
      - chat:write
      - chat:write.public
      - channels:read
settings:
  org_deploy_enabled: false
  socket_mode_enabled: false
  token_rotation_enabled: false
```

Those three scopes cover posting: `chat:write` to post and edit, `chat:write.public` to
post to a public channel the bot has not been invited to, `channels:read` to list
channels. Add more from [Common scopes](#common-scopes) for reading history, reactions or
files. Use the staging or local redirect URL from Step 3 if you are not connecting to
production.

After creating it, **Install to Workspace**, then continue from Step 4.

---

## Step 2: Configure OAuth Scopes

1. In your app settings, go to **OAuth & Permissions**
2. Scroll to **Scopes** section
3. Add **Bot Token Scopes** based on what you need:

### Common scopes

| Scope | Allows |
|-------|--------|
| `channels:read` | View basic channel info |
| `channels:history` | Read channel messages |
| `chat:write` | Send messages as your bot |
| `users:read` | View user profiles |
| `reactions:read` | View emoji reactions |
| `files:read` | Access files shared in channels |

4. Add **User Token Scopes** if you need to act as the user:

| Scope | Allows |
|-------|--------|
| `channels:read` | View channels the user is in |
| `chat:write` | Send messages as the user |

---

## Step 3: Configure OAuth Redirect URL

1. In **OAuth & Permissions**, scroll to **Redirect URLs**
2. Add the callback URL:

| Environment | Callback URL |
|-------------|-------------|
| Production | `https://app.inference.sh/settings/secrets/oauth/slack` |
| Staging | `https://app.staging.inference.sh/settings/secrets/oauth/slack` |
| Local dev | `http://localhost:3000/settings/secrets/oauth/slack` |

3. Click **Save URLs**

---

## Step 4: Get Your Credentials

1. Go to **Basic Information** in your app settings
2. Copy these values:

| Credential | Location | Purpose |
|------------|----------|---------|
| **Client ID** | App Credentials | OAuth authentication |
| **Client Secret** | App Credentials | OAuth authentication |
| **Signing Secret** | App Credentials | Webhook verification |

### Bot token

A bot token lets an app post to Slack directly, with no OAuth round trip per user. It is
what you want for one-way messaging: alerts, build results, digests, an agent that reports
into a channel.

**It does not exist until the app is installed**, and it is not on Basic Information:

1. Sidebar → **Install App** → **Install to Workspace** → **Allow**
2. Sidebar → **OAuth & Permissions** → **Bot User OAuth Token**, at the top, starting `xoxb-`

Then give it to inference shell, either way:

| Where | How | Use when |
|-------|-----|----------|
| Team secret | `belt secrets set SLACK_BOT_TOKEN` (prompts for the token) | One workspace, your own team |
| Slack credential | Paste into the **bot token** field when connecting Slack | The token belongs with the same app's client id and secret |

Both arrive in an app as `SLACK_BOT_TOKEN`. Use a team secret when the bot posts to a
different workspace than the OAuth app serves — keeping two workspaces in one credential
record reads as a mistake later.

Adding scopes after installing does not update the token's permissions: reinstall the app,
or calls fail with `missing_scope`.

---

## Step 5: Connect in inference shell

### Configure credentials

1. Go to **vaults → credentials**
2. Find **Slack** and click **Configure**
3. Enter your credentials:
   - **Client ID**
   - **Client Secret**
   - **Signing Secret** (for webhook events)
   - **Bot Token** (optional, for sending messages)
4. Click **Save credentials**

> These are stored securely as encrypted secrets.

### Authorize the connection

1. Click **Connect**
2. You'll be redirected to Slack to authorize
3. Select your workspace and review permissions
4. Click **Allow**
5. Done! Your Slack credential is now active.

---

## Event Subscriptions (agent chat)

To let users message your agent from Slack, point Slack event subscriptions at your agent's **channel webhook**. Each agent has its own endpoint. Replace `{agent_id}` with the agent ID from the web app.

| Environment | Request URL |
|-------------|-------------|
| Production | `https://api.inference.sh/agents/{agent_id}/channel/slack` |
| Legacy (still supported) | `https://api.inference.sh/agents/{agent_id}/slack` |

The endpoint verifies requests with your **Signing Secret** (no API key). Inbound messages start an agent chat; replies are delivered back to the same Slack thread, including streaming and typing indicators when supported. The platform records `channel_context` (`channel_type: slack` plus thread metadata) on the chat, and later turns reply to the same thread. Only messages that arrive through this endpoint set it; `POST /agents/run` ignores a `channel_context` field.

→ [Agents API — Messaging channel webhooks](/docs/api/rest/agents#messaging-channel-webhooks) · [Channel context](/docs/api/rest/agents#channel-context)

1. In your Slack app, go to **Event Subscriptions**
2. Toggle **Enable Events** to On
3. Set the **Request URL** to your agent's channel webhook (table above)
4. Subscribe to bot events you want:

| Event | Trigger |
|-------|---------|
| `message.channels` | New message in a channel |
| `message.im` | Direct message to your bot |
| `app_mention` | Someone @mentions your bot |
| `reaction_added` | Emoji reaction added |
| `member_joined_channel` | User joins a channel |

5. Click **Save Changes**

---

## Capabilities

| Capability | Description | Required Scopes |
|------------|-------------|-----------------|
| `slack.channels.read` | Read channel info | `channels:read` |
| `slack.channels.history` | Read channel messages | `channels:history` |
| `slack.channels.write` | Send messages | `chat:write` |
| `slack.users.read` | Read user profiles | `users:read` |
| `slack.reactions.read` | Read emoji reactions | `reactions:read` |
| `slack.files.read` | Read shared files | `files:read` |

---

## Using in apps

Declare Slack requirements in your app:

```yaml
# inf.yml
credentials:
  - key: slack.channels.write
    description: Send notifications to Slack

  - key: slack.channels.history
    description: Read channel messages
    optional: true
```

At runtime, your app receives:

```bash
SLACK_ACCESS_TOKEN=xoxp-user-token
SLACK_BOT_TOKEN=xoxb-bot-token
SLACK_TEAM_ID=T01234567
```

### Example: Send a message

```python
from slack_sdk import WebClient
import os

client = WebClient(token=os.environ["SLACK_BOT_TOKEN"])

client.chat_postMessage(
    channel="#general",
    text="Hello from my AI agent! 🤖"
)
```

### Example: Read channel history

```python
from slack_sdk import WebClient
import os

client = WebClient(token=os.environ["SLACK_ACCESS_TOKEN"])

result = client.conversations_history(channel="C01234567", limit=10)

for message in result["messages"]:
    print(f"{message.get('user')}: {message.get('text')}")
```

---

## Security

- **Your app** — you control the Slack app and its permissions
- **Signing secret** — webhook events are verified using your secret
- **Encrypted storage** — all credentials are encrypted at rest
- **Revocable** — uninstall the app from your workspace anytime

### Revoking access

1. **From inference shell**: **vaults → credentials → disconnect**
2. **From Slack**: Workspace Settings → Manage Apps → Remove

---

## Troubleshooting

### "Callback URL mismatch"

- Ensure the redirect URL in your Slack app matches exactly
- The URL is case-sensitive

### "Invalid signing secret"

- Verify you copied the Signing Secret from Basic Information
- Make sure there are no extra spaces
- Save it on your workspace's Slack OAuth app (**Configure credentials** or `PUT /credentials/slack/app`); verification reads it from there

### "Missing scopes"

- Add the required scopes in OAuth & Permissions
- Reinstall the app to your workspace after adding scopes

### "Channel not found"

- Your bot needs to be invited to private channels
- Use `/invite @YourBotName` in the channel

---

## Next

→ [Discord](/docs/credentials/discord)

