Skip to content

Slack Integration — Self-Hosted

Self-hosted RunWhen deployments connect Slack through the in-cluster slackbot service. You create a dedicated Slack app in your Slack workspace, expose it at https://slack.<domain>, and supply the app’s OAuth credentials to the runwhen-platform Helm chart.

This guide covers the platform-operator path. End-user install and day-to-day use (DMs, @mentions, /runwhen settings) are the same as on RunWhen SaaS — see the Setup Guide after the platform side is configured.

Slack is optional. The chart always deploys slackbot, but it stays idle until you create an app, wire credentials, and complete OAuth.


SaaS vs self-hosted

ModelWho creates the Slack appWhere credentials live
RunWhen SaaSRunWhenRunWhen-operated secrets; users click Connect in the UI
Self-hostedYou (Slack workspace admin)Your Helm values or a Kubernetes Secret you manage

See Self-Hosted Deployment Requirements for cluster, DNS, TLS, and registry prerequisites before configuring Slack.


How the chart exposes slackbot

ItemValue
Public URL (Slack → platform)https://slack.<domain> (override: ingress.services.slack.host)
Kubernetes Service<release>-slackbot:8000
OAuth redirecthttps://slack.<domain>/oauth_redirect
Event / interactivity URLhttps://slack.<domain>/runwhen
UI install entryhttps://app.<domain>Connect Slack, or browse to https://slack.<domain>/install

Replace <domain> with your global.domain Helm value everywhere below. If you set a custom ingress.services.slack.host, use that host instead — the Slack app URLs must match exactly.

Prerequisites

  • Public DNS and TLS for slack.<domain>, reachable by Slack’s servers over HTTPS. Slack validates the Event Subscriptions request URL from the public internet — this does not work on a fully air-gapped cluster.
  • Public DNS and TLS for app.<domain> (the OAuth flow redirects the browser back here to link the Slack workspace to a RunWhen workspace).
  • Slack workspace admin access to create and install the app.

Step 1 — Create the Slack app from a manifest

The fastest path is api.slack.com/appsCreate New AppFrom an app manifestYAML.

Paste the manifest below, replacing <domain> with your platform domain (for example acme.example.com):

display_information:
name: RunWhen
description: |
Connect Slack to RunWhen. AI Assistants answer in DMs and @mentions.
/runwhen: help or settings only.
background_color: "#737373"
features:
app_home:
home_tab_enabled: true
messages_tab_enabled: true
messages_tab_read_only_enabled: false
bot_user:
display_name: RunWhen
always_online: false
slash_commands:
- command: /runwhen
url: https://slack.<domain>/runwhen
description: "Help and settings: workspace defaults, AI Assistants, channel mapping. Chat via DM or @mention."
usage_hint: "[help | settings] — chat by DM or @mention, not via this command"
should_escape: false
oauth_config:
redirect_urls:
- https://slack.<domain>/oauth_redirect
scopes:
bot:
- app_mentions:read
- assistant:write
- channels:read
- channels:history
- channels:write.invites
- chat:write
- chat:write.customize
- commands
- groups:read
- groups:history
- groups:write.invites
- im:read
- im:history
- im:write.invites
- mpim:read
- mpim:history
- mpim:write.invites
- team:read
- users:read
- users:read.email
pkce_enabled: false
settings:
event_subscriptions:
request_url: https://slack.<domain>/runwhen
bot_events:
- app_home_opened
- app_mention
- assistant_thread_started
- assistant_thread_context_changed
- channel_rename
- member_joined_channel
- message.channels
- message.groups
- message.im
- message.mpim
interactivity:
is_enabled: true
request_url: https://slack.<domain>/runwhen
org_deploy_enabled: false
socket_mode_enabled: false
token_rotation_enabled: false
is_mcp_enabled: false

The platform does not use Socket Mode or an app-level token. All traffic runs over public HTTPS request URLs, so slack.<domain> must be internet-reachable before Slack accepts the Event Subscriptions URL.

Environment-specific slash commands

When several self-hosted environments share one Slack workspace, give each environment a distinct slash command (for example /runwhen-staging, /runwhen-prod). Change the command field in the manifest and set the matching Helm value:

slack:
slashCommand: runwhen-staging # without the leading /

The request URL path stays /runwhen on the platform — only the command name in Slack differs.


Step 2 — Manual reference (if not using a manifest)

If you configure the app by hand, set these on the Slack app settings pages:

OAuth & Permissions

SettingValue
Redirect URLhttps://slack.<domain>/oauth_redirect
Bot Token Scopesapp_mentions:read, assistant:write, channels:read, channels:history, channels:write.invites, chat:write, chat:write.customize, commands, groups:read, groups:history, groups:write.invites, im:read, im:history, im:write.invites, mpim:read, mpim:history, mpim:write.invites, team:read, users:read, users:read.email
User Token Scopesnone

