306a1454aa
## Before After connecting to oAuth linear app connection: <img width="1512" height="851" alt="image" src="https://github.com/user-attachments/assets/39b94aaf-648f-46a6-8f4d-deb1cb7e22c5" /> ## After Redirects to Linear <!-- This is an auto-generated description by cubic. --> <a href="https://cubic.dev/pr/twentyhq/twenty/pull/21678?utm_source=github" target="_blank" rel="noopener noreferrer" data-no-image-dialog="true"><picture><source media="(prefers-color-scheme: dark)" srcset="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"><source media="(prefers-color-scheme: light)" srcset="https://www.cubic.dev/buttons/review-in-cubic-light.svg"><img alt="Review in cubic" src="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"></picture></a> <!-- End of auto-generated description by cubic. -->
127 lines
6.4 KiB
Markdown
127 lines
6.4 KiB
Markdown
# twenty-slack
|
||
|
||
Slack tools for **Twenty workflows** and **agents** (the same logic functions
|
||
are available as workflow steps and as tools where your deployment exposes
|
||
them). Uses the official
|
||
[`@slack/web-api`](https://github.com/slackapi/node-slack-sdk) `WebClient`
|
||
(Slack retries and error types).
|
||
|
||
## What you can do
|
||
|
||
Once the app is installed and Slack is **connected** (see **Twenty setup**
|
||
below):
|
||
|
||
- **Workflow steps** — post, update, or delete bot messages; send ephemerals;
|
||
add reactions; list channels. Pick a **workspace shared** or **just for me**
|
||
connection; steps run with that token.
|
||
- **Agents / AI** — when your Twenty instance surfaces app tools to the model,
|
||
these functions can be invoked the same way as other app logic functions.
|
||
- **Quick-send** — command menu **Send Slack message** opens a side panel to
|
||
pick a channel and post (same Slack connection as workflows).
|
||
|
||
## Tools
|
||
|
||
| Name | Slack API |
|
||
|------|-----------|
|
||
| `slack-post-message` | `chat.postMessage` |
|
||
| `slack-post-ephemeral-message` | `chat.postEphemeral` |
|
||
| `slack-update-message` | `chat.update` |
|
||
| `slack-delete-message` | `chat.delete` |
|
||
| `slack-add-reaction` | `reactions.add` |
|
||
| `slack-list-channels` | `conversations.list` |
|
||
|
||
### Workflow field names (for authors)
|
||
|
||
Fields use camelCase names in the step UI, for example **`slackChannelId`** (Slack channel or DM: **name** or **ID**), **`messageText`**, and **`messageTimestamp`** (Slack’s per-message id — same value as tool output **`slackTs`** when chaining steps). Optional **`parentMessageTimestamp`** is only for **thread replies**. Post / update / ephemeral steps support optional **`messageFormat`**: **`markdown`** sends the body as Slack **`markdown_text`** (e.g. **`**bold**`**), **`plain`** sends **`text`** with markup disabled, omit uses Slack’s default for **`text`**. Ephemeral steps use **`recipientSlackUserId`**; reactions use **`emojiName`** (Slack shortcode, for example `white_check_mark`). Updating a message uses **`newMessageText`**.
|
||
|
||
### Quick-send command menu item
|
||
|
||
This app also ships a global command menu item — **Send Slack message** — that opens a side-panel form to pick a channel (from `conversations.list`) and post a message via `chat.postMessage`. The form is backed by two HTTP routes exposed by the app:
|
||
|
||
- `GET /slack/channels` — lists channels visible to the bot (mirrors `slack-list-channels`).
|
||
- `POST /slack/messages` — posts a message (mirrors `slack-post-message`).
|
||
|
||
Both routes require an authenticated Twenty user and use the same shared Slack connection as the workflow tools.
|
||
|
||
### Prerequisites (Slack workspace)
|
||
|
||
- You can **install** the Slack app on a workspace you administer (or get an
|
||
admin to approve it).
|
||
- For **posting**: invite the bot to the channel, **or** rely on
|
||
**`chat:write.public`** (included in OAuth) to post to **public** channels
|
||
without joining — private channels still require membership.
|
||
- **`slack-list-channels`** and the quick-send channel picker need
|
||
**`channels:read`** / **`groups:read`** on the token (requested at connect
|
||
time; see below).
|
||
|
||
## Slack app setup
|
||
|
||
1. Create a Slack app at [api.slack.com/apps](https://api.slack.com/apps)
|
||
(dedicated to this Twenty app — do not reuse for other Twenty apps).
|
||
2. **OAuth & Permissions** → **Bot Token Scopes**. Twenty uses Slack’s **bot**
|
||
OAuth (`oauth/v2/authorize` with `scope=…`). You must add scopes here — not
|
||
only under **User Token Scopes** — or Slack will refuse install with *“doesn’t
|
||
have a bot user to install”* until at least one bot scope exists.
|
||
|
||
The scopes **requested at connect time** are defined in
|
||
`src/connection-providers/slack-connection.ts` and must also appear under
|
||
**Bot Token Scopes** on the Slack app (Slack validates the set). Current
|
||
list:
|
||
|
||
- `channels:read` — `conversations.list` / channel picker (public)
|
||
- `chat:write` — post, update, delete, ephemeral
|
||
- `chat:write.public` — post to public channels without the bot joining
|
||
- `groups:read` — list private channels the bot is in
|
||
- `reactions:write` — add reactions
|
||
|
||
If you **add or remove** scopes in that file or in the Slack app, existing
|
||
installs must **re-authorize** (disconnect and **Add connection** again, or
|
||
reinstall the Slack app to the workspace) so the token picks up new scopes.
|
||
|
||
3. Set the **Redirect URL** on the Slack app to
|
||
`<YOUR_TWENTY_SERVER_URL>/auth/apps/callback` — the same origin your
|
||
Twenty **server** uses for API routes (the callback is not served by the SPA
|
||
alone). Local monorepo dev often uses `http://localhost:3000` (confirm the
|
||
port your `twenty-server` / `SERVER_URL` actually uses).
|
||
|
||
**Slack “PKCE” app setting vs `localhost`:** If you turn on **PKCE** for the
|
||
Slack app under **OAuth & Permissions**, Slack treats `http://localhost…`
|
||
redirect URLs as **desktop** redirects. **Desktop redirects cannot request
|
||
bot scopes**, so OAuth will fail for this integration while you use a
|
||
localhost callback. For local dev you can either **leave Slack’s PKCE
|
||
opt-in disabled** on that Slack app, or use an **`https://` redirect** (for
|
||
example a tunnel such as ngrok or Cloudflare Tunnel to your local server),
|
||
register that URL in the Slack app, and point Twenty’s `SERVER_URL` at the
|
||
same public base URL. See Slack’s [Using
|
||
PKCE](https://docs.slack.dev/authentication/using-pkce) docs (this is
|
||
separate from Twenty sending a PKCE challenge on the authorize request).
|
||
|
||
4. Copy the Slack **Client ID** and **Client Secret**.
|
||
|
||
## Twenty setup
|
||
|
||
1. Register / install this app on your Twenty server (`twenty-slack`).
|
||
2. In **Settings → Applications → Twenty Slack**, open the **Application registration**
|
||
tab (admin-only) and set:
|
||
- `SLACK_CLIENT_ID`
|
||
- `SLACK_CLIENT_SECRET`
|
||
3. In the same app, open the **Connections** tab and click **Add connection**.
|
||
Choose **Just for me** or **Workspace shared**, then complete the Slack sign-in.
|
||
|
||
Once connected, workflow steps use the connection access token: a
|
||
**workspace** connection is preferred when present; otherwise the first
|
||
connection returned for the Slack provider is used (see
|
||
`src/logic-functions/utils/get-slack-connection.ts`).
|
||
|
||
## Development
|
||
|
||
```bash
|
||
cd packages/twenty-apps/internal/twenty-slack
|
||
yarn install
|
||
yarn lint
|
||
yarn test
|
||
```
|
||
|
||
Use `yarn twenty dev` from this directory to develop against a local Twenty
|
||
instance (see other internal apps in this monorepo).
|