The Inbox Autopilot: What 60 Days of Letting an n8n Workflow Triage My Email Taught Me A developer built an n8n workflow that uses LLM classification and draft generation to triage 60–80 daily Gmail messages, saving roughly 35 minutes each morning over a 60-day production run. The workflow routes mail into five buckets (urgent, needs-reply, waiting-on-me, newsletter, noise) with a confidence gate that sends anything below 0.75 into a human-reviewed 'unsure' bucket, and never sends email automatically. Three failures shaped the design: synthetic few-shot examples misclassified a refund request as a newsletter, a single drafting prompt produced tonally wrong replies, and stripping quoted history caused a purchase confirmation to be filed as noise. This is part of my build-in-public series on running LLM workflows in n8n in production. Everything here is from a real template I sell and support — the mistakes are mine, the fixes are tested. Every morning I did the same thing: open Gmail, scan 60–80 new emails, decide what needed a reply, what could wait, and what was noise. It took 45 minutes on a good day. Not writing replies — just deciding . The triage, not the work. So I built a workflow to do the deciding. A Gmail trigger, a classifier, a draft-reply generator, and a morning review. It's been running for 60 days. It now saves me about 35 minutes every morning. But the interesting part isn't the time saved — it's the three ways it failed, each of which taught me a rule I now apply to every classifier I build. Gmail Trigger on new mail → a Code node that strips signatures, disclaimers, and quoted history → a classifier LLM call that assigns one of five buckets: urgent , needs-reply , waiting-on-me , newsletter , noise → a confidence gate → for needs-reply , a second LLM call drafts a reply in my voice → drafts land in Gmail as drafts , never sent. Urgent gets a Slack/Telegram ping. Newsletters get auto-archived. The morning review is a Gmail search: in:draft newer than:1d , five minutes, approve or edit. The one hard rule: the workflow never sends email. Draft-only. That single constraint makes every other failure recoverable. Week two, a customer wrote in with a refund request. Long email, polite tone, order number buried in paragraph three. The classifier filed it as newsletter with 0.91 confidence. Why? My few-shot examples were synthetic — tidy little emails I wrote myself, each fitting its bucket perfectly. Real email is not tidy. The model learned "polite + long = newsletter" from my examples and confidently applied it. The fix was to throw away the synthetic examples and few-shot with my real email — 40 actual messages, warts and all, including the ones where a refund request reads like a thank-you note. Accuracy on the tricky cases went from "scary" to "boring." Synthetic examples teach the model a clean world that doesn't exist. Classification fixed, drafting began. The first week of drafts were grammatically fine and emotionally wrong. An annoyed customer got a cheerful "Happy to help 🎉" reply. A formal partner email got slang. The problem: one system prompt for all drafts. The fix: per-bucket tone templates . The drafting prompt receives the bucket and a one-line voice card: needs-reply-angry → "acknowledge the frustration first, no exclamation marks, no emojis, state what happens next"; needs-reply-formal → "use their name, sign with full signature." It's not fancy, but misfire rate on tone dropped to near zero. Voice is a parameter, not a personality. This one cost me a customer interaction. Someone replied to an existing thread; the workflow classified the single message — "Sounds good, let's do it" — as noise . It was a purchase confirmation for a $79 custom service request. The purchase-confirmation context lived three messages up, which I'd stripped as "quoted history" to save tokens. Lesson: strip quoted history for classification, but fetch the thread for context when it matters. Now the classifier gets the current message plus the last two messages of the thread compressed , which costs ~300 extra tokens and catches every "sounds good" that actually means something. Token savings that break decisions aren't savings. Every classification returns a confidence score. Below 0.75, the email goes into a sixth bucket: unsure — always shown to the human, never auto-filed. The unsure bucket gets 10–15% of mail, and that's by design : it's where the classifier admits ignorance instead of being confidently wrong. I'd rather review 12 emails than un-archive one misfiled refund. This is the same pattern as the review-queue and retry-budget posts in this series: the system's honesty about its own limits is the feature. A classifier without an unsure bucket is a liar with good PR. ~70 emails/day, classification at ~600 tokens each plus drafts for ~10 of them: about $0.40/day on GPT-4o-mini. The 35 minutes it saves me every morning would need to be worth $0.40. It is. The Gmail API is free, n8n is self-hosted, and the only real cost was the week I spent fixing the three failures above. Two things deliberately stay human: the final send I read every draft before it goes — the 5-minute morning review is the whole quality system , and the unsure bucket which is a human inbox by another name . Everything else — reading, sorting, drafting, archiving — is the workflow's. That split has held for 60 days without an incident worth mentioning, which for an email automation is the highest praise I have. I'm building AI Automation Lab https://payhip.com/haopengailab — production-ready n8n workflow templates. The AI Inbox Triage & Reply Drafter https://payhip.com/b/W0mLE is the full workflow from this article: the Gmail trigger, the classifier with real-email few-shots, the confidence gate, the per-bucket draft templates, and the morning-review setup. My open-source patterns live at github.com/zhp910318/n8n-ai-automation-lab https://github.com/zhp910318/n8n-ai-automation-lab .