← Back to Plugins
Channels

Plugin Slack Workspace

stevekinney By stevekinney 👁 27 views ▲ 0 votes

OpenClaw plugin from stevekinney/openclaw-plugin-slack-workspace

GitHub

Install

npm install
npm

README

# Slack Workspace

An OpenClaw plugin that gives the agent Slack workspace tools the bundled Slack channel plugin doesn't have: scheduling, search, structured messages, canvases, bookmarks, public-channel management, Slack Lists, file uploads, and more. It registers its tools and hooks with `definePluginEntry`. The channel plugin still handles conversation itself (replies, reactions, pins, and file handling inside a chat turn), so nothing here duplicates it.

## Tools

Every tool uses the bot token except `slack_search` and `slack_search_context`, which need the user token; `slack_identity`, which checks whichever token you ask about; and `slack_workflow_trigger_run`, which uses no Slack token at all. The scopes listed are the ones Slack's docs require for the methods each tool calls. `openclaw slack-workspace doctor` checks them against what your tokens actually hold (see [Scope doctor](#scope-doctor)).

Tools marked † take an optional `channelId`. Inside a Slack conversation, leaving it out targets the current channel. Outside one (cron jobs, automations, other chat platforms), it's required.

### Identity and search

| Tool | What it does | Token | Scopes |
|---|---|---|---|
| `slack_identity` | Report who a token authenticates as and which scopes it holds | bot or user (`tokenKind`) | none |
| `slack_search` | Keyword search over messages or files as the authorizing user, including their private channels and DMs. Points the agent to `slack_search_context` for questions | **user** | `search:read` |
| `slack_search_context` | Real-time Search (`assistant.search.context`): messages ranked by meaning, each with its permalink and surrounding messages; optionally files, channels and users. Falls back to `search.messages` (`mode: "legacy"`) when unavailable | **user** | `search:read.public` (plus `search:read.private`, `.im`, `.mpim`, `.files`, `.users` for wider coverage) |

### Messages and Block Kit

| Tool | What it does | Token | Scopes |
|---|---|---|---|
| `slack_post_table` † | Post rows and columns as a native table | bot | `chat:write` |
| `slack_post_plan` † | Post a checklist or progress card | bot | `chat:write` |
| `slack_post_chart` † | Post a native chart | bot | `chat:write` |
| `slack_post_rich_text` † | Post prose with real lists, quotes, and code blocks | bot | `chat:write` |
| `slack_blocks_send` † | Post raw Block Kit blocks | bot | `chat:write` |
| `slack_blocks_update` † | Replace an existing message's blocks by `ts` | bot | `chat:write` |
| `slack_interaction_prepare` † | Prepare a bounded modal or external-select interaction | bot | none |
| `slack_message_get` † | Find messages by the metadata stamped on them and return their `ts` | bot | `channels:history`, `metadata.message:read` |
| `slack_message_delete` † | Delete a message this bot posted (approval-gated) | bot | `channels:history`, `chat:write` |
| `slack_post_ephemeral` † | Send one user a message only they can see | bot | `chat:write` |
| `slack_work_object_post` † | Post a native Work Object card for an external issue, task, or doc | bot | `chat:write` |

`slack_post_table`, `slack_post_plan`, `slack_post_chart`, and `slack_post_rich_text` also take `updateTs` to rewrite a message they posted earlier.

After posting or updating, those four tools and `slack_blocks_send`/`slack_blocks_update` call `chat.getPermalink` and return the message's `permalink`, so the agent can link to what it posted. If the lookup fails, the post still succeeds: the result just omits `permalink` and a warning is logged.

`slack_message_delete` wraps `chat.delete` so the agent can clean up its own scratch or obsolete cards. Before deleting, it reads the message back with `conversations.history`, or `conversations.replies` when you pass the thread parent's `threadTs`, and compares its author with the bot's `auth.test` identity. If another user or app posted the message, or the message can't be found, the tool refuses the call and never reaches `chat.delete`. Deleting is irreversible, so every call also waits for a human's approval.

