Inbox triage and reply drafter for a cleaning company
Two hours a night of customer mail, answered from memory. Now the inbox sorts itself, drafts the routine replies on the thread and keeps the follow-ups. The owner still presses send.
Click through the dashboard for the demo inbox: all 25 sorted messages, every draft, the follow-up ledger and both digests. It is a static copy, so nothing you click is sent.
Open the demo dashboardProblem
The owner of a small residential cleaning company (two crews, about ninety recurring families) is the office after hours. When her part-time office manager dropped to eight hours a week, every reschedule, quote request, reminder reply and invoice question landed on the owner's phone, and she answers them at the kitchen table from 7 to 9pm. Her words on the discovery call: "it's not the texts, it's the remembering." Nothing is tracked, so the quote that was never sent, the canceled visit that was never rebooked and the family nobody reminded all fall through. Her own numbers: about two hours a night, about three wasted crew trips a month (two cleaners paid for a morning, plus the drive), one or two recurring families lost a quarter to a visit that was never rebooked, and one lost quote that "stung". The demo business here is fictional (Harbor Home Cleaning, Alexandria, VA); the pattern and the numbers are from the call.

Before
Open the inbox at 7pm. Read each message, work out what it is about and which family it is from, open the calendar to check the day, type the reply, then try to remember the follow-up: move the visit, tell the crew, send the quote, resend the receipt. Vendor mail and cold pitches get read along with everything else. Anything she does not get to tonight is gone by tomorrow unless she wrote it on paper. The two hours are mostly re-reading and re-deciding the same five kinds of message.
What I built
The owner asked for "an AI that answers the texts". That is the wrong build for a business where a wrong day, a wrong price or a wrong tone costs a customer. The constraint I set with her: the system may read everything and write anything, but it may send nothing, promise no day it has not checked, and state no price that is not in a file she controls. Every rule it follows has to be in plain English she can edit. Inside that constraint the whole inbox is fair game.
- Trigger: a new message in the business Gmail under one label (the rest of the mailbox is never touched), or a 25-message fixture that replays identically for the demo.
- Classify: Claude reads the message against a rubric the owner wrote in plain English (seven categories, three flags) plus her customer list, and returns a structured record: category, flags, who it is, which visit, which date they want, amount and invoice number, anything the crew needs to know, and a one-line summary.
- Route: code decides, not the model. Angry, unclear, disputes and anything it cannot place go to a "needs you" queue with the reason and no draft. Vendor mail is filed. Reschedules and reminder replies get a deterministic draft from her own templates, with a lookup in the schedule so the draft can only offer a day that is actually open. Quote requests and payment questions get an AI draft in her voice that may only state facts from her FAQ file; a checker rejects any draft with an amount that is not in the FAQ, more than six sentences, or more than one question.
- Draft: the reply lands as a Gmail draft on the customer's thread. There is no send path for customer mail anywhere in the code. She reads, edits if she wants, and presses send.
- Remember: every message that implies a next step writes a follow-up to a ledger with a due date ("move the Patels to Friday and tell Team Blue", "send Jessica the written quote within 24 hours", "pass the new gate code to the crew"). It stays open until she closes it.
- Report: a one-page dashboard (needs you, drafted, filed, the ledger) and a 7am and 5pm digest email: what came in, what was drafted, what needs her, what is still open from yesterday.
What stays human: every send, every upset customer, every disagreement about money, every price outside the FAQ ranges, and the rubric itself. When she edits the rubric, the affected messages re-run; nothing else changes.
Demo
On a call I open the dashboard and press "Replay the demo inbox". The 25 messages of a fictional Tuesday sort themselves in a few seconds: 16 get a draft, 4 land in needs-you with the reason ("disagrees about money", "sounds upset", "can't tell what they need"), 5 are filed, and 21 follow-ups hit the ledger with due dates. I open the Gmail account next to it: the same 25 threads sit under the demo label, each with its category label and its draft reply on the thread. Then I send a message from my phone to the demo address, and it arrives on the dashboard classified, with a draft on the thread, inside five minutes. The 5pm digest for that day is one click from the header.
Result
Labeled projected for the owner's time, measured for the system's accuracy.
owner hours saved per week = hours per night in the inbox x nights per week, minus review time
With her inputs: 2 hours x 6 nights = 12 hours a week, against about 20 minutes a day reading drafts and closing follow-ups. Roughly 10 hours a week back. At $50 an hour of owner time that is about $500 a week, or $2,000 a month, which is the part-time office hire she was not making.
trips saved per month = lockouts per month x (2 cleaners x paid hours + drive)
Her stated three wasted trips a month come from reminders and reschedules that never got written down. The ledger and the digest turn "what did I forget" into a number on the screen every morning. Measuring this one needs her calendar and Square history for a month before and a month after, which is the first thing a paying engagement would set up.
Measured on the 25-message fixture, in three fresh trials: 75 of 75 messages classified, routed and
fact-extracted correctly; 0 violations of the never-rules (no draft for a needs-you message, no day
offered that is full or closed, no amount outside the FAQ); 45 of 48 drafts judged sendable with at
most one edit by a stronger model used as the judge; about $0.004 per message. The three misses were
one style point (a date written without its weekday). Full table in EVAL-RESULTS.md.
Stack
Python, FastAPI, SQLite. Claude Sonnet 5.5 for classification (structured outputs against the rubric, prompt caching on the rubric, style and FAQ files) and for the AI drafts; Claude Fable 5.1 as the eval judge. Gmail API with OAuth on one label: drafts on the thread, labels per category, the digest as the only outbound mail. Docker on an Ubuntu home server, cron for the five-minute poll and the two digests. Build time: one day for the fixture, pipeline, dashboard, digest and eval, plus about 25 minutes of the owner's clicking for the Google OAuth setup. The eval found the two real bugs: a rubric gap (a customer saying "we'll be out, key under the mat" is confirming the visit, not cancelling it) and the AI drafts breaking her style rules in six ways on the first run. Both became one line each in a file she can read.
Next
A paying version swaps the schedule file for Google Calendar and the invoicing tool (Square or Jobber), puts the SMS line next to email through the same classifier, sends the day-before reminders itself from the calendar (the highest-scoring item in her audit), and learns from her edits: every draft she changes before sending becomes an example for the next one.