Event Subscriptions

SettingValue
Request URLhttps://slack.<domain>/runwhen
Bot eventsapp_home_opened, app_mention, assistant_thread_started, assistant_thread_context_changed, channel_rename, member_joined_channel, message.channels, message.groups, message.im, message.mpim

Slash Commands

CommandRequest URL
/runwhen (or your custom name)https://slack.<domain>/runwhen

Interactivity & Shortcuts

Enabled, Request URL: https://slack.<domain>/runwhen

App Home

Enable the Home tab and Messages tab. Allow users to send messages from the Messages tab (required for the DM experience).


Step 3 — Feed credentials into Helm

From the Slack app’s Basic Information and OAuth & Permissions pages, copy three values into your Helm overlay:

Slack app valueHelm valueRendered env var
Signing Secretsecrets.values.slackSigningSecretSLACK_SIGNING_SECRET
Client IDsecrets.values.slackClientIdSLACK_CLIENT_ID
Client Secretsecrets.values.slackClientSecretSLACK_CLIENT_SECRET
slack:
existingSecret: "" # or rw-slack-credentials for BYO Secret (recommended)
slashCommand: runwhen # must match the command in your Slack app manifest
secrets:
method: "k8s-secret"
values:
slackSigningSecret: "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
slackClientId: "1234567890.1234567890"
slackClientSecret: "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
# Encrypts OAuth install payloads. Auto-generated when empty on chart 0.2.20+.
fernetKey: ""

Do not commit plaintext secrets. Inject at deploy time (for example --set secrets.values.slackClientSecret="$SLACK_CLIENT_SECRET") or use the BYO Secret path below.

Keep Slack credentials in an operator-managed Secret:

Terminal window
kubectl create secret generic rw-slack-credentials -n <namespace> \
--from-literal=SLACK_SIGNING_SECRET='...' \
--from-literal=SLACK_CLIENT_ID='...' \
--from-literal=SLACK_CLIENT_SECRET='...'
slack:
existingSecret: rw-slack-credentials

When slack.existingSecret is set, the chart does not write those keys to platform-secrets; backend pods load your Secret instead.

You do not put a bot token in Helm. The per-workspace bot token is minted during OAuth install (Step 4) and stored in Vault automatically.

URL wiring (automatic)

SLACKBOT_URL and SLACKBOT_INTERNAL_URL are derived by the chart from your ingress host — no manual env vars unless you override ingress.services.slack.host.


Step 4 — Deploy and connect a workspace

  1. Deploy or upgrade the chart with the credentials from Step 3.
  2. Confirm slackbot is healthy:
    Terminal window
    kubectl rollout status deploy/<release>-slackbot -n <namespace>
    kubectl logs deploy/<release>-slackbot -n <namespace>
  3. From https://app.<domain>, use Connect Slack (or open https://slack.<domain>/install) and click Add to Slack.
  4. Approve the OAuth scopes. Slack redirects to https://slack.<domain>/oauth_redirect; the bot token is stored in Vault; your browser returns to https://app.<domain> to finish linking the Slack workspace to a RunWhen workspace.
  5. Complete user-facing setup: Slack Setup Guide — Parts 2 and 3.

Verify

  • In Slack, run /runwhen settings (or your custom command) and confirm workspace and AI Assistant selection.
  • DM the bot or @mention it in a channel — you should get a response.
  • The App Home tab should render when opened.

Known limitations

LimitationDetails
Token refreshScheduled Slack token refresh is not active yet. Keep token_rotation_enabled: false in the manifest until a future chart release enables it.
No disable toggleThe slackbot workload and ingress are always rendered. To fully disable, scale the deployment to zero and remove the slack ingress host.
Air-gapOAuth and event delivery require public reachability to and from slack.com. Slack is effectively unavailable in air-gapped installs.

For product-level Slack behavior (thread ownership, rich-content handoff, context window), see Slack Integration Overview — Current Limitations.


Troubleshooting

SymptomResolution
Slack rejects Event Subscriptions URLConfirm https://slack.<domain>/runwhen is publicly reachable with a valid TLS certificate
OAuth redirect mismatchRedirect URL in the Slack app must exactly match https://slack.<domain>/oauth_redirect
/runwhen unknown in SlackCommand name in the Slack app must match slack.slashCommand in Helm
Install succeeds but bot is silentComplete Setup Guide Part 3 — select workspace and AI Assistant
ValueError: Fernet key must be 32 url-safe base64-encoded bytesSet secrets.values.fernetKey explicitly or upgrade to chart 0.2.20+ (auto-generates a stable key)