Tips > AI & LLM Integration

Build Human-in-the-Loop AI Workflows

For high-stakes outputs -- legal documents, customer-facing communications, financial summaries -- always route AI-generated content through human review bef...

For high-stakes outputs -- legal documents, customer-facing communications, financial summaries -- always route AI-generated content through human review before publishing. n8n's Wait node combined with webhook callbacks makes this pattern straightforward.

Real-world example: A workflow generates a weekly customer newsletter using AI, then sends it to a marketing manager via Slack for approval before scheduling it in the email platform.

Workflow structure:

[Schedule Trigger] → [Gather Data] → [Generate Newsletter: GPT-4o]
    → [Send to Slack for Review] → [Wait for Approval]
    → [IF: approved] →── yes ──→ [Schedule in Mailchimp]
                      └── no ──→ [Regenerate with Feedback]
```text
Slack message with approval buttons (using Slack Block Kit):

```json
{
  "blocks": [
    {
      "type": "section",
      "text": {
        "type": "mrkdwn",
        "text": "*Weekly Newsletter Draft*\nGenerated: {{ $now.toFormat('dd MMM yyyy') }}"
      }
    },
    {
      "type": "section",
      "text": {
        "type": "mrkdwn",
        "text": "{{ $json.newsletter_preview }}"
      }
    },
    {
      "type": "actions",
      "elements": [
        {
          "type": "button",
          "text": { "type": "plain_text", "text": "Approve" },
          "style": "primary",
          "action_id": "approve",
          "url": "{{ $execution.resumeUrl }}/approve"
        },
        {
          "type": "button",
          "text": { "type": "plain_text", "text": "Reject with Notes" },
          "style": "danger",
          "action_id": "reject",
          "url": "{{ $execution.resumeUrl }}/reject"
        }
      ]
    }
  ]
}
```text
The **Wait** node pauses execution until the reviewer clicks a button. The resume URL carries the decision:

```javascript
// Code node after Wait — process the reviewer's decision
const webhookData = $json;

if (webhookData.path === 'approve') {
  return [{ json: { approved: true, newsletter: $('Generate Newsletter').first().json.content } }];
} else {
  return [{ json: { approved: false, feedback: webhookData.body?.notes || 'No specific feedback' } }];
}
```text
> **Tip: Set a Deadline**
>
> Configure the Wait node with a **Limit Wait Time** of 24 hours. If no one reviews in time, route to a fallback (send a reminder, or skip that week's newsletter). Never let a workflow wait indefinitely.

Human-in-the-loop adds a few hours of latency but prevents AI hallucinations from reaching your customers.

**Related:** [Use Manual Trigger During Development Instead of Webhook or Schedule](../api-cost-optimization/01-use-manual-trigger-during-development-instead-of-webhook-or-schedule.md) | [Flatten Deeply Nested API Responses](../code-node-mastery/01-flatten-deeply-nested-api-responses.md)

Showcase builds

19 complete workflows from my own projects, each with its n8n workflow JSON to import. Showcase entries link the file at the end of the article.

See the showcase builds

Keep reading

191 entries grouped by topic, from first workflow to queue mode. Free, no signup.

Browse the encyclopedia

Need it built?

I design, build and run n8n systems for clients. Every engagement starts with a $1,500 diagnostic audit, credited toward the build.

Book a 20-minute call