Slack connections

The Slack integration lets recipes listen for events and slash commands in your Slack workspace, call the Slack Web API to read and post messages, and route specific automations to specific Slack users by linking their Slack identity to a Neurocad account. Three things have to be in place before any Slack-driven recipe will run end-to-end:

  1. The workspace is connected in /connect.
  2. The Neurocad bot is invited to any channel the recipe needs to listen to or post in.
  3. Each invoking user has run /neurocad link in Slack and confirmed the link in Neurocad.

The rest of this doc walks through each of those, then covers the Slack trigger and Slack action nodes.

1. Connect the Slack workspace

In Neurocad, go to /connect → SlackAdd connection. This kicks off Slack's OAuth v2 install flow:

  • Sign in to your Slack workspace if prompted.
  • Review the requested bot scopes — chat:write, channels:read, groups:read, channels:history, groups:history, reactions:read, reactions:write, app_mentions:read, commands, files:read, users:read — and approve.
  • Slack redirects back to /connect/provider/slackApi and the new workspace appears in the list.

What's stored on the connection: the bot OAuth token, the team id, the team name, the bot user id, and the OAuth scopes that were granted. The team id is the routing key for everything Slack-related — every trigger registration and every inbound event uses it.

If a workspace later changes its scopes, updates its app config, or has its tokens revoked, the connection drifts:

  • needs_reauth — Slack delivered a tokens_revoked event. The connection stays, but executions using it will fail until you reconnect from /connect.
  • uninstalled — Slack delivered an app_uninstalled event. The connection is marked uninstalled and you'll have to add the workspace again before recipes referencing it can deploy or run.

Both states show up on the connection card and surface as missing_scope / invalid_auth / token_revoked errors at runtime, with the recommended fix: "The Slack connection is no longer valid. Reconnect the workspace in Connections."

2. Invite the Neurocad bot to channels

The Slack bot can only see, post in, or download files from channels it has been invited to. Inviting it is a one-time setup in Slack itself:

  • In any channel you want the recipe to use, run /invite @Neurocad.
  • Repeat for every channel (or DM) the recipe needs.

If the bot isn't a member of a channel the recipe references, you'll see runtime errors with a clear hint: "The Slack bot is not a member of this channel. Invite it in Slack and try again." (That's Slack's not_in_channel / channel_not_found error mapped to user-facing copy.) The fix is always: invite the bot.

For public channels, an invite is enough. For private channels, the bot has to be invited by an existing member; there's no admin-side override.

3. Each user links their Slack identity with /neurocad link

Some Slack triggers — app mention and slash command — are user-invoked: a specific Slack user typed @neurocad deploy or /neurocad deploy. To run those safely, Neurocad has to know which Neurocad user is invoking, not just which Slack user. That's what /neurocad link does.

How a user links

  1. In any Slack channel where the bot is installed, type /neurocad link.
  2. The bot replies with an ephemeral message containing a one-time URL: "Link your Slack account to Neurocad: … This link expires in 10 minutes."
  3. Click the URL. It opens Neurocad's /slack/link?token=… page.
  4. Sign in to Neurocad if not already signed in. The page shows Confirm link with the description: "Confirm to link your Slack account to your Neurocad account. This allows you to trigger automations from Slack."
  5. Click Confirm link. The token is consumed and the Slack identity is bound to the signed-in Neurocad user.

The token is single-use and expires in 10 minutes. If it expired or was already consumed, the page says "This link has expired. Use /neurocad link in Slack to get a new link." and the user just runs /neurocad link again.

A user can review and remove their links from /settings under Connected accounts. Removing a link doesn't delete the Slack workspace connection itself — just the user-to-Slack-identity binding. They can re-link any time with /neurocad link.

What /neurocad link requires server-side

When /neurocad link arrives, the platform looks up the Slack workspace install for the team id Slack sent. If there is none — i.e. nobody at your workspace has run /connect → Slack yet — the bot replies: "No Slack workspace installation is registered for this team. A workspace admin needs to install Neurocad first." Have a workspace admin connect the workspace from /connect, then re-run /neurocad link.

Why two-step linking exists

The Who can invoke setting on the Slack trigger node decides who is allowed to fire the automation:

  • Only org members (default) — Only Slack users whose linked Neurocad user is a member of this workflow's organisation can invoke. This is the right default for internal automations.
  • Anyone with a linked account — Any Slack user in the workspace whose account is linked to Neurocad can invoke, regardless of org membership.

