DEV Community

Cover image for Every AI email tool has the same bug. It is not a bug in the model.
yongrean
yongrean

Posted on

Every AI email tool has the same bug. It is not a bug in the model.

Every AI email product shipped in the last two years has the same architecture, and it is the wrong one.

The model reads your mail. The model decides what matters. The model drafts a reply, and in the ambitious ones, the model sends it. Somewhere in the system prompt there is a paragraph asking it politely to check with you first.

That paragraph is the entire safety story. That is the bug.

The bug is not that models hallucinate

Everyone knows models hallucinate. That is priced in. The bug is subtler and worse: these systems give the model authority, then try to constrain it with instructions.

Instructions are input. Your email is also input. And your email is written by strangers.

So the threat model is not "the model is sometimes wrong." It is: someone who wants your model to do something writes an email designed to make it do that. They do not need to breach your infrastructure. They just have to send you mail — which is a thing they are already allowed to do, by design, for free, from anywhere on earth.

Ask whatever AI inbox tool you use one question:

When it decides to hide a message from me, what artifact can I read to see why? Not a natural-language explanation the model generated afterward — the actual decision.

There usually isn't one. The decision was a forward pass. It left no trace you can audit, test, or pin.

The fix is boring and nobody ships it

Separate perception from authority.

Let the model do what models are genuinely good at: read messy text, produce a few calibrated numbers. Then let code make the decision.

In my own tool the model never picks the outcome. It scores four features per email — confidence, sender trust, reversibility, urgency — and a deterministic, unit-tested rule maps those four numbers to exactly one of five lanes: interrupt me now, it's scheduling, queue it, file it as a record, or never render it. That rule is about 200 lines. You can read it. A test pins it. If its behaviour changes, CI fails.

Three things fall out of that split, and they are why I think this is a correctness argument rather than a style preference.

Model choice stops being a vibe and becomes a measurement. I re-ran my committed 56-email gate set across six current models today — same prompt, same rule, one run each:

model overall urgent recall $/M input
gpt-5.4 100% (56/56) 13/13 $2.50
gemini-3.5-flash 98.2% 13/13 $1.50
gemini-2.5-flash 96.4% 13/13 $0.30
grok-4.3 94.6% 12/13 $1.25
claude-opus-4.8 91.1% 10/13 $5.00
claude-sonnet-5 80.4% 5/13 $2.00

I had been telling people a cheap model beats the expensive ones. That is no longer true and I am retiring it — gpt-5.4 is perfect on this set. But look at what replaced it, because it is worse news for the industry, not better: price does not order the table. The most expensive model lands fifth. Two frontier models fail my gate outright. And the spread among frontier models is 19.6 points — five times the 3.6-point gap between the best of them and a pin that costs eight times less.

If you picked your model because it benchmarks well, you picked on a number that has nothing to do with this job.

A failure gets a mechanism instead of a shrug. Sonnet 5 missed eight urgent emails. Seven of them failed on confidence, not urgency — it scored urgency 0.80–1.00, which is correct, and confidence 0.55–0.60, against a rule that needs 0.70 to interrupt you. It read the situation right and then declined to say it was sure.

I know that because the threshold is a number in a file I can open. In a "the model picks the tier" design, this same result reads as Sonnet 5 is worse at email — which is both wrong and useless. You cannot fix a vibe.

It degrades instead of breaking. With no LLM at all — provider down, rate limited, key expired — a keyword path produces the same four features and still classifies at 82.1%. I want to be precise about what that does and does not buy, because I have been sloppy about it before: urgent recall in that mode is 46.2%. Degraded mode costs you the interrupt. It does not cost you the message — every urgent item it missed landed in the queue, visible, and none were hidden.

Automation is not a lane

This is the part people get wrong when they copy the pattern.

Classification and delegation are separate decisions, and collapsing them is how "it sorted my mail" becomes "it answered my mail." A lane says what a message is. A separate flag says whether this particular message is even eligible to be answered unattended — reversible, high confidence, trusted sender, not urgent. And a separate account-level mode says whether unattended answering is on at all.

Three switches, not one. You can be wrong about the lane and still not be wrong about the outbox.

Approval has to bind bytes, not intent

The classification half is the easy half. The hard part is the three actions you cannot take back: send, permanent delete, forward.

Most tools gate those behind a confirmation dialog. That is theater, because what you confirmed and what executes are connected by nothing but hope.

So: approving mints a receipt — a sha256 over the exact canonical payload bytes at the moment you click yes. At execution the bytes are hashed again and compared. Any drift and it fails closed. No send, no delete, no forward.

The check does not live in the prompt. It lives in the execution path. There is no phrasing that gets around it, because the thing doing the checking cannot read English.

That is the difference between a safety policy and a safety property.

The part where I make this falsifiable

Claims like these are cheap, so here is mine, stated so you can break it:

Given an inbound message crafted to maximize model confidence, no path exists from classification to an executed irreversible action without a human approval that byte-pins the payload.

Note what that does not say. It does not say the model can't be fooled — it can. It does not say the lane will be right — a hostile message may well land in PUSH. That is a nuisance, not a breach. The floor is not a better classifier. It is a smaller blast radius.

The repo's SECURITY.md lists nine claims like that one, and for each: what would disprove it, and which test enforces it. It also names what has no authority — including my own accuracy numbers. A 96% classification score is not a safety argument, and I would rather say so myself than let it quietly stand in for one.

Here is the same rule applied to me. While writing this I re-ran my real-mail eval set and it came back at 86.8%, not the 94.3% my README had been claiming for weeks. The gap turned out to be fully explained — four of the seven misses are a lane the labels predate, and 46 + 4 = 50 is exactly the old number — but "fully explained" is not the same as "still true." The number stopped reproducing, so it is out of the README as of today, along with the model claim above. If you want to check either one, the eval sets and the runner are in the repo.

That is the actual test of whether a project means the falsifier thing: what happens when its own number fails.

It also lists what is missing. There is no end-to-end adversarial corpus yet — fixtures that start from a hostile email and assert containment across the whole path. That gap is written down in the repo, not hidden.

So

If you use anything with an LLM near your inbox, go find out how it decides. If the answer is "the model decides, and we told it to be careful," you are trusting a probability distribution with your outbox.

You do not have to use mine. It's AGPL, self-hostable, docker compose up -d with prebuilt images, and it runs against a local model if you want nothing leaving your machine at all. But whatever you use — make it show you the decision.

Six months solo, 101 releases, ~1,590 commits. If you think the architecture is wrong, the fastest way to prove it is a PR that breaks the claim above. I'll merge it.

github.com/k08200/klorn

Top comments (1)

Collapse
 
deanlee profile image
Dean Lee

Email is the nastiest version of this because the attacker is already inside the normal input channel. I like the framing around authority. The safe boundary probably has to live outside the model, with the model reduced to proposing actions that another layer can permit or reject.