> ## Documentation Index
> Fetch the complete documentation index at: https://opensre.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Slack

> Post messages via webhook, and chat with the agent via Socket Mode.

## Overview

The Slack integration covers two surfaces:

1. **Incoming webhook** — outbound delivery of agent messages and scheduled reports to a channel.
2. **Socket Mode bot** — two-way chat with the OpenSRE agent (mentions and DMs), managed the same way as the [Telegram gateway](/docs/integrations/messaging/telegram#two-way-chat-gateway-dm-text).

## Prerequisites

* A Slack workspace where you can create or install apps (workspace admin or app-install permissions).
* The channel you want messages posted to (webhook) and/or where the bot will be invited (Socket Mode).

## Setup

### Option 1: Direct setup command (recommended)

```bash theme={null}
opensre integrations setup slack
```

Choose **webhook**, **Socket Mode**, or **both**. Credentials are persisted to `~/.opensre/integrations.json` (and can be merged on re-run). Picking one mode clears the other when you intentionally switch.

### Option 2: Environment variables

```bash theme={null}
SLACK_WEBHOOK_URL=https://hooks.slack.com/services/<workspace-id>/<binding-id>/<secret>
# Optional Socket Mode gateway:
SLACK_BOT_TOKEN=xoxb-…
SLACK_APP_TOKEN=xapp-…
SLACK_ALLOWED_USERS=U0123ABCD
# Optional default channel for scheduled bot-token delivery:
# SLACK_DEFAULT_CHAT_ID=C0123ABCD
```

| Variable                     | Description                                                                                                                                    |
| ---------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------- |
| `SLACK_WEBHOOK_URL`          | Incoming webhook URL. Required for outbound delivery.                                                                                          |
| `SLACK_BOT_TOKEN`            | Bot token (`xoxb-…`) for the two-way Slack bot. Env or integration store.                                                                      |
| `SLACK_DEFAULT_CHAT_ID`      | Default channel (`C…`) for scheduled delivery when using a bot token. Env or integration store; pair it with the same source as the bot token. |
| `SLACK_APP_TOKEN`            | App-level token (`xapp-…`) for Socket Mode. Env or integration store.                                                                          |
| `SLACK_ACCESS_TOKEN`         | User token (`xoxp-…`) with `search:read`. Required only for `slack_search_messages` — Slack rejects bot tokens there.                          |
| `SLACK_ALLOWED_USERS`        | Comma-separated Slack user IDs allowed to talk to the bot (required unless open workspace).                                                    |
| `SLACK_ALLOW_OPEN_WORKSPACE` | Set to `1` to allow any workspace member (dogfood escape hatch).                                                                               |
| `SLACK_TEAM_TASKS_LIST_ID`   | Optional Slack List id (`F…`) for `slack_read_list` without a name search.                                                                     |

OpenSRE reads env as a fallback when no Slack entry exists in `~/.opensre/integrations.json`. Bot / app tokens use `resolve_env_credential` (process env, then the credentials file). `SLACK_WEBHOOK_URL` is store/env only.

<Note>
  **Credential resolution.** Store first when present. Then: `SLACK_BOT_TOKEN` / `SLACK_APP_TOKEN` → env then keyring; `SLACK_WEBHOOK_URL` → plain env only (never keyring).
</Note>

Socket Mode needs **both** `xoxb-` and `xapp-` tokens (prefixes enforced).

## Credentials

### Create a Slack incoming webhook

1. Visit [https://api.slack.com/apps](https://api.slack.com/apps) and click **Create New App → From scratch**.
2. Name the app (e.g. `OpenSRE`) and pick your workspace.
3. In the left sidebar, open **Incoming Webhooks** and toggle the feature **On**.
4. Click **Add New Webhook to Workspace**.
5. Pick the channel where messages should be posted and click **Allow**.
6. Copy the generated URL:

   ```text theme={null}
   https://hooks.slack.com/services/<workspace-id>/<binding-id>/<secret>
   ```

<Note>
  Treat this URL like a password — anyone holding it can post to your channel. If your workspace already has a Slack app you want to reuse, you can add a new webhook to it instead of creating a fresh app; the URL format is the same.
</Note>

### Create Socket Mode tokens

1. In your Slack app settings, enable **Socket Mode** and create an app-level token with the `connections:write` scope (`xapp-…`).
2. Under **OAuth & Permissions**, grant the bot scopes below, then install the app and copy the bot token (`xoxb-…`).
3. Under **Event Subscriptions**, subscribe to the bot events `app_mention` and `message.im`.

**Bot Token Scopes (Socket Mode chat + teammate tools):**

| Scope                | Needed for                                                              |
| -------------------- | ----------------------------------------------------------------------- |
| `app_mentions:read`  | Gateway `@mention` inbound                                              |
| `chat:write`         | Gateway replies + `slack_reply_message`                                 |
| `im:history`         | Gateway DMs + reading DM history                                        |
| `channels:history`   | `slack_read_messages` + thread seeding in public channels               |
| `groups:history`     | `slack_read_messages` in private channels                               |
| `mpim:history`       | `slack_read_messages` in multi-party DMs                                |
| `groups:read`        | Resolve private channel names                                           |
| `groups:write`       | Manage / create private channels                                        |
| `files:read`         | Inbound file-attachment downloads + discover Slack Lists (`files.list`) |
| `files:write`        | Upload files as the bot                                                 |
| `lists:read`         | `slack_read_list` — read Slack List rows (`slackLists.items.list`)      |
| `usergroups:read`    | View workspace user groups                                              |
| `users.profile:read` | Speaker profile details                                                 |
| `users:read`         | `slack_list_team_members` + user lookup                                 |

<Note>
  Add these only if you use the feature — they are not in the current app config: `reactions:write` (gateway ack 👀 / ✓ reactions + `slack_add_reaction`), `channels:read` / `im:read` / `mpim:read` (resolve `#channel-name` and DM names → ID), and `channels:join` (`slack_join_channel`).
</Note>

Reinstall the app after adding scopes so the bot token picks them up. Invite the bot (`/invite @OpenSRE`) to private channels it should read or post in.

<Note>
  `slack_search_messages` is the one tool a bot token can never run — Slack refuses bot tokens for workspace message search, no matter which scopes you grant. To enable search, add `search:read` under **OAuth & Permissions → User Token Scopes**, reinstall, and set `SLACK_ACCESS_TOKEN` to the resulting user token (`xoxp-…`). Leave it unset and search simply stays hidden from the agent; every other Slack tool works on the bot token alone.
</Note>

### Allow your Slack user

Find your Slack **member ID** (`U…`) in the Slack app: profile → **⋯** → **Copy member ID**.

```bash theme={null}
opensre messaging allow -p slack -u U0123ABCD
# or in REPL: /messaging allow -p slack -u U0123ABCD
```

or set `SLACK_ALLOWED_USERS=U0123ABCD` in `.env`. The integration store takes precedence when both are set.

<Warning>
  Use the Slack **member ID** (`U…`) from **Copy member ID**, not `@display-name`. Handles can be reassigned; inbound authorization only matches stable user IDs.
</Warning>

For dogfood only, you may set `SLACK_ALLOW_OPEN_WORKSPACE=1` instead.

### DM pairing (optional)

```bash theme={null}
opensre messaging pair -p slack
```

Then DM the bot (or mention it) and send `/pair <code>`.

```bash theme={null}
opensre messaging status -p slack
opensre messaging revoke -p slack -u U0123ABCD
```

## Slack tools

Teammate tools (bot token) plus webhook blast. Credentials resolve inside the tools (never in tool-call traces). Shared client: `integrations/slack/web_client.py`.

| Tool                          | What it does                                   | Needs                                                | Approval |
| ----------------------------- | ---------------------------------------------- | ---------------------------------------------------- | -------- |
| `slack_send_message`          | Post to the webhook's fixed channel            | `SLACK_WEBHOOK_URL`                                  | No       |
| `slack_reply_message`         | Post to any channel/thread (`C…` or `#name`)   | bot token, `chat:write`                              | No       |
| `slack_read_messages`         | Read channel history or a thread (`thread_ts`) | bot token, history + list scopes                     | No       |
| `slack_search_messages`       | Workspace message search                       | **user** token (`SLACK_ACCESS_TOKEN`), `search:read` | No       |
| `slack_list_team_members`     | List workspace members                         | bot token, `users:read`                              | No       |
| `slack_join_channel`          | Join a public channel                          | bot token, `channels:join`                           | Yes      |
| `slack_add_reaction`          | React to a message ts                          | bot token, `reactions:write`                         | No       |
| `slack_read_list`             | Read Slack List rows                           | bot token, `lists:read`                              | No       |
| `replay_slack_thread_locally` | Replay a Slack thread into the local session   | bot token                                            | No       |

Prefer `slack_reply_message` / `slack_read_messages` when the bot token is configured and the user names a channel or thread. Use `slack_send_message` only for the fixed webhook channel.

For "add task", "remind me", and "what should we focus on next" requests, use OpenSRE work management. Gateway turns can default reminders and recurring check-ins to the current Slack channel.

Example prompts:

* "Read the last 20 messages in #incidents and summarize."
* "Search Slack for 'Windows install' this week."
* "Join #ops then reply that mitigation is rolled out."
* "Who is on the team, and what does Vaibhav do?"
* "Add task: ping owners about the deploy window."
* "Get GitHub star velocity for the last 30 days on `your-org/your-repo` and post it to Slack."
* "Generate a Slack-ready work status report for `your-org/your-repo` and post it."

The last two need [GitHub configured](/docs/integrations/code/github) and name the repository explicitly
(`your-org/your-repo`) so the GitHub tools can resolve it — see
[GitHub workflow tools](/docs/integrations/code/github-workflow-tools) for what they can report on.
Message tools post without a separate approval prompt; check the target channel
for the delivered message.

### Production Engineer schedules (Slack)

Wire morning digests, PR sweeps, and `/loops` prompt loops to Slack. The gateway daemon (or `opensre cron start`) must be running so the scheduler can deliver when a tick finishes — the report arrives proactively; you do not need to ask in chat.

**Destination options:**

| Setup                   | How to target Slack                                                              |
| ----------------------- | -------------------------------------------------------------------------------- |
| Incoming webhook        | Omit `--chat-id` — the webhook URL is bound to one channel                       |
| Bot token (Socket Mode) | Set `SLACK_DEFAULT_CHAT_ID` (or pass `--chat-id` / `/loops add --slack-chat-id`) |

Copy the channel id (`C…`) from Slack channel details. During `opensre integrations setup slack` (Socket Mode or Both), you can persist a default channel id for scheduled delivery. The default channel is taken from the same place as the bot token: if the token is in `.env`, set `SLACK_DEFAULT_CHAT_ID` there too. A channel saved only in the integration store is not paired with an env or task-level token.

```bash theme={null}
opensre sentry digest schedule add \
  --cron "0 8 * * mon-fri" --tz Europe/London \
  --provider slack --chat-id C0123ABCD

# Webhook: omit --chat-id
opensre cron add --kind github_pr_sweep --cron "0 9 * * mon-fri" \
  --tz Europe/London --provider slack

# Bot token: default channel or explicit --chat-id
export SLACK_DEFAULT_CHAT_ID=C0123ABCD
opensre cron add --kind github_pr_sweep --cron "0 9 * * mon-fri" \
  --tz Europe/London --provider slack --chat-id C0123ABCD
```

See [Scheduled deliveries](/docs/platform/cron) and [Sentry morning digest](/docs/integrations/incidents/sentry#morning-digest-scheduled).

### Two-way chat gateway (Socket Mode)

No public inbound HTTPS URL is required — the gateway holds an outbound websocket. Each thread is its own conversation.

```bash theme={null}
opensre gateway start
opensre gateway status
# want: slack: connected via socket mode
```

| Command                   | What it does                                       |
| ------------------------- | -------------------------------------------------- |
| `opensre gateway start`   | Start the daemon (web, Telegram, Slack, scheduler) |
| `opensre gateway status`  | Show daemon and component state                    |
| `opensre gateway logs -f` | Follow live gateway logs                           |
| `opensre gateway stop`    | Stop the daemon                                    |

Built-in chat commands: `/new` (fresh session), `/help`, `/pair <code>`.

While a turn runs, the gateway adds an 👀 (`eyes`) reaction on the inbound message, then swaps to ✅ (`white_check_mark`) when the reply is finalized.

If Slack is not configured the daemon still runs the other components and `opensre gateway status` shows `slack: not configured`.

### Deploying the Slack gateway

The Slack gateway backend is deployed and operated separately — not from this repo. Configure the integration here (tokens and scopes above); provisioning the hosted backend is out of scope for this repo.

The EC2 gateway path (`make deploy-gateway`) is **Telegram-only** and ignores `SLACK_*` variables with a validation warning: Slack Socket Mode is single-consumer, so a second gateway holding the same tokens would split events.

## Verify

```bash theme={null}
opensre integrations verify slack
```

A successful run reports the integration as `passed`. Webhook-only configs confirm the URL is present; Socket Mode configs also run Slack `auth.test` on the bot token. To also confirm webhook delivery, add the `--send-slack-test` flag:

```bash theme={null}
opensre integrations verify slack --send-slack-test
```

This posts a small test message to the configured channel.

## Troubleshooting

| Symptom                                          | Fix                                                                                                                                                     |
| ------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **`error: webhook_url is required.` from setup** | You chose webhook (or both) and left the URL empty. Re-run and paste the full URL including `https://`, or choose Socket Mode only.                     |
| **`slack: not configured` from gateway status**  | Missing `SLACK_BOT_TOKEN` / `SLACK_APP_TOKEN` or empty allowlist without `SLACK_ALLOW_OPEN_WORKSPACE=1`. Allow yourself, then `gateway stop` / `start`. |
| **Connected, but deny reply**                    | Your `U…` is not in the allowlist. Pair with `/pair <code>` or `messaging allow`.                                                                       |
| **`invalid_payload` or `channel_not_found`**     | Recreate the webhook for the current channel and update `SLACK_WEBHOOK_URL`.                                                                            |
| **Messages posted to the wrong channel**         | A webhook is bound to the channel it was created against — create a new webhook for the new channel.                                                    |
| **Webhook returns `no_service`**                 | The Slack app or webhook was deleted. Re-create it and update the URL.                                                                                  |

## Security

* Treat webhook URLs and bot/app tokens like passwords.
* Prefer least-privilege bot scopes; add optional scopes only when you use those tools.
* Keep `SLACK_ALLOWED_USERS` set in production; treat open-workspace mode as dogfood only.
* Store secrets in the integration store / keyring / secret manager — not in source control.
