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
01 — Problem
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.
02 — Build
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.
03 — Decisions
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.
04 — Result
Result
lanes: auto, human review, security hold
inbound ports, database keys, or credentials held by n8n
nodes in the production worker, generated from a build script
05 — Next
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.