Resources

n8n · LLM classification · human-in-the-loop

AI Support Triage with a Human Approval Gate

An n8n pipeline that classifies incoming support tickets, drafts a reply, and pauses on a hosted approval page so a human decides what gets sent.

Status
Going live on LaserBurnAI, September 2026
Period
September 2026
Role
Designed and built the SaaS endpoints, the n8n workflows, and the MCP server
n8n (self-hosted, Docker)OpenAI via n8n credentialsNext.js API routesSupabaseResendMCP (streamable HTTP)workflow-as-code build scripts

01Problem

The problem

A one-person SaaS gets support tickets at all hours. Most are routine, some are urgent lockouts, and a few are hostile: prompt-injection attempts dressed as customer messages.

Fully automatic replies were never acceptable. The goal was to remove the reading and drafting work without removing the human decision.

02Build

What I built

  • Intake: a support form on the SaaS writes tickets to a queue table. Signed-in users are identified from the session only; a plan field supplied by the client is ignored. An anonymous lane exists on purpose, rate-limited per IP, because locked-out users are the most urgent tickets.
  • Triage: a guardrail node screens for jailbreak and injection patterns, then a structured extractor classifies the ticket against a strict enum schema with a confidence score. Three lanes result: auto, human review, or security hold.
  • Drafting and approval: the model drafts a reply, then the workflow pauses on an n8n Wait node in form-resume mode. The approval page is hosted by n8n and needs no messaging credentials. The reviewer can approve, edit, or reject.
  • Delivery: the reply is sent through the SaaS, which marks the ticket answered only after the email provider confirms the send.
  • A worker that polls the SaaS every two minutes, claims one ticket at a time with a race-safe status guard, and reclaims stale work after 15 minutes.
  • A read-only MCP server so an AI assistant can list pending approvals and read tickets from the terminal.

03Decisions

The decisions that mattered

Anyone can list a stack. These are the calls that changed the outcome.

Poll, do not tunnel

The first design exposed n8n to the internet through a tunnel so the SaaS could push tickets. Polling inverted it: n8n needs zero inbound exposure, the SaaS never depends on a desktop being online, and there is nothing to attack.

The worker never gets a database key

n8n talks to three narrow SaaS endpoints behind a bearer secret with constant-time comparison. It cannot read the users table, cannot write arbitrary rows, and cannot send email on its own.

Metered AI spend is gated to paying customers

Only tickets from paid-plan users enter the automatic lane. Everyone else is routed to manual handling. One predicate in the intake route enforces it, so widening the rule later is a one-line change.

Agents read, humans decide

The MCP server deliberately has no approve tool. Exposing approval to an agent that reads untrusted customer text would defeat the point of the approval gate.

04Result

Result

3

lanes: auto, human review, security hold

0

inbound ports, database keys, or credentials held by n8n

28

nodes in the production worker, generated from a build script

05Next

What I'd do next

  • Run it against live production tickets and publish the first month of lane distribution.
  • Deliver approval links to Slack or email instead of a file, and add bearer auth to the learning-version webhooks.