Every email gets exactly one label.

One prompt-cached call sorts each inbound email into 12 labels; the ones that matter fan out into the Job Apps pipeline.

12 labels · 1 per email7 job-app sublabels1 LLM call per email0 replies sent by machine

01 / FIG. 3The sorter

ribbon width = share of mail · numbers = label precedence
TriagerONE CALL PER EMAILGMAIL · PUB/SUB · SONNETNotifications 1022%News → briefs 1118%Marketing 1216%Job Apps → pipeline 0411%Finance 028%Purchases 077%People 036%Security 014%Networking 053%Medical 062%Home 092%Returns 081%⚠ FLAGGED — ADDITIVE OVERLAYONLY WHEN ACTION IS REQUIRED

ILLUSTRATIVE SHARES · PRECEDENCE (01–12) DECIDES EDGE CASES — SECURITY ALWAYS BEATS MARKETING · MESSAGE_ID DEDUPS REPLAYS

02The Job Apps pipeline

langgraph · opus · fired by dispatch

Dispatch → Notion

5 stages
DispatchBEARER POST FROM TRIAGER
ClassifyONE OF 7 SUBLABELS
SublabelAPPLIED IN GMAIL
MatchCASCADE → NOTION ROW
Status ↑NEVER BACKWARD
OfferInterview SchedulingAssessmentRecruiter OutreachStatus UpdateApplication ConfirmationRejection

The match cascade

never guesses
Posting URLEXACT MATCH
no match ↓
Company + roleVERIFIED AGAINST THE ROW
still ambiguous ↓
⚠ Human reviewNEVER WRITES TO A GUESSED ROW

03 / FIG. 4The one-way line

status is monotonic · terminal stations are read-only
SavedAppliedScreenInterviewOfferONE WAY — AN EMAIL NEVER MOVES A ROW LEFTREJECTEDWITHDRAWNARCHIVEDTERMINAL — READ-ONLY

Labeled, matched, advanced — never sent.

The job search runs itself in Notion; the replies stay yours.

briefs →read the code ↗