-
Notifications
You must be signed in to change notification settings - Fork 12
feat(email-steward): add header heuristics before sub-agent body reads #130
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -399,6 +399,43 @@ receipt from a new vendor might need review; the 50th recurring receipt doesn't. | |
| Read full email body only when subject isn't enough. Most triage is sender + subject. | ||
| Always sanitize the body before processing — see Security section. | ||
|
|
||
| ### Header Heuristics: Decide Before You Spend | ||
|
|
||
| Run this BEFORE spawning a sub-agent or reading any body. These are RFC-level signals | ||
| that are already present in the envelope/headers you fetched, so they cost nothing. | ||
| Heuristics-first beats sending everything to a model: it is cheaper AND more accurate on | ||
| borderline bulk mail, because a header is a fact while a body read is an inference. | ||
|
|
||
| Check in this order and stop at the first match: | ||
|
|
||
| | Signal (header / sender) | Verdict | Why it is reliable | | ||
| | ---------------------------------------------------- | ----------- | -------------------------------------- | | ||
| | `Content-Type: text/calendar` or `X-Microsoft-CDO-*` | important | Real invite, never bulk | | ||
| | `List-Unsubscribe` present | promotional | Bulk sender self-identifying | | ||
| | `Precedence: bulk` / `list` / `junk` | promotional | Sender marking it as non-personal | | ||
| | `List-Id` AND no `In-Reply-To` | promotional | List broadcast, not a reply to them | | ||
| | Any campaign header (see list below) | promotional | Sent by a bulk-mail platform | | ||
| | Sender localpart matches the promo pattern below | promotional | Address is not a person who reads mail | | ||
|
Comment on lines
+417
to
+418
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
For transactional mail sent through SES/Postmark/SendGrid, or account, security, and payment notices sent from a AGENTS.md reference: AGENTS.md:L46-L52 Useful? React with 👍 / 👎. |
||
|
|
||
| Campaign headers: `X-Mailchimp`, `X-MC-User`, `X-SG-EID`, `X-Sendgrid`, `X-Mailgun`, | ||
| `X-Postmark`, `X-HubSpot`, `X-Marketo`, `X-SES-Outgoing`, `X-Campaign`. | ||
|
|
||
| Promo sender pattern (match on the localpart, case-insensitive): `no-?reply`, | ||
| `newsletter`, `marketing`, `promo(tions)?`, `offers`, `deals`. | ||
|
|
||
| Two rules that keep this safe: | ||
|
|
||
| 1. **Include beats exclude, always.** If the sender is a VIP or matches a keep rule, | ||
| that wins over every promotional signal above. A VIP who happens to mail through a | ||
| campaign platform must never be filtered. Check the keep list FIRST. | ||
| 2. **Fail safe, not silent.** A heuristic only ever routes mail to the normal | ||
| promotional handling (quarantine label / unsubscribe queue). It must never | ||
| hard-delete, and anything unmatched falls through to the existing flow unchanged. | ||
| When a header is absent or malformed, that is not a match; it is a fall-through. | ||
|
|
||
| Only mail that survives all of the above is ambiguous enough to justify a sub-agent body | ||
| read. Log which heuristic fired so the decision is auditable in the run log. | ||
|
|
||
| ### Housekeeping | ||
|
|
||
| First run each day: | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When a heuristic matches, it returns
importantorpromotional, but neither is in the required action vocabulary, and the later instruction mentions a quarantine label or unsubscribe queue without choosing an action or confidence. The runner therefore cannot satisfy the required structured decision and confidence threshold deterministically, and different agents may archive, unsubscribe, skip, or alert the same message; define an explicit valid action and confidence—or resume normal classification—for each verdict. This ambiguity is deployed because workflow AGENT files are synchronized to live instances.AGENTS.md reference: AGENTS.md:L46-L52
Useful? React with 👍 / 👎.