In both modes, an invoker who hasn't run /neurocad link yet gets blocked, with an ephemeral reply: "Your Slack account is not linked to Neurocad yet. Run /neurocad link and follow the URL to finish linking."

In org-members mode, an invoker who is linked but not a member of the workflow's org gets: "You don't have access to that command. It's restricted to members of the workflow's organisation."

Non-user-invoked events (message, reaction_added, file_share, channel_created, team_join, etc.) bypass this gate entirely — they fire on the workspace firehose without per-user gating.

The Slack trigger node

Slack trigger starts a recipe when a matching Slack event arrives. It uses the slackApi credential, fires inside the workspace selected by that credential, and registers itself with Slack to receive events on the platform's webhook endpoints (/api/slack/events and /api/slack/commands).

Trigger on

A multi-select of event types this trigger fires for. You can pick more than one.

  • Any event — Wildcard. Fires on every event the bot can see in the workspace. Useful while exploring.
  • App mention — The bot is @-mentioned in a channel it's in. Pair with Command word below.
  • Slash command — A workspace user runs a /neurocad <word> slash command. Pair with Command word.
  • New message — A message is posted to a channel the bot is in.
  • Reaction added — A reaction is added to a message.
  • File shared — A file is shared in a channel. Pair with Download attached files below.
  • File made public — A file is made public.
  • Channel created — A new public channel is created.
  • User joined workspace — A new user is added to the workspace.

Watch entire workspace / Channel to watch

For events that are tied to a channel (message, reaction_added, file_share, app_mention, plus Any event), you choose between:

  • Watch entire workspace — Fires for matching events in any channel the bot is in. Off by default.
  • Channel to watch — Required when Watch entire workspace is off. Pick from the channel list, paste a channel id, or paste a Slack channel URL — all three are accepted.

Workspace-wide events (team_join, channel_created, file_public) deliver workspace-wide regardless of the channel selection.

Command word (user-invoked events only)

Required when App mention or Slash command is selected. This is the first word after the mention or slash that addresses this specific automation, e.g. deploy in @neurocad deploy or /neurocad deploy. It must be:

  • Unique within the Slack workspace — Two recipes can't both register the word deploy. The activation step rejects duplicates with: "Command deploy is already registered to a different automation in this workspace. Unregister it first or choose a different command alias."
  • Case-insensitive, normalised at registration time.

The recipe is matched by (team_id, command_word). Slack's /neurocad <word> and @neurocad <word> both route to whichever recipe registered <word> first.

Who can invoke (user-invoked events only)

The access control gate described in Why two-step linking exists.

Download attached files (file_share / Any event only)

When on, files attached to the inbound event are downloaded inline through the Slack credential and exposed as binary fields (file_0, file_1, …) on the workflow item. Downstream nodes — Library, Schematic, Create share link — can wire those binary fields directly. Off by default; turn it on whenever you need to actually use the shared file.

Show user and channel names

Off by default. When on, the trigger calls users.info and conversations.info to enrich the inbound payload with user_name and channel_name, so events show @alice / #general instead of U01ABC / C01XYZ. Costs one Slack API call per resolved id per event.

Ignore events from these users

Multi-select of Slack users whose events should be silently dropped. Useful for ignoring the bot's own messages, or for skipping known-noisy automation accounts.

Listen / Capture

Like every trigger that supports trigger capture, the property panel shows a Listen button. Click it, then trigger the event from Slack — post the message, run the slash command, etc. — and Neurocad captures one real payload so the rest of the graph has a real Slack event to wire against.

The Slack action node

Slack is the outbound action node. Like the GitHub node, it exposes a Resource + Operation selector that drives the rest of the form. The credential is slackApi.

Resources and operations

  • Channel — Get, History, List, Members, Replies
  • Message — Send, Update, Delete, Get permalink
  • Reaction — Add, Remove, Get
  • File — Download
  • User — Get, List

Common parameters across resources

  • Channel — Pick from list, paste an id, or paste a Slack URL. Required for every channel / message / reaction operation.
  • User — Pick from list, paste an id, or paste a Slack URL. Required for User → Get.
  • Limit / Return all — For collection endpoints (channel.list, channel.history, channel.replies, channel.members, user.list). When Return all is on, the node walks Slack's cursor pagination internally.
  • Channel types — For Channel → List: any combination of public channels, private channels, IMs, MPIMs.

