Skip to content

feat(email-steward): add header heuristics before sub-agent body reads - #130

Closed
TechNickAI wants to merge 1 commit into
mainfrom
feat/email-steward-header-heuristics
Closed

feat(email-steward): add header heuristics before sub-agent body reads#130
TechNickAI wants to merge 1 commit into
mainfrom
feat/email-steward-header-heuristics

Conversation

@TechNickAI

Copy link
Copy Markdown
Owner

What

Adds a header heuristics stage to the email steward that runs before any sub-agent is spawned to read an email body.

Why

The steward currently escalates ambiguous mail straight to a sub-agent body read. Most of that mail is bulk/promotional and can be classified for free from headers we already fetched.

Heuristics-first is both cheaper and more accurate than sending everything to a model, because a header is a fact while a body read is an inference. Bulk senders self-identify via RFC headers (List-Unsubscribe, Precedence, List-Id) and campaign platforms stamp their own (X-Mailchimp, X-Sendgrid, X-HubSpot, etc.).

Safety

Two rules are stated explicitly in the doc, because this stage decides things without reading content:

  1. Include beats exclude. A VIP or keep-rule match wins over every promotional signal, so a VIP who happens to mail through a campaign platform is never filtered.
  2. Fail safe, not silent. Heuristics only route into the existing promotional handling (quarantine label / unsubscribe queue), never hard-delete. A missing or malformed header is a fall-through, not a match.

Only mail that survives every check is ambiguous enough to justify the expensive path.

Verification

Ran the logic against a live inbox before opening this:

Case Result
VIP sender (x2) important via include-precedence, protected
noreply@ service notification promotional, correctly caught with no body read
Ambiguous account-status email correctly fell through to the normal flow

That last row is the key negative test: the heuristics did not swallow the one email that genuinely warranted attention.

Credit

Design informed by the services/mailguard cascade in mypaios/mypaios (MIT).

Add a zero-cost triage stage that classifies bulk mail from RFC-level
headers before any sub-agent is spawned to read a body.

Heuristics-first is both cheaper and more accurate than sending every
ambiguous email to a model: a header is a fact, a body read is an
inference. List-Unsubscribe, Precedence, List-Id, campaign headers and
no-reply sender patterns resolve most promotional mail outright, so the
expensive path is reserved for genuinely ambiguous mail.

Two safety rules are stated explicitly:
- Include beats exclude, so a VIP mailing through a campaign platform is
  never filtered.
- Fail safe: heuristics only route to existing promotional handling,
  never hard-delete, and a missing or malformed header is a
  fall-through rather than a match.

Verified against a live inbox: VIP senders were correctly protected, a
no-reply notification was caught with no body read, and an ambiguous
account-status email correctly fell through to the normal flow.

Design informed by the mailguard cascade in mypaios/mypaios (MIT).
@TechNickAI

TechNickAI commented Aug 4, 2026

Copy link
Copy Markdown
Owner Author

Review triage

Required check "Pre-commit (linting)": green. Python tests green. Cursor Bugbot: no findings.

claude-review FAILURE is not a finding on this PR. The workflow log shows ANTHROPIC_API_KEY: resolving empty, and it exits with No buffered inline comments (zero review output). The same workflow is failing the same way on unrelated branches, so this is a repo-level missing/expired secret rather than anything in this diff. main has no branch protection, so it is not a merge gate either.

Worth fixing separately: the ANTHROPIC_API_KEY repo secret needs to be re-added so automated review actually runs on future PRs.

No code changes made in response, because there were no review findings to address.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: cca758770e

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +417 to +418
| 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 |

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Require corroboration for promotional delivery markers

For transactional mail sent through SES/Postmark/SendGrid, or account, security, and payment notices sent from a no-reply address, these checks stop at the first match and route the message to quarantine/unsubscribe without inspecting its body. These signals identify delivery infrastructure or reply behavior, not promotional intent, so a non-VIP message needing attention can be removed from the inbox; require corroborating promotional evidence or let weak matches fall through to normal triage. This AGENT is upstream-synced to live instances, so the misclassification propagates on update.

AGENTS.md reference: AGENTS.md:L46-L52

Useful? React with 👍 / 👎.

Comment on lines +413 to +414
| `Content-Type: text/calendar` or `X-Microsoft-CDO-*` | important | Real invite, never bulk |
| `List-Unsubscribe` present | promotional | Bulk sender self-identifying |

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Map heuristic verdicts to valid structured actions

When a heuristic matches, it returns important or promotional, 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 👍 / 👎.

@TechNickAI

Copy link
Copy Markdown
Owner Author

Superseded by TechNickAI/hermes-config#92. The header heuristic is now part of the Hermes-native email-steward skill, with account adapters, cron setup, isolated body reads, deterministic tests, and a safety correction from live transactional-email testing.

@TechNickAI TechNickAI closed this Aug 5, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant