Loopfour
Triggers

Slack triggers

Start a workflow from Slack events, slash commands or interactions, and read the payload each Slack trigger passes into the workflow run.

A Slack trigger starts a run when something happens in a Slack workspace your company has connected: a message is posted, someone runs a slash command, or someone clicks a button. There are three trigger types:

TypeStarts a run when
slack_eventSlack sends an Events API event, such as message or app_mention
slack_slash_commandSomeone runs a slash command, such as /invoice
slack_interactiveSomeone clicks a button, submits or closes a modal, or uses a shortcut

Connect Slack first. Loopfour finds the company for an incoming request by the Slack workspace ID (team_id) on your Slack connection. A request from a workspace with no connection starts nothing.

Slack events

Configuration

{
  "trigger": {
    "type": "slack_event",
    "eventType": "message",
    "channelTypes": ["channel"],
    "keywords": ["invoice", "refund"]
  }
}
FieldTypeRequiredMeaning
type"slack_event"Yes
eventTypestringYesThe Slack event to listen for. See the list below
channelTypesarray of channel, group, im, mpimNoOnly events from these kinds of conversation
userIdsstring arrayNoOnly events from these Slack user IDs, such as U01234567
keywordsstring arrayNoThe message text must contain at least one of these. Case is ignored
regexstringNoThe message text must match this JavaScript regular expression. Case matters
filterobjectNoExtra conditions on the Slack request body. See Filters

eventType is one of: message, app_mention, reaction_added, reaction_removed, channel_created, channel_archive, channel_unarchive, channel_rename, member_joined_channel, member_left_channel, file_shared, file_created, app_home_opened, link_shared, or * for any of them.

In Studio, add a Slack block and switch it to trigger mode. The block shows Event, Channel Types, User IDs, Keywords (for message and app mention events) and Filter (JSON). Studio does not offer * or regex; set those through the API.

How filters apply

  • channelTypes and userIds only filter events that carry a channel type or a user. An event without one passes.
  • keywords and regex only filter events that have text. An event with no text passes.
  • An invalid regex is skipped, not treated as a failure.
  • Every condition you set must pass.

Events that are skipped

  • Messages from bots, including Loopfour's own Slack app. This stops a workflow that posts to Slack from triggering itself.
  • For message and * triggers, housekeeping message subtypes: message_deleted, message_changed, channel_join, channel_leave, channel_topic, channel_purpose, channel_name, channel_archive, channel_unarchive, pinned_item and unpinned_item. File uploads (file_share) and thread replies sent to the channel (thread_broadcast) still start runs.

Slash commands

{
  "trigger": {
    "type": "slack_slash_command",
    "command": "/invoice",
    "usageHint": "[customer] [amount]"
  }
}
FieldTypeRequiredMeaning
type"slack_slash_command"Yes
commandstringYesThe command, including the /. Must match exactly
descriptionstringNoA note for people reading the workflow. Not used for matching
usageHintstringNoA note on the arguments. Not used for matching

Slack only sends a command that is set up in the Slack app. command matches a command that arrives; it does not create one in Slack.

The person who runs the command sees a private reply, Processing /invoice..., straight away. The run starts after that. Whatever they typed after the command is in text.

The slash command trigger has no Studio block. Set it in the definition through the API.

Interactions

{
  "trigger": {
    "type": "slack_interactive",
    "interactionType": "block_actions",
    "actionId": "start_month_end_close"
  }
}
FieldTypeRequiredMeaning
type"slack_interactive"Yes
interactionTypeblock_actions, view_submission, view_closed, shortcut, message_action or *YesThe kind of interaction
actionIdstringNoFor block_actions only: one of the clicked actions must have this action_id
callbackIdstringNoThe modal's callback_id, or the shortcut's callback_id, must equal this
filterobjectNoExtra conditions on the interaction payload. See Filters

Clicks on the buttons of a Loopfour approval step are handled as approval decisions. They do not start runs.

The interactive trigger has no Studio block. Set it in the definition through the API.

What the run receives

Every Slack trigger puts the request into input.slackEvent. The run is recorded with triggerType: "webhook".

FieldMeaning
input.slackEvent.idLoopfour's ID for this delivery
input.slackEvent.sourceevents_api, slash_command or interactive
input.slackEvent.payloadThe Slack request body

What sits in payload depends on the source:

SourceUseful fields
events_apiteam_id, event_id, and event with type, user, text, channel, channel_type, ts and, for uploads, files
slash_commandcommand, text, user_id, user_name, channel_id, channel_name, team_id, response_url, trigger_id
interactiveSlack's interaction payload, such as type, user, team, actions, view and callback_id

For example, a step reads the message text as {{input.slackEvent.payload.event.text}} and the slash command arguments as {{input.slackEvent.payload.text}}. See Variable references.

Filters

filter is a JSON object. Each key is a dot path into the Slack request body, and each value is either a plain value (must be equal) or an operator object with $eq, $ne, $in or $exists. All keys must pass.

{ "event.channel": { "$eq": "C01234567" } }

For slack_event, paths start at the Events API body, so the message fields are under event.. For slack_interactive, paths start at the interaction payload.

Endpoints

Loopfour's Slack app sends requests to these routes. You do not call them yourself.

RouteReceives
POST /api/v1/slack/eventsEvents API requests, including Slack's url_verification challenge, which is echoed back
POST /api/v1/slack/commandsSlash commands
POST /api/v1/slack/interactiveButton clicks, modal submissions and shortcuts

Each request must carry a valid Slack signature (x-slack-signature, version v0, HMAC-SHA256 over v0:<timestamp>:<raw body>) and an x-slack-request-timestamp within five minutes. Otherwise it gets 401. The routes use the webhook rate limit of 10,000 requests per minute per IP address.

Loopfour answers Slack straight away and matches workflows afterwards, so Slack's three-second limit is met even when many workflows listen.

Repeated deliveries

Slack resends a request it thinks failed. Loopfour remembers each Events API event_id, and the trigger_id of each slash command or interaction for one hour and ignores a repeat in that time. A repeated slash command gets the private reply Command already processed.

Test without Slack

Start the workflow by hand with a sample request as input:

curl -X POST "https://workflow.loopfour.ai/api/v1/workflows/$WORKFLOW_ID/run" \
  -H "x-api-key: $LOOPFOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "input": {
      "slackEvent": {
        "id": "test-1",
        "source": "events_api",
        "payload": {
          "team_id": "T01234567",
          "event": { "type": "message", "user": "U01234567", "text": "Invoice for Acme, 4200 USD", "channel": "C01234567", "channel_type": "channel" }
        }
      }
    }
  }'

See API trigger for the response.

On this page