Sajjad Mahessar Good Merch Group Free audit
~/sajjad $ cat projects/ai-email-agent ← cd ../projects Systems

AI email agent

Live since Jul 2026~£1/month to run

An agent that answers the venue inbox. It polls every ten minutes, classifies each message, and writes a reply into the Drafts folder for a human to read and send. It has never sent an email and cannot. Everything it isn't certain about goes to a person instead.

Type
AI agent
Category
Systems
Built with
Python (stdlib only) · Microsoft Graph · Provider-agnostic LLM · SQLite · launchd
Project
6 of 37
// watch · 29s
The escalation section of the knowledge base listing categories the agent must never auto-answer
EVERY TEN MINUTES 1 · FETCH · NEW MAIL SINCE WATERMARK 2 · PRE-FILTER · NO AI · DROPS OTA, SUPPLIER, NOREPLY 3 · UNDERSTAND · ONE MODEL CALL · RETURNS JSON 4 · GUARD · NO AI · CAN VETO ANYTHING PROPOSED 5 · ACT · CREATE DRAFT IN THE ORIGINAL THREAD 6 · LOG · DECISION AND TOKEN COST THE MODEL PROPOSES · ORDINARY CODE DECIDES WHAT IS ALLOWED OUT
Two of the six stages contain no AI at all — that's the design

The guard layer

The model proposes a reply. Then ordinary code decides whether it is allowed to exist. A prompt is a request; code is a rule — and the model cannot talk its way past a rule.

  • No bank details, ever. Every draft is scanned for sort-code, account-number and IBAN patterns. The highest-value rule in the system, because invoice-interception fraud targets hospitality inboxes specifically.
  • Price whitelist. Every currency figure in a draft must already appear in the knowledge base. An invented price cannot leave the building.
  • Force-escalate keywords read from the incoming email, not the reply — refunds, chargebacks, solicitors, environmental health, allergy, coeliac, anaphylaxis. These escalate regardless of what the model concluded.
  • Link whitelist, competitor blocklist, a length ceiling, and a block on any draft that discloses being automated.
  • A confidence floor: below 0.75 it escalates whatever it said.
A blocked draft isn't discarded silently — it's logged and escalated, so you can see what it tried to say and why it was stopped. The failures are visible rather than invisible.

What I built

  • A six-stage pipeline where stages two and four contain no AI at all. A deterministic pre-filter drops booking platforms, suppliers, marketing and anything from a no-reply address before a single token is spent; the guard layer sits between the model and the mailbox.
  • An 18-section knowledge base as one editable file per venue, read fresh on every run. Changing a price needs no redeploy, and if a fact isn't in the file the agent doesn't know it and escalates.
  • Application-level mail permissions clamped to a single mailbox by an Exchange Application Access Policy, rather than granting tenant-wide access. Verified both ways: the intended mailbox granted, another explicitly denied.
  • Every decision logged to SQLite with its token cost. Measured, not estimated: £0.019 for twenty messages, around £1 a month at real volume.
  • Built multi-venue from the start — a second site needs a folder and a filled-in questionnaire, not a code change.

What went wrong

  • The first version over-escalated badly. The classifier treated any mention of a room as an availability enquiry, so questions about hairdryers, breakfast and luggage went to a human. The distinction is whether they're asking if a room is free — everything else the knowledge base covers is just a question. Fixed by splitting the intent taxonomy with explicit examples.
  • Documented rather than hidden: the schedule only runs while the machine is awake. Acceptable while a human sends every draft, and a blocker that must be cleared before auto-send is ever switched on.

What the analysis found

Exporting twelve months of mail was meant to size the problem. It answered a different question: the inbox gets around 195 genuine guest threads a year, roughly four a week, already answered 80% of the time. The gain was never hours saved — it was replies going out in minutes instead of days, including at 11pm on a Sunday, and being right every time.

It also surfaced two things nobody was looking for. 21 of 150 sampled guest threads had booked and never received a confirmation email — spread evenly across six months, so a persistent fault rather than a blip, generating 14% of all guest mail. And 76 separate tour operators and travel agents had made contact in a year, a commercial channel sitting in the same pile as "do you do Sunday lunch".
Security audit

Database security audit & remediation

55 production tables locked down live

PostgreSQLRow-level securitySQL migrationsSECURITY DEFINER
Web app

Multi-company HR system

One HR system for five companies

JavaScriptSupabasePostgreSQL + RLSTOTP two-step
No charge

I’ll find the money before you pay me anything.

Send me your software subscriptions and I’ll come back with what’s replaceable and what it’s worth — free, and yours to keep either way. How it works →

Contact

Want the same done to your cost base?

Open to operations, automation and technical operations roles — and to talking with anyone running a multi-site business who suspects they're paying for software they could own instead.