How to Add Human-in-the-Loop Approval to an AI Automation Workflow
5 min read

You add human-in-the-loop approval by pausing the workflow after the AI produces its output, sending that output to a person with approve and reject controls, and resuming only when they approve. In n8n this is the Wait node, which suspends the run until a webhook fires; in code it is a pending-state record plus a resume endpoint. The mechanics are easy. The hard part is judgement: put a gate on the irreversible actions and leave the reversible ones alone, because a gate on everything just teaches people to rubber-stamp.
Key takeaways
- Pause the workflow, show the AI output to a human, and resume only on approval. The n8n Wait node does this natively.
- Gate the irreversible actions: sending a customer email, charging a card, posting publicly. Let reversible steps run free.
- Show the human the full context and a one-line summary so the decision takes seconds, not minutes.
- Set a timeout so a forgotten approval does not freeze the workflow forever. Decide what happens on no response.
- Gating everything backfires. Too many approvals turn into reflex clicks, which is worse than a few well-placed gates.
How the pause-and-resume works
An approval gate has three moving parts. The workflow runs up to the point of the irreversible action, then stops and stores its state. A notification goes to a human with the proposed action and two buttons. When they click, a webhook fires that resumes the exact run where it paused, carrying the decision with it. n8n’s Wait node handles the pause and resume in one node (n8n docs); outside n8n you store a pending record and expose a resume endpoint that looks it up.

The Slack approval gate
Here is the pattern: the workflow posts the AI draft to Slack with approve and reject buttons that point at the n8n Wait node’s resume URL. The person reads, clicks, and the workflow continues down the matching branch.
// n8n Code node: build a Slack approval message pointing at the Wait resume URL
const resumeUrl = $execution.resumeUrl; // n8n provides this when a Wait node is active
const draft = items[0].json.aiDraft;
return [{
json: {
text: `Approve this AI reply?\n\n>${draft}`,
blocks: [
{ type: 'section', text: { type: 'mrkdwn', text: `*Proposed reply:*\n${draft}` } },
{ type: 'actions', elements: [
{ type: 'button', text: { type: 'plain_text', text: 'Approve' },
style: 'primary', url: `${resumeUrl}?decision=approve` },
{ type: 'button', text: { type: 'plain_text', text: 'Reject' },
style: 'danger', url: `${resumeUrl}?decision=reject` },
] },
],
},
}];After the Wait node resumes, a Switch reads the decision query parameter and branches: approve continues to send, reject routes the draft back for a rewrite or drops it. Always include a timeout on the Wait node so a draft nobody looks at does not leave the run hanging for days.
Where to put the gate, and where not to
The instinct is to gate everything the AI does. Resist it. Every approval you add is a tax on a human’s attention, and attention spent on safe, reversible steps is attention not available for the dangerous one.
- Gate the irreversible: sending a customer email, charging a card, posting publicly, deleting data, signing anything.
- Do not gate the reversible: saving a draft, writing to an internal log, creating a task someone reviews anyway.
- Gate by confidence: auto-proceed when the model is sure, route only the low-confidence cases to a human.
The gate that caught the wrong number
June 2025, a Wednesday afternoon, a 9-person consultancy ran an AI workflow that drafted client proposals and emailed them automatically. Nadia, who ran delivery, had pushed for an approval gate before the send step, and a colleague had argued it slowed everything down. Three weeks in, the gate earned its keep. The AI drafted a proposal that quoted a project at a figure pulled from the wrong template, about 30% under their real rate, in confident, polished prose. It looked perfect. Nadia caught it in the Slack approval message in the four seconds it took to read the number, clicked reject, and the workflow looped the draft back for a fix. Out of roughly 60 proposals that month, the gate stopped exactly one. That one would have cost more than the entire year of mild inconvenience the gate added. The turn was the sceptical colleague going quiet, then asking to add the same gate to two more workflows.
That is the honest economics of approval gates. Most of the time they do nothing visible, and it is tempting to remove them. Then once a quarter they catch the thing that would have been a refund, an apology, or a lost client, and they pay for every boring approval at once.
My opinion on gates and trust
I think most teams gate the wrong things. They put approvals on everything early, the queue gets heavy, people start clicking approve without reading, and now the gate is theatre that provides false comfort. A gate that is always approved is not a control, it is a habit. Place gates only where the action is irreversible or the cost of a mistake is real, keep the rest automatic, and your reviewers will actually read the few approvals that matter. Where I will hold this loosely: in a regulated setting, a mandatory sign-off on every action may be a requirement you cannot design away, and then the answer is to make each approval as fast to read as possible rather than to remove it. For the confidence-based version of gating, see adding fallback logic for low-confidence agents, and for a real approval gate on published content, automating social media with an LLM and n8n.
“A gate that is always approved is not a safeguard, it is a habit. Put the human where a mistake cannot be undone, and nowhere else.”
Frequently asked questions
Frequently asked questions
How do I pause an n8n workflow for human approval?
Use the Wait node set to resume on a webhook. The workflow suspends at that node and stays paused until the resume URL is called, which is what the approve and reject buttons point at. The run continues exactly where it stopped.
Should every AI action need human approval?
No. Gate only irreversible or high-cost actions like sending emails, charging cards, or posting publicly. Gating everything overloads reviewers and trains them to approve without reading, which defeats the purpose of the gate.
What happens if nobody responds to an approval request?
Set a timeout on the wait step and decide the default. For risky actions, a timeout should mean "do not proceed" and escalate to someone else. Never leave a run paused indefinitely waiting on a click that may never come.
Can I combine approval gates with confidence scores?
Yes, and it is the best of both. Auto-proceed when the model is confident, and route only the low-confidence cases to a human approval gate. That keeps the approval queue small enough that people actually read each one.
Where should the approval notification go?
Wherever the reviewer already works, usually Slack, Teams, or email, with the full proposed action and a one-line summary inline. The faster the decision is to read, the healthier the approval queue stays.