This workflow follows the HTTP Request → Slack recipe pattern — see all workflows that pair these two integrations.
The workflow JSON
Copy or download the full n8n JSON below. Paste it into a new n8n workflow, add your credentials, activate. Full import guide →
{
"_meta": {
"template": "hitl-gate",
"description": "Human-in-the-loop approval gate. Agent calls webhook \u2192 Slack notification \u2192 human approves/rejects \u2192 action executes \u2192 result returned synchronously.",
"skill": "n8n-hitl-gate",
"version": "0.1.0"
},
"name": "[Tool] HITL Gate - ACTION NAME",
"nodes": [
{
"id": "webhook-trigger",
"name": "Webhook Trigger",
"type": "n8n-nodes-base.webhook",
"position": [
240,
300
],
"parameters": {
"httpMethod": "POST",
"path": "hitl-action",
"responseMode": "responseNode",
"options": {}
}
},
{
"id": "validate-payload",
"name": "Validate Payload",
"type": "n8n-nodes-base.code",
"position": [
480,
300
],
"parameters": {
"jsCode": "// Validate and describe the action for the approval message\nconst { action, target, value } = $json.body;\n\nif (!action || !target) {\n throw new Error('Missing required fields: action, target');\n}\n\nreturn {\n action,\n target,\n value: value || null,\n description: `${action}: ${target}${value ? ` ($${value})` : ''}`,\n requested_at: new Date().toISOString()\n};"
}
},
{
"id": "slack-approval",
"name": "Slack Approval Request",
"type": "n8n-nodes-base.slack",
"position": [
720,
300
],
"parameters": {
"operation": "message",
"channel": "#agent-approvals",
"text": ":robot_face: *OpenClaw action requires approval*\n\nAction: {{ $json.description }}\nRequested: {{ $json.requested_at }}\n\n*Click to respond:*\n<YOUR_N8N_URL/webhook/approve-action?execution_id={{ $execution.id }}&decision=approved|\u2705 Approve> | <YOUR_N8N_URL/webhook/approve-action?execution_id={{ $execution.id }}&decision=rejected|\u274c Reject>\n\n_This request expires in 24 hours_"
},
"credentials": {
"slackApi": {
"name": "<your credential>"
}
}
},
{
"id": "wait-for-approval",
"name": "Wait for Approval",
"type": "n8n-nodes-base.wait",
"position": [
960,
300
],
"parameters": {
"resume": "webhook",
"options": {
"limitWaitTime": true,
"limitType": "hours",
"limitValue": 24
}
}
},
{
"id": "check-decision",
"name": "Check Decision",
"type": "n8n-nodes-base.if",
"position": [
1200,
300
],
"parameters": {
"conditions": {
"string": [
{
"value1": "={{ $json.query.decision }}",
"operation": "equals",
"value2": "approved"
}
]
}
}
},
{
"id": "execute-action",
"name": "Execute Action (customize this)",
"type": "n8n-nodes-base.httpRequest",
"position": [
1440,
200
],
"parameters": {
"method": "POST",
"url": "YOUR_API_ENDPOINT",
"sendBody": true,
"bodyParameters": {
"parameters": []
}
}
},
{
"id": "respond-approved",
"name": "Respond: Completed",
"type": "n8n-nodes-base.respondToWebhook",
"position": [
1680,
200
],
"parameters": {
"respondWith": "json",
"responseBody": "={{ JSON.stringify({ status: 'completed', message: 'Action approved and executed', result: $json, timestamp: new Date().toISOString() }) }}",
"options": {
"responseCode": 200
}
}
},
{
"id": "respond-rejected",
"name": "Respond: Rejected",
"type": "n8n-nodes-base.respondToWebhook",
"position": [
1680,
400
],
"parameters": {
"respondWith": "json",
"responseBody": "={{ JSON.stringify({ status: 'rejected', message: 'A human declined this action', timestamp: new Date().toISOString() }) }}",
"options": {
"responseCode": 200
}
}
}
],
"connections": {
"Webhook Trigger": {
"main": [
[
{
"node": "Validate Payload",
"type": "main",
"index": 0
}
]
]
},
"Validate Payload": {
"main": [
[
{
"node": "Slack Approval Request",
"type": "main",
"index": 0
}
]
]
},
"Slack Approval Request": {
"main": [
[
{
"node": "Wait for Approval",
"type": "main",
"index": 0
}
]
]
},
"Wait for Approval": {
"main": [
[
{
"node": "Check Decision",
"type": "main",
"index": 0
}
]
]
},
"Check Decision": {
"main": [
[
{
"node": "Execute Action (customize this)",
"type": "main",
"index": 0
}
],
[
{
"node": "Respond: Rejected",
"type": "main",
"index": 0
}
]
]
},
"Execute Action (customize this)": {
"main": [
[
{
"node": "Respond: Completed",
"type": "main",
"index": 0
}
]
]
}
},
"settings": {
"executionOrder": "v1"
},
"tags": [
{
"name": "agent-tools"
},
{
"name": "hitl"
}
]
}
Credentials you'll need
Each integration node will prompt for credentials when you import. We strip credential IDs before publishing — you'll add your own.
slackApi
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
[Tool] HITL Gate - ACTION NAME. Uses slack, httpRequest. Webhook trigger; 8 nodes.
Source: https://github.com/bcharleson/n8n-agent-cli/blob/c16a09ec7630f508ef5b46d5c7e1b15d006ec7af/templates/hitl-gate.workflow.json — original creator credit. Request a take-down →
Related workflows
Workflows that share integrations, category, or trigger type with this one. All free to copy and import.
This n8n workflow orchestrates a powerful suite of AI Agents and automations to manage and optimize various aspects of an e-commerce operation, particularly for platforms like Shopify. It leverages La
Fully automates your service order pipeline from incoming booking to supplier confirmation — with built-in SLA enforcement and automatic escalation if a supplier goes silent. 📥 Receives orders via web
This workflow automatically processes new free-trial / lead sign-ups in real time: Catches a webhook from any source (Webflow form, Intercom, custom agent, etc.) Filters out personal / disposable / .e
Public-facing professionals (developer advocates, founders, marketers, content creators) who get bombarded with LinkedIn messages that aren't actually for them - support requests when you're in market
This workflow transforms natural language queries into research reports through a five-stage AI pipeline. When triggered via webhook (typically from Google Sheets using the companion [](https://gist.g