---
title: "Slack"
description: "The verified plugin ai.oz0/slack - Slack as the front door to your agents, with answers, questions and approvals in threads."
canonical_url: "https://docs.oz0.ai/build/plugins/verified/slack"
---
# Slack

> The verified plugin ai.oz0/slack - Slack as the front door to your agents, with answers, questions and approvals in threads.

For: tenant administrators and plugin users.

`ai.oz0/slack` connects Slack as a [chat channel](https://docs.oz0.ai/build/apps/chat-channels). Mention your Slack app or send `/oz0 <request>` to start an agent [bound to that channel](https://docs.oz0.ai/build/apps/chat-channels#bind-a-channel-to-agents).

The answer, questions and approvals arrive in the thread. Reply there to continue the conversation.

<table>
<thead>
  <tr>
    <th>
      
    </th>
    
    <th>
      
    </th>
  </tr>
</thead>

<tbody>
  <tr>
    <td>
      Manifest name
    </td>
    
    <td>
      <code>
        slack
      </code>
      
       (hub name <code>
        ai.oz0/slack
      </code>
      
      )
    </td>
  </tr>
  
  <tr>
    <td>
      Tool
    </td>
    
    <td>
      <code>
        oz0_slack
      </code>
      
      : <code>
        normalize
      </code>
      
       (the event source), <code>
        post
      </code>
      
       (the channel), <code>
        send
      </code>
      
       (an agent posts a message)
    </td>
  </tr>
  
  <tr>
    <td>
      Event source and channel
    </td>
    
    <td>
      <code>
        slack
      </code>
      
      , on <code>
        POST https://&lt;edge>:7443/events/&lt;tenant>/slack
      </code>
    </td>
  </tr>
  
  <tr>
    <td>
      Tenant secrets
    </td>
    
    <td>
      <code>
        SLACK_SIGNING_SECRET
      </code>
      
       (read by the edge only), <code>
        SLACK_BOT_TOKEN
      </code>
      
       (<code>
        xoxb-…
      </code>
      
      , saved by Connect or set by hand, which connection <code>
        slack
      </code>
      
       hands each call that posts or opens a form, for that call only; it is never in the plugin's environment); <code>
        SLACK_CLIENT_SECRET
      </code>
      
       for Connect
    </td>
  </tr>
  
  <tr>
    <td>
      Connection
    </td>
    
    <td>
      <code>
        slack
      </code>
      
      : your own Slack app from a manifest, its credentials pasted and checked, then Slack's OAuth v2 install
    </td>
  </tr>
  
  <tr>
    <td>
      Egress
    </td>
    
    <td>
      <code>
        slack.com
      </code>
      
       (the Web API) and <code>
        hooks.slack.com
      </code>
      
       (slash commands' and clicks' response URLs); GovSlack's hosts go on the tenant's egress allowlist
    </td>
  </tr>
</tbody>
</table>

Upgrading to 1.1.0 needs nothing: the same `SLACK_BOT_TOKEN` now reaches each call through the connection instead of
the plugin's environment, and the egress names exact hosts instead of `*.slack.com`.

## Create your own Slack app, about two minutes

Every cluster uses a Slack app of its own, since Slack sends an app's events to one URL and yours go to your edge. Connect makes it from a manifest with your edge's URLs filled in ([Connections](https://docs.oz0.ai/admin/connections#your-own-app-about-two-minutes)):

```bash [Terminal]
oz0 plugin install hub:ai.oz0/slack
oz0 connection start slack --open --wait 15m
```

Or in the console: Credentials, Connections, `slack`, Connect. The edge's page for the first step opens:

1. Create the app on Slack opens Slack's new-app page with the manifest filled in: the app's name (your tenant's plus `-oz0`, shortened to Slack's 35 characters; `--param app_name=...` for another), its bot, the `/oz0` command, the event subscriptions (`app_mention`, `message.channels`, `message.groups`, `message.im`) and interactivity, all on `https://<edge>/events/<tenant>/slack`, the connection's callback as the redirect URL, and the bot scopes `app_mentions:read`, `chat:write`, `commands`, `channels:history`, `groups:history` and `im:history`. Pick the workspace and create it.
2. From the app's Basic Information, App Credentials, paste the Client ID, the Client Secret and the Signing Secret on the edge's page. The edge checks each one's form, asks Slack's `oauth.v2.access` whether it knows the Client ID and Client Secret (with a code that is not one, which Slack refuses as `invalid_code` only for a client it knows), then seals the secrets as `SLACK_CLIENT_SECRET` and `SLACK_SIGNING_SECRET`, and never shows them again.
3. On the app's Event Subscriptions page, click Retry next to the Request URL. Slack sends its URL check again, signed with the signing secret; the edge answers it only if the secret you pasted is the app's, and the page goes on.
4. Slack asks you to allow the app in your workspace. The edge exchanges the code with the client secret, seals the bot token as `SLACK_BOT_TOKEN` (management never sees it; the edge hands it to each call that needs it), and checks it with Slack's `auth.test`.

Then bind the channel and map people:

```bash [Terminal]
oz0 channel bind helpdesk --channel slack --agent support-triage
oz0 channel member add slack U0123ABCD alice --workspace T0456EFGH
```

Your Slack user ID is under your profile, Copy member ID; the workspace ID is in the workspace's URL (`connection show slack` shows it too). Or let people link themselves: each makes a code under Chat channels in the console (or `oz0 channel link`) and sends `link <code>` to the app in a direct message or as `/oz0 link <code>`. Turn on the Messages Tab under App Home so people can write to the app directly. GovSlack: `--param slack_url=https://slack-gov.com`, and `--param apps_url=` its app settings page.

If a step does not pass, its page says why; [troubleshooting](https://docs.oz0.ai/admin/connections/troubleshooting#troubleshooting) has Slack's usual causes (the URL not verified, a wrong signing secret, missing scopes).

### By hand

1. Create a Slack app for your workspace at Slack's app settings, from scratch.
2. OAuth & Permissions, bot token scopes: `app_mentions:read`, `chat:write`, `commands`, `channels:history`, `groups:history` (to see replies in threads of public and private channels), `im:history` (direct messages, where people [link their identity](https://docs.oz0.ai/build/apps/chat-channels#link-your-own-chat-identity)). Install the app to the workspace and copy the Bot User OAuth Token.
3. Basic Information: copy the Signing Secret.
4. Event Subscriptions: on, with the request URL `https://<edge>:7443/events/<tenant>/slack`. Slack checks it at once; the edge answers its challenge. Subscribe to the bot events `app_mention`, `message.channels`, `message.groups` and `message.im`, and turn on the Messages Tab under App Home.
5. Interactivity & Shortcuts: on, with the same URL.
6. Slash Commands: create `/oz0` with the same URL.

```bash [Terminal]
oz0 secret set SLACK_SIGNING_SECRET --from-file ~/.secrets/slack-signing --signing --host <edge>:7443
oz0 secret set SLACK_BOT_TOKEN --from-file ~/.secrets/slack-bot-token
```

## In Slack

- `@oz0 what broke last night?` in a channel the app is in starts the binding's default agent, in a thread on the mention.
- `/oz0 billing why was I charged twice?` starts `billing` when the binding allows it; Slack shows you "On it." and the app posts "you asked billing: …" and starts the thread there.
- A reply in the thread goes on with the conversation. A reply to an open question answers it.
- Questions have a button per choice, or Answer, which opens a form (a [typed question](https://docs.oz0.ai/agents/asking-people#typed-questions)'s fields in a modal). Approvals have Approve and Deny, and Edit and approve opens a modal with the call's fields, where an optional date or choice can be left empty ([edit forms per chat](https://docs.oz0.ai/agents/approvals/edits-and-repeat-calls#edit-forms-in-chat-threads)); only mapped people with the operator role decide, everyone else gets a message only they see. Open in OZ is a link button to the job's page in the console.
- An answer that matches its agent's contract and is a table or key-values comes as section fields, each value plain text ([results as cards](https://docs.oz0.ai/build/apps/chat-channels/conversations#results-as-cards)).

The edge refuses a delivery whose `X-Slack-Signature` does not match the signing secret or whose `X-Slack-Request-Timestamp` is more than five minutes off. What the plugin posts is escaped (`&`, `<`, `>`), so nothing an agent writes mentions `@channel` or anyone else; only the person who asked is named.

## For agents

An agent that lists `oz0_slack.send` may post to a channel by its ID: `send(channel, text, thread?)`. The text starts with the tenant's [AI label](https://docs.oz0.ai/govern/ai-labels), `[AI agent] ...`, as the platform's own posts do. Give it to agents that need to, and mind that it posts as the app. Give agents `send`, never `post`: buttons count only on the platform's own messages, but `post` lets an agent post buttons at all. An agent that calls `post` anyway gets the AI label on its message too.

A rate limit (429, `ratelimited`) or Slack's 5xx is reported as retryable, and the platform posts again after the wait Slack asked for. `not_in_channel` is final: invite the app to the channel, and the person who asked is told so.

## Settings

`SLACK_API_URL` in the tool's environment points the plugin at another Web API, such as GovSlack's (`https://slack-gov.com/api`) or a test fake.

## A message an agent sends asks by default

The plugin's suggested policy asks a person before each `send` ("the plugin asks before it sends a message"), as a
function that does not say whether it destroys anything did already. The install writes it as a rule of the tenant's
tool policy, marked as the plugin's. An admin who lets an agent post on its own switches it, with a reason:
`oz0 plugin policy slack --set oz0_slack.send=allow --reason "..."`. The channel's own replies (`post`) are the platform's
and not asked about.


## Sitemap

See the full [sitemap](https://docs.oz0.ai/sitemap.md) for all pages.
