On this page
On a 13-row test set we wrote ourselves, rules sorted 12 of the messages before any model saw them. Episode 07 is the workflow behind that number: a shared inbox router that runs a deterministic rules engine ahead of a model, and never sends anything on its own.
A small consulting or agency inbox mixes leads, technical questions, spam and existing-client mail in one place, and every hour spent sorting it by hand is an hour not spent on the work itself. This workflow polls one mailbox, runs a known-client allowlist, a spam check and a set of regex intent patterns ahead of anything else, and only sends the messages none of those rules can call to one model, which classifies the message and drafts a reply. There is no send node anywhere on the canvas. The only write this workflow can make is a label inside the mailbox, and that write sits behind a whitelist gate that throws on any other shape.
If iframes are blocked where you are reading this, the video is at the Episode 07 video.
skynetlabsai.com) holds only 8 messages as of
this recording, too few to run a real hold-out measurement, so every count
below comes from a 13-row test fixture we wrote ourselves, disclosed here and
on every card in the video. The label-write step ships in dry run: no label
was applied to a real message during this recording.
What does the inbox router actually do?
An IMAP poll reads the inbox (disabled by default here; the recorded run used the manual test path). A masking step hashes the sender and truncates the subject before anything is stored. A deterministic rules router then checks, in order: a known-client allowlist, a spam and bounce pattern, a technical-question pattern, and a lead pattern. Anything none of those rules can call is routed to a model over OpenRouter, which classifies the message as lead, technical, spam or existing client, and drafts a reply. Every row lands in Postgres. A whitelist gate reads the write's own shape before it can reach the mailbox and refuses anything that is not a label — a label is the only write this workflow can ever make.
What did the test run actually show?
On the 13-row fixture (samples/inbox-sample.json: 12 clean rows
plus one deliberate edge case built to reach the model), the rules router
handled 12 of 13 messages without a model ever seeing them — measured by
extracting the router's own stored code and running it against the fixture
directly, not by reading the logic and guessing.
| Metric | Observed |
|---|---|
| Messages in the test fixture | 13 |
| Rules-handled | 12 of 13 (92.3%) |
| Model-handled | 1 of 13 (the deliberate edge case) |
| Ship gate | 60% or more rules-handled — cleared at 92.3% |
| Real mailbox size at recording | 8 messages, too few for a live hold-out |
| Messages sent by the workflow | 0 — there is no send node |
| Labels applied | 0 — the label write ships in dry run |
Read the small mailbox honestly: our own inbox at
skynetlabsai.com has too little real traffic yet to run the
14-day hold-out the workflow was designed around. A read-only smoke test
confirmed the mailbox credential works and can read a real message, masked
before anything left the terminal — that is a connection proof, not a volume
proof. A production install against a live agency inbox should re-run the
hold-out once real volume exists.
The cap sheet
Gotchas worth knowing before you fork this
No core n8n node applies a label or flag over plain IMAP — only the trigger
node exists in core. The label-write node ships as a Gmail node, disabled, as
the deliberate swap point: a production fork against Gmail would enable it for
real, and a fork that stays on plain IMAP needs a community IMAP action node
or a raw IMAP call in a Code node instead. Either way, this repo's reference
deployment ships dry_run: true
and that node disabled, so nothing is ever actually labelled by the copy you
clone.
A whitelist gate reads any caller-supplied write shape before it builds anything, and throws on any item that is not a label. A crafted item asking to send a reply was fed into that gate directly and it threw, refusing to write — the real pipeline never produces a send-shaped item upstream at all, so this is a genuine refusal path, not a check that never fires.
How do I import it and where are the swap points?
The free workflow JSON is MIT-licensed at github.com/waseemnasir2k26/n8n-workflows/tree/main/workflows/07-inbox-router-drafts-only. Create the Data Table for the caps row, run the schema against your own Postgres, import the workflow and the error workflow, set your own IMAP, Postgres and OpenRouter credentials, then run the manual test path before ever pointing the IMAP trigger at a live mailbox.
Three swap points are built into the canvas on purpose:
- The IMAP poll trigger, shipped disabled — the manual test path drives a sample-inbox fixture instead until you are ready for a real mailbox.
- The label-write node, shipped disabled — a Gmail node as the reference swap point, since core n8n has no plain-IMAP label action.
-
A
dry_runflag on the caps row, defaulted true, so the workflow can decide and log a row without ever touching the mailbox. Flip it only once you know exactly which mailbox that row points at.
Frequently asked questions
Does this workflow send anything?
No. There is no send node anywhere on the canvas. The only write it can make is a mailbox label, and that write sits behind a whitelist gate that refuses any other shape. Every draft the model writes stays in a review table for a person to read.
Why did you test on 13 written messages instead of the real mailbox?
Because the real mailbox only held 8 messages at recording time, too few for the 14-day hold-out the workflow was designed around. The 13-row fixture is disclosed on every card and in this article rather than left as a quiet substitution.
What happens to the messages rules cannot sort?
They reach a single model node over OpenRouter, capped at 40 calls a day behind a real Postgres count, which classifies the message and drafts a reply. The draft carries a confidence score; anything under the threshold is downgraded to needs review before it ever reaches a label.
What stops the workflow from running away on errors?
A separate error workflow counts consecutive failures and trips a breaker after 3 in a row, independent of the message rules. Once tripped, the workflow processes zero items until a person resets it by hand.
The rest of the series
One workflow per video, the JSON given away under an MIT license each time, built by Waseem Nasir at SkynetLabs.
- Episode 05, n8n clinic WhatsApp booking agent: a code guard hands off medical and price questions before the model.
- Episode 06, n8n Meta ads circuit breaker: our own breaker missed our own overspend, and this one closed the gap.
Want an inbox router tuned for your own mailbox? Book a discovery call with SkynetLabs.
WhatsApp +92 300 1001957 · Waseem Nasir, SkynetLabs
Hire SkynetLabs, our Top Rated agency on Fiverr: https://www.fiverr.com/agencies/skynetjoellc