https://github.com/user-attachments/assets/a77aa941-da48-4c30-8e14-587516c19ac4 Added a new feature that allows the bot to introduce itself when added to a Slack channel. This includes a welcome message and a detailed thread reply outlining its capabilities. The implementation includes new utility functions for handling the welcome event, managing welcome state, and posting messages. Updated relevant logic functions to support this feature, ensuring the bot can provide a seamless introduction to users in new channels. - Introduced `slack-channel-welcome` logic function. - Added constants for welcome message text. - Implemented event parsing and handling for `member_joined_channel`. - Updated `slack-events-resolver` to route welcome events appropriately.
6.4 KiB
Setup
Two parts: a Slack app you create, and the Twenty side where you paste its credentials and connect. The conversational assistant needs a third part on top.
1. Slack app
-
Create a Slack app at api.slack.com/apps. Use a dedicated app — do not reuse one across Twenty apps.
-
OAuth & Permissions → Bot Token Scopes. Twenty uses Slack's bot OAuth (
oauth/v2/authorizewithscope=…), so scopes must be added here and not only under User Token Scopes, otherwise Slack refuses the install with "doesn't have a bot user to install".The scopes requested at connect time must all appear under Bot Token Scopes (Slack validates the set):
Scope Used for channels:readconversations.listand the channel picker (public channels)chat:writepost, update, delete, ephemeral chat:write.publicpost to public channels without the bot joining groups:readlist private channels the bot is in reactions:writeadd reactions app_mentions:readassistant: mentions of the bot channels:historyassistant: thread follow-ups in public channels groups:historyassistant: thread follow-ups in private channels im:historyassistant: direct messages Adding or removing scopes later means existing installs must re-authorize: disconnect and Add connection again.
-
Redirect URL. Set it to
<YOUR_TWENTY_SERVER_URL>/auth/apps/callback— the origin your Twenty server uses for API routes, not the SPA. Local monorepo dev is usuallyhttp://localhost:3000(confirm the porttwenty-server/SERVER_URLactually uses).PKCE and
localhost: if you enable PKCE on the Slack app, Slack treatshttp://localhost…as a desktop redirect, and desktop redirects cannot request bot scopes — OAuth will fail. For local dev either leave Slack's PKCE opt-in disabled, or use anhttps://redirect (ngrok, Cloudflare Tunnel), register it in the Slack app, and pointSERVER_URLat the same base URL. See Slack's Using PKCE docs. This is separate from Twenty sending a PKCE challenge on the authorize request. -
Copy the Client ID and Client Secret.
2. Twenty
- Install this app (
slack) on your Twenty server. - Settings → Applications → Twenty Slack → Application registration (admin only), set
SLACK_CLIENT_IDandSLACK_CLIENT_SECRET. - Connections → Add connection, choose Just for me or Workspace shared, complete the Slack sign-in.
Workflow steps then use that connection's access token: a workspace connection is preferred when present, otherwise the first connection returned for the Slack provider.
For posting, either invite the bot to the channel or rely on chat:write.public for public channels. Private channels always require membership.
3. Conversational assistant
The assistant reuses the same Slack connection — no second bot identity.
-
Signing secret. In Application registration, set
SLACK_WEBHOOK_SECRETfrom your Slack app (Basic Information → App Credentials). The server verifies every Slack Events request with it. -
Event subscriptions. On the Slack app, enable Event Subscriptions and set the Request URL to:
<YOUR_TWENTY_SERVER_URL>/webhooks/server/9ad6fa20-dff5-4d3f-ad5f-084f3c8b0b09That ID is the
slack-events-resolverlogic function. Slack signs the handshake, soSLACK_WEBHOOK_SECRETmust be set first or Slack reports "didn't respond with the value of the challenge parameter."Under Subscribe to bot events, add:
app_mention— mentions of the bot in a channelmessage.im— direct messages to the botmessage.channels— replies in public-channel threads, for un-mentioned follow-upsmessage.groups— same, for private channels the bot is inmember_joined_channel— optional; lets the bot introduce itself when it is added to a channel
Invite the bot to any channel where it should follow threads. Slack may ask you to reinstall after changing subscriptions.
-
Reconnect so the token picks up the assistant scopes.
-
Role. The
slack-assistantagent binds to the app's Slack Assistant role automatically on install and upgrade. Anyone who can message the bot acts with that role — Slack users are not mapped to individual Twenty members yet, so keep the role scoped to what you're comfortable exposing.
Behaviour notes
- Thread memory. After a successful reply the bot stays active in that thread, so follow-ups need no mention. Channel threads stay active for 24 hours after the last reply (each reply renews it); DM threads never expire.
- Channel welcome. With
member_joined_channelsubscribed, the bot posts a short introduction the first time it is added to a channel, with the details (what to ask it, what it reads, and the shared-role caveat from step 4 above) in a thread reply so the channel itself stays quiet. It fires once per channel for 30 days, and only for the bot's own join — humans joining afterwards trigger nothing. Skip the subscription if you would rather it arrived silently. - One Slack workspace per Twenty workspace. Connecting Slack claims that Slack team for the connecting Twenty workspace. On the same server, a second Twenty workspace connecting the same Slack team is rejected. The claim is not released on disconnect yet, so moving a Slack workspace needs a server admin.
Workflow field names (for step authors)
Fields use camelCase in the step UI:
slackChannelId— channel or DM, name or IDmessageText,newMessageText— body to post / the replacement on updatemessageTimestamp— Slack's per-message id, same value as the tool outputslackTswhen chaining stepsparentMessageTimestamp— thread replies onlymessageFormat—markdownsends the body as Slackmarkdown_text(**bold**),plainsendstextwith markup disabled, omitted uses Slack's default fortextrecipientSlackUserId— ephemeral stepsemojiName— Slack shortcode, for examplewhite_check_mark
HTTP routes
The Send Slack message command menu item is backed by two app routes, both requiring an authenticated Twenty user and using the same Slack connection as the workflow steps:
GET /slack/channels— lists channels visible to the botPOST /slack/messages— posts a message