# The Inbox Autopilot: What 60 Days of Letting an n8n Workflow Triage My Email Taught Me

> Source: <https://dev.to/haopengai/the-inbox-autopilot-what-60-days-of-letting-an-n8n-workflow-triage-my-email-taught-me-8bn>
> Published: 2026-10-16 09:35:17+00:00

*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).*