Message specifics

  • Send / Update — Takes Message text. Send also takes an optional Thread timestamp to reply in a thread.
  • Update / Delete / Get permalink — Takes Message timestamp.
  • History — Takes optional Oldest timestamp / Latest timestamp / Include archived filters.
  • Replies — Takes the Thread timestamp to fetch replies for.

Reaction specifics

  • Reaction name — The emoji name without colons (thumbsup, not :thumbsup:).

File → Download

  • File URL — Slack's url_private / url_private_download. Most often you wire this from a Slack trigger's event.files[*].url_private_download.
  • File name / MIME type / Output field name — Control how the downloaded file is attached to the outgoing item. The downloaded file lands as a binary field on the item under the chosen field name.

Provider error mapping

Slack's Web API returns errors as { ok: false, error: "<code>" } even on HTTP 200. The node maps the common ones into actionable messages so the failure is obvious in the run panel:

  • not_in_channel / channel_not_found"The Slack bot is not a member of this channel. Invite it in Slack and try again."
  • user_not_found"Slack could not find that user. Choose a user from the list or enter a valid Slack user ID."
  • message_not_found"Slack could not find that message. Check the channel and message timestamp."
  • missing_scope"The connected Slack workspace is missing a required scope. Disconnect and reconnect it in Connections to grant the new permissions."
  • invalid_auth / token_revoked / account_inactive"The Slack connection is no longer valid. Reconnect the workspace in Connections."
  • rate_limited"Slack rate-limited the request. Wait a moment and retry."

Common Slack-driven recipe shapes

The built-in Slack create library preset is a complete example of all three concerns lining up:

Slack trigger (slash_command, command word "create-symbol", download files on)
→ Slack (file → Download) # pulls the uploaded file
→ Slack (user → Get) # resolves invoker info
→ Library (extract from binary) # generates a symbol
→ Create share link # returns a public URL
→ Slack (message → Send) # posts the result back to the originating channel

The preset's first canvas note spells out the same checklist: "This recipe requires your Slack connection. Navigate to /connect and add it there first. Then @Neurocad can be invited to your Slack channels. Last each user must type the command /neurocad link to register their Slack user with Neurocad."

A simpler workspace-firehose pattern, no slash command, no per-user gating:

Slack trigger (file_share, watch workspace, download files on)
→ Library
→ Create share link
→ Slack (message → Send to a fixed #ops channel)

Deploying a Slack-driven recipe

Slack recipes are deployable — they start from a server-side trigger and only use Connect / EDA nodes. Once the recipe is shaped:

  1. Click the recipe title menu → Deploy. The deployment lands in /automate as inactive.
  2. In /automate, toggle the recipe on. Activation registers the trigger against the workspace's team id and the chosen routing key (event types + command word + channel). Slack now starts routing matching events to the recipe.
  3. Deactivating tears the registration down. Updating the recipe and clicking Update deployment rebuilds the registration in place.

Two activation-time errors are worth knowing:

  • "Slack credential is missing the team id — cannot register the trigger. Reconnect the Slack integration so the team id is captured." — The connection record is from before team-id capture, or got partially populated. Reconnect from /connect.
  • "Command <word> is already registered to a different automation in this workspace. Unregister it first or choose a different command alias." — Your command word collides with another deployed recipe in the same workspace. Pick a different word, or remove / deactivate the conflicting recipe.

Quick checklist when something doesn't fire

If a Slack-driven recipe doesn't seem to be firing, walk this list in order — almost every "it's not working" report is one of these:

  • The Slack workspace is connected in /connect and the connection isn't needs_reauth or uninstalled.
  • The recipe's deployment is active in /automate.
  • The bot is a member of the channel the recipe watches (run /invite @Neurocad in that channel).
  • For app mention / slash command: the command word matches what the user typed and is unique in the workspace.
  • For app mention / slash command: the invoking user has run /neurocad link and confirmed it.
  • For org-members mode: the invoker's linked Neurocad user is a member of the workflow's organisation.
  • The credential's granted scopes cover what the action nodes call (look for missing_scope errors and reconnect to widen scopes).

If all of those pass and it's still silent, capture a real event with the trigger's Listen button — that tells you whether Slack is reaching the workflow at all, separately from whether downstream nodes are succeeding.

Last updated May 7, 2026