---
sidebar_position: 5
title: Slack
---

# Slack skill

Read/write a Slack workspace — list channels, post messages, reply in threads, react, read history, list users.

- **ID:** `slack`
- **MCP server:** `slack` (tools exposed as `mcp__slack__*`)
- **Underlying server:** `npx @modelcontextprotocol/server-slack@latest`

## Tools provided

| Tool | What it does |
|---|---|
| `slack_list_channels` | List public channels (id, name, topic) |
| `slack_post_message` | Post a top-level message. Requires `channel` and `text` |
| `slack_reply_to_thread` | Post a reply with `thread_ts` |
| `slack_add_reaction` | Add an emoji reaction to a message |
| `slack_get_channel_history` | Recent messages in a channel (`limit` default 20) |
| `slack_get_thread_replies` | All replies in a thread |
| `slack_get_users` | Workspace members (excludes bots and deleted) |
| `slack_get_user_profile` | Detailed profile for a `user_id` |

## Setup

Slack uses a bot token + workspace team id.

1. Create (or reuse) a Slack app at [api.slack.com/apps](https://api.slack.com/apps).
2. Add Bot Token Scopes — the full set this skill's tools need:
   `chat:write`, `channels:read`, `channels:history`, `groups:read`, `groups:history`,
   `reactions:write`, `users:read`, `users:read.email`, `users.profile:read`, `usergroups:read`.
   (`users:read.email` backs `slack_find_user_by_email`; `usergroups:read` backs
   `slack_list_usergroups` / `slack_get_usergroup_members` — omit either and those
   tools fail with `missing_scope`.)
3. Install the app to your workspace; copy the **Bot User OAuth Token** (`xoxb-…`) and **Team ID**.
4. Set them on the agent's env (locally) or via **Cloud → Env vars**:

```bash
SLACK_BOT_TOKEN=xoxb-...
SLACK_TEAM_ID=T01234567
```

The skill declares `envKeys: ['SLACK_BOT_TOKEN', 'SLACK_TEAM_ID']` and the official `@modelcontextprotocol/server-slack` consumes them.

## Use in an agent

```js
import { WorkflowAgent, WorkflowGraph } from '@zibby/core';
import { SKILLS } from '@zibby/skills';

export class DeployAnnouncer extends WorkflowAgent {
  buildGraph() {
    const graph = new WorkflowGraph();
    graph.addNode('announce', {
      agent: 'claude',
      skills: [SKILLS.SLACK],
      prompt: (state) => `Post to #deploys: "v${state.version} deployed to ${state.env}".
      If state.threadTs is set, use slack_reply_to_thread instead of slack_post_message.`,
    });
    return graph;
  }
}
```

## Output example

`slack_post_message`:

```json
{ "ok": true, "ts": "1715839203.000400", "channel": "C0123ABC" }
```

`slack_list_channels`:

```json
{
  "channels": [
    { "id": "C0123ABC", "name": "deploys", "topic": "Release announcements" },
    { "id": "C0456DEF", "name": "incidents", "topic": "P0/P1 coordination" }
  ]
}
```

## Implementation notes

`resolve()` spawns the official `@modelcontextprotocol/server-slack` via `npx` and passes through `SLACK_BOT_TOKEN` + `SLACK_TEAM_ID`. The in-process `handleToolCall` (used by the `assistant` strategy) talks directly to `https://slack.com/api/<method>` with the same bot token resolved via the backend's integration token service.
