Streamlining Approvals with Slack Workflow Builder
Move your approval process out of messy threads and into a structured Slack workflow. Learn how to combine Workflow Builder with a custom backend for auditable, no-code automation.
02 Sept 2025, 05:35 UTC

The Friction of Manual Approvals
Many teams handle requests—like budget approvals or content sign-offs—through a chaotic mix of direct messages and channel threads. The manual process usually looks like this: an employee posts a request, a manager sees it hours later and replies "Approved," and the team eventually finds that message to move forward. This lacks an audit trail and creates bottlenecks.
The Slack Workflow Builder solves this by turning a conversation into a structured process. The key takeaway is that while you can build the entire trigger and notification sequence without code, any requirement for long-term data persistence or complex logic requires a lightweight external app.
Building the Approval Pipeline
To avoid cluttering channels, the most effective trigger for an approval process is a shortcut. This allows a user to initiate the request only when needed, rather than triggering a workflow on every single message.
Step 1: Defining the Trigger and Input
In the Workflow Builder, create a new workflow and select the "Shortcut" trigger. This adds a menu item to the Slack interface that users can click to start the process. Once triggered, use the Collect input step to prompt the user for a description of their request. This input is stored as a variable that can be passed to subsequent steps in the execution.
Step 2: Notifying the Approver
Once the data is collected, use the Send a message step to alert the manager. For a professional interface, use Block Kit (Slack's UI framework) to include buttons for "Approve" and "Deny." This prevents the manager from having to type a response and ensures the output is standardized.
{
"blocks": [
{
"type": "section",
"text": {
"type": "mrkdwn",
"text": "*New Request:* ${request_description}\n*From:* <@${requester}>"
}
},
{
"type": "actions",
"elements": [
{
"type": "button",
"text": { "type": "plain_text", "text": "Approve" },
"value": "approve",
"action_id": "decision_btn"
},
{
"type": "button",
"text": { "type": "plain_text", "text": "Deny" },
"value": "deny",
"action_id": "decision_btn"
}
]
}
]
}
Handling Logic with a Custom App
Workflow Builder is stateless; it forgets everything once the run ends. To create a permanent record of the approval, you must use the Run a workflow step action to call an external HTTP endpoint. This endpoint acts as your backend to log the decision in a database.
Run this logic on a server (e.g., Node.js) with the following structure:
app.post('/slack/approval-handler', async (req, res) => {
const { user, actions } = req.body;
const decision = actions[0].value; // 'approve' or 'deny'
const timestamp = req.body.message_ts;
// Log to external database for audit trail
await db.logs.insert({
requestId: timestamp,
approver: user.id,
decision: decision,
date: new Date()
});
res.json({ text: `Decision recorded: ${decision}` });
});
Constraints and Trade-offs
- Step Limits: A single workflow execution is limited to 250 steps. This is plenty for simple approvals but may fail for complex, multi-stage corporate hierarchies.
- Rate Limiting: High-frequency triggers (like "on every message") can hit workspace quotas. Stick to shortcuts or scheduled triggers for administrative tasks.
- Permissions: Only users with the
Workflowspermission can publish or edit these flows. If you see a "Not authorized" error, contact your workspace admin. - State Management: Because data is purged after the run, any requirement for a "history" tab or reporting must be handled by your external app.
Verification and Testing
To verify the deployment, follow these steps:
- Trigger the shortcut and fill out the input form.
- Confirm the approver receives the Block Kit message with buttons.
- Click a button and check the Workflow Builder History tab to ensure the status is marked as
Success. - Query your external database to confirm the decision was persisted.
If a step fails, the execution log will provide the error code and the specific step that timed out or returned a non-200 response.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.