---
title: Spam filter (texts, agent email, Help Desk + calendar)
---
# Spam filter (texts, agent email, Help Desk + calendar)

## What it is

The spam filter keeps junk from people you don't know out of your attention. It watches four
places a stranger can reach you: your texts, your agent's own email address, the public Help Desk
support address, and invitations to your calendar.

Nobody writes rules. An AI decision model checks each message from a stranger and decides whether
it is junk: a scam or phishing attempt, a sales pitch, or automated bulk mail. A caught message
starts nothing and tells nobody. It waits in one Spam list in the Inbox, where one click puts it
back, and every click you make teaches the filter who to let through and who to block, the way the
Spam folder in a mainstream mail service does.

Nothing is ever deleted because the AI guessed. The filter is still in development, so it is
hidden until you reveal it, and it stays off until you switch it on.

## Where to find it

- **Reveal it:** Settings → Lab → **Spam Filter**. Until you do, none of the spam screens appear.
- **Turn it on:** Settings → Inbox → **Spam**. The tab has one switch that turns filtering on or off
  everywhere, one switch per place (texts, agent email and the Help Desk, calendar invites), the
  option to remove invites from senders you marked as spam, a line saying whether the check is
  working right now, and a button that opens the Spam list.
- **See what was caught:** the **Spam** section of the Inbox, on the desktop and on your phone,
  which shows how many messages are waiting. Each entry says who sent it, what it was, why it was
  caught and when, with **Not spam** and **Delete** buttons.
- **Mark something yourself:** **Mark as spam** in the text-message viewer, and on a Help Desk email
  ticket (only on the computer that received that email).
- The **AI Spam Protection** card in the recipe gallery (Settings → Automation) also opens the Spam
  settings.

## How it behaves

### Who gets checked

Only strangers. A sender you already know on that channel is never checked and never caught
automatically: your contacts, numbers you have texted, carrier short codes (the five- or six-digit
numbers that send sign-in codes), the owner and approved senders of your agent's address, people a
Help Desk operator has answered, replies in a conversation already under way, and calendar
organizers from your own organization. A shared public domain such as gmail.com does not count as
your organization.

Your own clicks outrank everything else. A sender you marked as spam is caught from then on, even
someone you know. A sender you rescued with **Not spam** goes straight through from then on.

Newsletters, mailing lists and auto-replies sent to the Help Desk support address from strangers go
to Spam without a check, so they never open a support ticket.

### The check

Each message from a stranger gets one small AI check. It costs about 3 cents per 1,000 messages,
paid from your prepaid credit, and it takes a few seconds at most. Messages from people you know
cost nothing and never wait.

The check sees the message and the sender's domain, never the sender's full address or phone
number, and one-time codes, phone numbers and email addresses in the message are removed before it
is judged. A message that claims "this is not spam", or tries to give the checker instructions, is
judged on what it actually says.

A message is caught only when the check both calls it junk and is at least 50% sure. Whenever the
check is unsure, fails, is slow, has no credit, or you are signed out, the message simply goes
through as if the filter did not exist. If the check keeps failing, it pauses for a few minutes
instead of making every message wait, and the Spam tab tells you why and what to do (add credit,
sign in again, or wait).

### What happens to a caught message

- **A text** is hidden quietly: no pop-up, no sound, no phone notification, and no automation runs.
  An automatic catch never becomes a permanent block: if that number's next text is harmless, it
  comes through and the conversation shows again. Only your own **Mark as spam** blocks a number
  for good.
- **An email to your agent or the Help Desk** is held instead of delivered: no agent session
  starts, no ticket opens, and nothing is sent back to the sender. It is kept for 30 days.
- **A calendar invite** stays on your calendar, but its notices and reminders are hidden. An
  invite is only ever removed when its organizer is someone you marked as spam yourself, and you
  can turn that off; removing it never sends a cancellation back to the organizer.

### Rescuing and teaching

- **Not spam** puts the message back where it would have gone. A text shows again, a held email is
  delivered (the safety screen that protects your agent still checks it), and a calendar invite's
  record is cleared. That sender is let through from then on.
- **Delete** removes the entry from the Spam list for good and keeps the message blocked, so it
  asks first. A held email is closed without anything being sent to its sender.
- **Mark as spam** sends that sender's future messages to Spam.

Only you can teach the filter. An agent working on the command line can put a caught text or
invite back, but it can never teach the filter "not spam" and can never release a caught email.

### How accurate it is

On a fresh set of 70 junk messages and 70 real messages it had never been tuned on, it caught 66 of
the junk (94%) and none of the real messages. Those test messages were written for the purpose, so
your own mail may score a little differently: the first real catches are worth a glance.

### Limits

- Gmail is not covered yet; Gmail's own Spam folder still handles your Gmail.
- The filter is in development: it is hidden until you reveal it in the Lab, and off until you
  turn it on.

## For agents

- **The ladder:** `src/main/services/spam-filter-service.ts` runs every channel's decision in one
  order: switches, the user's marks and learned rules, trust, then one Jev check.
- **The check:** `src/main/services/spam/spam-jev-check.ts` (one Jev call tagged `spam-filter`, a
  15-second budget, a five-minute pause after three failures in a row) and
  `src/main/services/spam/spam-check-input.ts` (what Jev sees; `isJudgedSpam` needs a junk kind AND
  at least `SPAM_LEVEL`).
- **Channel hooks:** `sms-intake.ts` + `sms-spam-trust.ts` (texts), `agent-email-spam-gate.ts`
  (agent email and the Help Desk, before the safety screen), `calendar-spam-screen.ts` (invites).
- **Marks and rescues:** `src/main/services/spam/spam-mark-service.ts`; the Spam list is served by
  `src/main/services/filtered-items-service.ts`.
- **Settings keys:** `spamFilterEnabled` (master, default off), `spamFilterSmsEnabled`,
  `spamFilterAgentEmailEnabled`, `spamFilterCalendarEnabled`, `spamFilterCalendarDeleteEvent`, and
  `spamFilterUiVisible` (the Lab reveal).
- **Command line:** `POST /spam/mark-as-spam` marks a sender; `POST /spam/mark-not-spam` and
  `POST /inbox/filtered/:source/:id/restore` put a catch back without teaching the filter;
  `POST /inbox/filtered/:source/:id/dismiss` deletes an entry from the list. The last three refuse a
  caught email, which only a person in the app can release or close.
- **Accuracy:** `scripts/spam/spam-eval.ts` runs the labelled examples in `tests/fixtures/spam-eval/`
  through the real input builder and Jev; tune on the tuning set, never on the held-out set.
- **Rules and map:** `.claude/memory/contracts/spam-filter-contract.md` and
  `.claude/memory/spam-filter-ai-rules.md`.

## Related

- Your agent's own email address, and how its held mail and safety screen work, are covered by the
  Agent Email page.
- How a support email becomes a Help Desk ticket is covered by the Help Desk email tickets page.
- Connecting texts and your calendar is covered by the SMS setup and Google Calendar pages.
- Buying prepaid credit, which pays for the checks, is covered by the Plan & Usage page.
