SemiLayerDocs

Install Slack & Discord

Two phases:

  1. Org-level install — an org admin runs an OAuth round-trip from the SemiLayer Console. This binds a workspace (Slack team or Discord guild) to one SemiLayer org. One workspace per org per provider on the free tier; unlimited on paid plans.
  2. Per-user identity link — every user who wants to run commands runs /semilayer login once. This binds their chat identity (U_… Slack id or Discord user id) to their SemiLayer auth0 sub.

After both, the user can run any slash command and it executes with their RBAC against their org.

ℹ️

The bot does nothing on install. No notifications fire, no commands run. Both halves above are required to send a single message. Until they're done you have OAuth scope but no surface area.

Org-level install

1
Open Settings → Integrations in the Console

Navigate to https://console.semilayer.com/<your-org>/settings/integrations. The page lists every connected workspace and the install buttons for the providers you don't have yet.

2
Click the provider's install button

You're redirected through the SemiLayer service which mints a signed install nonce, then to Slack or Discord's OAuth grant screen. Approve the requested scopes — they're scoped narrowly:

  • commands — receive /semilayer … from any channel the bot is in
  • chat:write — post replies + notification cards
  • chat:write.public — post in channels the bot wasn't invited to (only used for --public reads)
  • users:read.email — match a Slack user's verified email back to the SemiLayer member directory during /semilayer login
3
Land back at the Console

The OAuth callback handler upserts a row in chat_workspaces with the bot token (encrypted at rest), workspace id, installer's user id, and the granted scopes. The Console's Integrations page now shows the workspace as Connected.

If the install fails (revoked scope, OAuth state mismatch, expired nonce), the callback page renders a clear error with the underlying reason — no silent failures.

Disconnect

The same Settings → Integrations page has a "Disconnect" button. Disconnecting:

  • Marks chat_workspaces.revoked_at. The bot stops responding to slash commands from that workspace immediately (verified at the request layer).
  • Does not delete chat_subscriptions or chat_watches. They become inert. Reinstalling the bot resurrects them.
  • Logs chat.workspace_revoked to admin_audit_log with the actor's email.

To wipe everything (subscriptions, watches, identity links), follow Disconnect with a Console action: Settings → Integrations → "Wipe chat state for this workspace."

After the workspace is connected, individual users still need to bind their chat identity. There's no way around this — the platform refuses to act on a slash command if it can't tell which SemiLayer member is asking.

1
Run /semilayer login from any channel where the bot lives

The bot replies (ephemerally, only you see it) with a one-time link. The link is a signed JWT — clicking it doesn't reveal anything new, it just packages the binding intent.

2
Click the link

The link points to the platform service. If you're already signed in to Console (sl_access cookie), you're auto-binded — no further click needed. If you're not, you're bounced through OIDC sign-in first, then auto-binded.

3
Land on the success page

The page tells you which workspace you're now bound to and which SemiLayer org membership the binding picked up. From here, every slash command in that workspace runs as your identity.

You can re-run /semilayer login any time. Re-binding overwrites the existing row.

What gets stored

TableRow written
chat_workspacesOne per (org, provider). Bot token + scopes + installer.
chat_user_linksOne per (workspace, externalUserId). Maps to the SemiLayer auth0 sub.
chat_subscriptionsOne per channel × notification type. Created via /semilayer notify on.
chat_channel_scopesOne per channel that has pinned defaults. Created via /semilayer here.
chat_watchesOne per scheduled command. Created via /semilayer watch or remind.
admin_audit_logOne per state change (install, link, subscription, watch, here-pin).

Bot tokens are encrypted at rest with the platform's KMS-backed envelope encryption. They never appear in logs, telemetry, or audit events.

Troubleshooting

"That workspace is already connected to another SemiLayer org." — A Slack team or Discord guild can be bound to one org at a time. The owning org has to disconnect first. (Future paid plans will allow multi-org workspaces.)

"Your chat identity isn't linked yet — run /semilayer login." — You skipped the per-user step. Run it from any channel; the link is DM'd if the bot can DM you, otherwise posted ephemerally in-channel.

"You're linked but not a member of the SemiLayer org bound to this workspace." — Your chat user is bound to a SemiLayer account, but that account isn't a member of the workspace's org. An org admin needs to invite you (Settings → Team → Invite member) using the email tied to your SemiLayer account.

Bot doesn't respond at all. — Check Settings → Integrations: is the workspace marked Connected? If yes and commands still 404, the bot may not be invited to the channel you're typing in. In Slack, type @SemiLayer and Slack will offer to invite the app. In Discord, the bot needs View Channel + Send Messages permission on the channel.