Skip to content

Slack

The Slack provider integrates your digital worker with Slack workspaces. It supports:

  • Direct messages (DMs)
  • Channel messages
  • App mentions
  • Interactive components (buttons, menus)
  • Block Kit rich messaging
  • Slash commands
  • Thread replies
  • A Slack workspace
  • Admin access to create a Slack app
  1. Create a Slack configuration token pair

    Go to api.slack.com/apps and create an app configuration token pair. Copy both values:

    • Configuration access token (xoxe.xoxp-...)
    • Configuration refresh token (xoxe-1-...)
  2. Configure Provider

    answers.json
    {
    "setup_answers": {
    "messaging-slack": {
    "slack_configuration_access_token": "xoxe.xoxp-xxx",
    "slack_configuration_refresh_token": "xoxe-1-xxx"
    }
    }
    }
  3. Run setup

    Terminal window
    gtc setup --answers answers.json ./my-bundle
  4. Click Add to Slack

    Setup registers or updates the Slack app and exposes an Add to Slack action. Open the generated Slack authorization URL, choose the workspace, review the requested scopes, and approve the install.

    When the OAuth redirect returns to setup, Greentic persists the Slack app id, client id, client secret, and runtime OAuth answers for the tenant. If the callback was not handled automatically, run gtc setup --answers answers.json ./my-bundle again after approving the install.

  5. Add the app in Slack

    Open Slack and check that the app is installed in the workspace. For channel conversations, add the app to the channel where the worker should respond. You can do this from the channel’s integration settings or by mentioning/inviting the app in the channel.

  6. Start or restart the runtime

    Terminal window
    gtc start ./my-bundle

    Startup uses the stored slack_app_id and configuration token pair to update the Slack app manifest with the current webhook URL.

  7. Test the channel

    Send a direct message to the app or mention the app in the Slack channel you added it to. Channel events only arrive for channels where the app is a member and the installed scopes allow the event.

OptionRequiredDescription
slack_configuration_access_tokenYesShort-lived Slack configuration token used for app manifest updates
slack_configuration_refresh_tokenYesRefresh token used to rotate the configuration access token
slack_app_idGeneratedSlack app id created or returned by setup
slack_client_idGeneratedSlack OAuth client id returned by app registration
client_secretGenerated secretSlack OAuth client secret returned by app registration

Slack uses the Greentic runtime’s public HTTPS endpoint for all incoming callbacks. Expose the runtime through HTTPS on port 443; local development can use a tunnel that forwards the public URL to the local runtime port.

DirectionProtocol and portPurpose
IncomingHTTPS 443 from Slack to GreenticEvents API callbacks, interactive component payloads, slash command payloads, and OAuth redirects
OutgoingHTTPS 443 from Greentic to slack.com and api.slack.comOAuth exchange, Web API sends, app registration, manifest updates, and configuration token rotation

No Slack-specific TCP port needs to be opened on the Greentic host. The important inbound requirement is that Slack can reach the configured public base URL and the /v1/messaging/ingress/messaging-slack/{tenant}/{team} path over HTTPS.

- id: reply
type: reply
config:
message: "Hello! How can I help you?"

Slack uses mrkdwn format:

- id: formatted
type: reply
config:
message: |
*Bold* _Italic_ `code`
>Blockquote
• Bullet point

Use Slack’s Block Kit for rich layouts:

- id: rich_message
type: reply
config:
blocks:
- type: section
text:
type: mrkdwn
text: "*Welcome!*\nHow can I assist you today?"
- type: divider
- type: actions
elements:
- type: button
text:
type: plain_text
text: "Get Help"
action_id: "help_clicked"
value: "help"
- type: button
text:
type: plain_text
text: "View Status"
action_id: "status_clicked"
value: "status"
- id: ask_action
type: reply
config:
message: "What would you like to do?"
blocks:
- type: actions
elements:
- type: button
text:
type: plain_text
text: "Create Ticket"
style: primary
action_id: "create_ticket"
- type: button
text:
type: plain_text
text: "Cancel"
style: danger
action_id: "cancel"
- id: select_option
type: reply
config:
blocks:
- type: section
text:
type: mrkdwn
text: "Select a category:"
accessory:
type: static_select
action_id: "category_select"
options:
- text:
type: plain_text
text: "Technical Support"
value: "technical"
- text:
type: plain_text
text: "Billing"
value: "billing"
- text:
type: plain_text
text: "General"
value: "general"

Reply in a thread:

- id: thread_reply
type: reply
config:
message: "This replies in the thread"
thread_ts: "{{original_message.thread_ts}}"

Slack’s file APIs change over time. Use this only when the installed messaging-slack pack exposes file support for your version; otherwise send a link or use Slack’s current external upload flow.

- id: upload_file
type: reply
config:
files:
- url: "https://example.com/report.pdf"
filename: "report.pdf"
title: "Monthly Report"

Messages only visible to one user:

- id: ephemeral
type: reply
config:
message: "Only you can see this"
ephemeral: true
user: "{{user_id}}"
flows/on_interaction.ygtc
name: handle_interaction
version: "1.0"
nodes:
- id: route_action
type: branch
config:
conditions:
- expression: "action_id == 'help_clicked'"
to: show_help
- expression: "action_id == 'create_ticket'"
to: create_ticket
default: unknown_action
- id: show_help
type: reply
config:
message: "Here's how I can help..."
triggers:
- type: block_action
target: route_action
- id: handle_select
type: branch
config:
conditions:
- expression: "selected_value == 'technical'"
to: technical_flow
- expression: "selected_value == 'billing'"
to: billing_flow
  1. Go to Slash Commands in your app settings
  2. Create a command (e.g., /support)
  3. Set Request URL to your webhook

Handle in your flow:

flows/slash_command.ygtc
name: slash_command
version: "1.0"
nodes:
- id: handle_command
type: reply
config:
message: "Support bot at your service!"
response_type: in_channel # or "ephemeral"
triggers:
- type: slash_command
command: "/support"
target: handle_command
greentic.demo.yaml
tenants:
demo:
teams:
support:
channels:
slack:
provider: messaging-slack
config:
channel_id: "C1234567890"
tenants:
demo:
teams:
support:
channels:
slack-general:
provider: messaging-slack
config:
channel_id: "C1234567890"
slack-vip:
provider: messaging-slack
config:
channel_id: "C0987654321"
  1. Verify Event Subscriptions:

    • Check Request URL is correct
    • Ensure events are enabled
    • Verify bot is subscribed to correct events
  2. Check Bot Permissions:

    • Reinstall app after adding scopes
    • Verify bot is in the channel
  3. Test Webhook:

    Terminal window
    curl https://your-domain.com/v1/messaging/ingress/messaging-slack/demo/default

Your bot token is invalid or expired. Get a fresh token from OAuth & Permissions.

  • Verify channel ID is correct
  • Ensure bot is added to the channel
  • Check channel is not archived

Slack rate limits vary by method. Handle gracefully:

- id: reply
type: reply
config:
message: "Response"
retry_on_rate_limit: true
max_retries: 3

Greentic automatically validates:

  • Request timestamp
  • Signature using signing secret
  • Token verification