Self-directed practice project
What This Workflow Does
A client fills out an intake form describing what they need built. An LLM reads the description, classifies it into one of five categories, states its reasoning, and the workflow routes it — a tailored confirmation email to the client, an internal notification, and a logged row in Google Sheets, all varying by category.
There's no live demo — like the Ferrer project, this runs inside its own n8n instance rather than being publicly hostable. The proof here is the workflow itself: view the workflow on GitHub.
How I Worked Through This
A plain three-category split wasn't enough once I actually thought
about failure cases. A genuinely ambiguous project description and
input that isn't a project description at all needed different
handling — labeling junk as "ambiguous" would misleadingly imply a
real lead worth review. I split those into two categories, then found
a second distinction inside failure itself: a classification that
fails outright (a network error, a bad API response) is a different
signal from one the model genuinely couldn't resolve, so a failed
attempt gets its own category — system_error — rather
than being folded into ambiguous.
A real test case exposed a deeper bug than a wrong label: "route incoming leads smartly based on their details" should have landed on ambiguous, and the model's own reasoning admitted it saw two valid readings and picked one anyway. The evaluation method itself was sequential — forcing a single category before ever checking whether another one also fit. I rebuilt it to independently check all three real categories first, then count how many plausibly fit, before deciding.
The classification node started failing with a parse error after I expanded to five categories. I checked the raw model output first rather than assuming my prompt was at fault — the model's answer was fine, but my structured-output schema still had the old three-category list. Fixed that, same error persisted, which sent me digging further: it turned out to be a documented bug in n8n itself, where newer versions route this node's output through logic meant for AI agents. Updating n8n resolved it cleanly.
Testing against real inboxes, not just node output, caught a real bug the schema never would have: the ai_workflow branch had its internal notification and client email destinations swapped, sending the internal-only message to the client. That same testing pass led to a structural redesign — Sheets logging didn't actually need to sit downstream of any client email succeeding, so I moved it to connect right after classification instead, decoupling the permanent record from whether a Gmail send happens to work.
Technical Details
| Component | Role |
|---|---|
| n8n | Workflow platform / orchestration |
| Form Trigger | Receives the client's intake submission |
| Google Gemini (LLM Chain) | Classifies the description and generates reasoning |
| Structured Output Parser | Forces a fixed JSON schema (category, reasoning, has_partial_intent) |
| Switch node | Routes across 6 rules — 5 categories, with ambiguous/system_error converging on shared review logic |
| Retry + fallback logic | 3 attempts, then routes to human review instead of crashing |
| Gmail API | Category-specific client and internal emails |
| Google Sheets API | Permanent log of every submission, decoupled from email success |