← All projects
LIVE DEMO

Support ticket triage agent

One n8n workflow that classifies, routes and drafts support tickets, and never answers on its own

STACKn8n 2.31.5 / PostgreSQL 16.14 / OpenRouter / Node.js / Docker
CONTEXTSpec project (Upwork brief)
DATE2026-07
Open recruiter demo support-ticket-triage-demo.aaron.cv
EVIDENCE, NOT CLAIMS

Eight cases you can trigger yourself

The demo posts to the same webhook as the source repository, with the same workflow, the same policy rows and the same provider. Every scenario states what it expects before it runs, then shows the actual result and the PostgreSQL rows behind it. Classification is probabilistic and is labelled as such; the policy checks are not. If the live provider fails during your run, the console says so and shows the safe degradation instead of a result.

42 automated scenarios in the versioned catalog 25 live classifier, 15 protected fixtures, 2 injected provider failures
202/210 scenario executions passed over five consecutive runs Measured 2026-07-24. Per run 40 or 41 of 42, no skips.
63 unit and contract tests passed 0 failed, with format, ESLint and Stylelint checks
0.75 confidence threshold that forces human review A policy row in PostgreSQL, changeable without touching the workflow
0 replies sent automatically The workflow only creates drafts. never_auto_send is an active policy row.
Not measured production accuracy, latency and availability Local synthetic runs only. This build has never seen production traffic.
01

It stops instead of guessing

Urgent, sensitive, low-confidence and incomplete tickets go to a human with no draft.

VERIFY: Run Ambiguous request and Sensitive topic
02

Routing is deterministic

The same urgent ticket routes to human review inside business hours and to on-call outside them.

VERIFY: Run Urgent during business hours, then After-hours urgent
03

Duplicates cost nothing

A repeated event returns the stored result, with one ticket and one decision in the database.

VERIFY: Run Duplicate event
04

Failures are loud and safe

A permanent provider failure returns HTTP 503, keeps the ticket for review and opens an alert.

VERIFY: Run Permanent provider failure
05

Retries are bounded and recorded

A transient provider error is retried with backoff and written to the audit trail as retry_scheduled.

VERIFY: Run Transient provider error
06

Every decision is auditable

Ticket, decision, cited sources, audit actions and alerts are read back from PostgreSQL after each run.

VERIFY: Open the PostgreSQL evidence panel under any result
TRY THESE CASES
Routine product questionAccepted, one cited source, draft created but never sent
Urgent during business hoursUrgent priority, human review queue, no draft
After-hours urgentSame ticket, business hours outside, on-call queue
Ambiguous requestConfidence below 0.75, human review, no draft
Sensitive topicPhrase match in SQL, privacy and security queue, no draft
Duplicate eventSecond call reported as duplicate, one ticket and one decision
Transient provider errorRetry recorded, then a normal accepted result
Permanent provider failureHTTP 503, ticket kept as failed, open provider_error alert
Your own ticketSame guardrails, and the invariants are checked on your input too
RUNTIME PATH
  1. Public console validates a synthetic ticket and posts it to the internal n8n webhook
  2. The workflow checks the intake contract and rejects an invalid one with HTTP 400
  3. PostgreSQL reserves the external ticket ID atomically before any provider call
  4. One provider classifies into a strict JSON schema with bounded retries
  5. SQL policy applies sensitive topics, required fields, confidence, timezone and business hours
  6. A grounded draft is created only when exactly one active knowledge version matches
  7. Decision, cited sources and audit actions are written in one transaction
  8. A separate error workflow records failures and raises an operational alert
DATA BOUNDARY

Synthetic customers and tickets only. n8n, PostgreSQL and the provider key stay on the internal Docker network; the console is the single public surface.

  • Only the ticket subject and message reach the model provider. Customer records, policy rows and knowledge articles stay in PostgreSQL.
  • The browser never receives the webhook URL, the database URL or the provider key.
  • Provider processing region and retention are not configured or measured for this reference implementation.
  • Operational alerts stay in PostgreSQL. No external notification channel is configured.
  • The demo database resets to its seeded state every night at 04:00 CET.

Support inboxes fail in the same two ways. Either everything waits for a person, or an assistant answers confidently and gets it wrong. This build takes the second risk seriously: the model is allowed to read and classify, and nothing else.

A ticket arrives on an n8n webhook and is validated against a strict intake contract. PostgreSQL reserves the external ticket ID atomically, so a repeated event returns the stored result instead of paying for a second classification. One provider then classifies the ticket into a fixed JSON schema. Output that does not fit the schema is treated as a provider failure, not as a guess.

Everything after that is deterministic. Sensitive topics are matched by phrase in SQL. Required fields depend on the category. Confidence below the 0.75 policy row forces human review. Queue, timezone and business hours come from rule tables, so the same urgent ticket routes to human review inside office hours and to on-call outside them. A grounded draft is written only when exactly one active knowledge version matches, and it is never sent.

This is a spec project built on a public brief, with synthetic customers and tickets. The measured test report is included rather than summarised: five consecutive runs of a 42-scenario catalog passed 202 of 210 executions, and all eight failures were live classification drift that still ended in human review or a safe error.

What it does

Proof console with the scenario cards for the support ticket triage demo
The public demo console. Every card states its expected behaviour before you run it.
Result panel showing checks, classification, draft response and the PostgreSQL audit trail
One run: expected versus actual, the decision, the cited source and the audit rows behind it.
n8n canvas of the published support ticket triage workflow
The published workflow: intake contract, atomic reservation, retries, policy and audit.
Local demo interface from the source repository showing a draft response and audit steps
The local demo interface that ships with the repository, running the same workflow.

Want something like this for your business?

Next one
yours?

Send a short description of what eats your time. You will usually see a working prototype before you have paid anything.

© 2026 aaron.cv · Torhout, Belgium (CET) aaronsinnaeve5@gmail.com Upwork