`slack_work_object_post` posts a [Work Object](https://docs.slack.dev/messaging/work-objects-overview) card for an item that lives in another system, like an issue, incident, or doc. It calls `chat.postMessage` with entity metadata and no `app_unfurl_url`, because it's a proactive post rather than a reply to a link unfurl. The card shows `title`, `displayId`, `displayType`, `status`, and a link to `url`. `entityType` picks Slack's entity schema: `task` (the default), `incident`, `file`, or `content_item`. Only `task` and `incident` have a status field, so the tool refuses a `status` on the others before calling Slack. Clicking the card opens only a static placeholder. Filling in the details pane means handling Slack's `entity_details_requested` event, and only the bundled channel plugin receives events. Slack renders Work Objects only after someone turns on **Work Object Previews** in the app's settings. If Slack rejects the entity metadata, the tool posts an equivalent plain Block Kit card, with a linked title and a context line, and returns `mode: "fallback"` with Slack's error as `reason`. Errors that a plain post would hit too, like `channel_not_found` or `missing_scope`, are thrown as usual. The result is `{ mode, channelId, ts, permalink?, reason? }`.

### Scheduling and reminders

| Tool | What it does | Token | Scopes |
|---|---|---|---|
| `slack_schedule_message` | Schedule a message up to 120 days out | bot | `chat:write` |
| `slack_schedule_reschedule` | Replace a pending scheduled message's text or time | bot | `chat:write` |
| `slack_remind` | Remind a person (by DM) or a channel at a set time | bot | `im:write`, `chat:write` |
| `slack_scheduled_list` | List pending scheduled messages | bot | none |
| `slack_scheduled_cancel` | Cancel a pending scheduled message | bot | `chat:write` |

### Canvases

| Tool | What it does | Token | Scopes |
|---|---|---|---|
| `slack_canvas_create` | Create a canvas from Markdown or a built-in template | bot | `canvases:write` |
| `slack_canvas_edit` | Append, prepend, insert, replace, or delete canvas content, or rename the canvas | bot | `canvases:write` |
| `slack_canvas_sections` | Find section IDs to edit relative to | bot | `canvases:read` |
| `slack_canvas_list` | Find canvases the bot can see | bot | `files:read` |
| `slack_canvas_access_set` | Share a canvas with channels or users | bot | `canvases:write` |
| `slack_canvas_access_delete` | Revoke canvas access | bot | `canvases:write` |
| `slack_canvas_delete` | Delete a canvas | bot | `canvases:write` |
| `slack_canvas_channel_get_or_create` | Get or create a channel's tab canvas | bot | `channels:read`, `canvases:write` |
| `slack_canvas_status_update` | Rewrite one section under a heading, for scheduled status runs | bot | `channels:read`, `canvases:read`, `canvases:write` |
| `slack_canvas_from_thread` | Turn a thread into a canvas | bot | `channels:history`, `canvases:write` |

### Bookmarks

| Tool | What it does | Token | Scopes |
|---|---|---|---|
| `slack_bookmark_list` | List a channel's bookmarks | bot | `bookmarks:read` |
| `slack_bookmark_add` | Add a link bookmark | bot | `bookmarks:write` |
| `slack_bookmark_edit` | Change a bookmark's title, link, or emoji | bot | `bookmarks:write` |
| `slack_bookmark_remove` | Remove a bookmark | bot | `bookmarks:write` |

### Public channels

| Tool | What it does | Token | Scopes |
|---|---|---|---|
| `slack_channel_list` | Find channels (public, plus private ones the bot is in) by name, topic, or purpose, each with `isMember` (read-only) | bot | `channels:read` (plus `groups:read` for private channels) |
| `slack_channel_members` | List a channel's member user IDs (read-only) | bot | `channels:read` (`groups:read` for private channels) |
| `slack_channel_create` | Create a public channel, or a private one with `isPrivate: true` | bot | `channels:manage` (`groups:write` for private) |
| `slack_channel_archive` | Archive a channel | bot | `channels:manage` (`groups:write` for private) |
| `slack_channel_unarchive` | Unarchive a channel (the undo for archive) | bot | `channels:manage` (`groups:write` for private) |
| `slack_channel_rename` | Rename a channel | bot | `channels:manage` (`groups:write` for private) |
| `slack_channel_set_topic` | Set a channel's topic | bot | `channels:write.topic` (`groups:write.topic` for private) |
| `slack_channel_set_purpose` | Set a channel's purpose | bot | `channels:manage` (`groups:write` for private) |
| `slack_channel_invite` | Invite users to a channel | bot | `channels:write.invites` (`groups:write.invites` for private) |
| `slack_channel_join` | Join a public channel as the bot | bot | `channels:read`, `channels:join` |
| `slack_channel_leave` | Leave a public channel | bot | `channels:read`, `channels:manage` |
| `slack_channel_kickoff` | Create a project channel (public or private) with topic, purpose, invites, canvas, and bookmark in one call | bot | `channels:manage`, `channels:write.topic`, `channels:write.invites`, `canvases:write`, `bookmarks:write` (plus the `groups:write*` twins for private) |

### Slack Lists

| Tool | What it does | Token | Scopes |
|---|---|---|---|
| `slack_list_create` | Create a List with typed columns | bot | `lists:write` |
| `slack_list_update` | Rename a List, or change its description or todo mode | bot | `lists:write` |
| `slack_list_schema` | Read a List's column and option IDs | bot | `lists:read` |
| `slack_list_item_create` | Add a row, by column name | bot | `lists:read`, `lists:write` |
| `slack_list_item_update` | Change cells, by column name | bot | `lists:read`, `lists:write` |
| `slack_list_item_delete` | Delete a row | bot | `lists:write` |
| `slack_list_items_delete_multiple` | Delete several rows | bot | `lists:write` |
| `slack_list_items_list` | Read a List's rows | bot | `lists:read` |
| `slack_list_item_info` | Read one row and its subtasks | bot | `lists:read` |
| `slac

... (truncated)
channels

Comments

Sign in to leave a comment

Loading comments...