Why probability bands beat a label
A filter that answers "phishing" or "not phishing" offers two options: deliver or drop. In practice the interesting cases sit between them — a supplier invoice whose domain is one character off, or a password-reset mail with a shortened link.
A probability lets you split the outcomes:
- High: quarantine and notify the recipient.
- Middle: deliver with a banner, or hold for review.
- Low: deliver normally, and count it as negative evidence for the next threshold pass.
Question shape
tsimport { booleanQuestion, choice } from '@system-one-ai/core';
export const mailQuestions = {
credentialRisk: booleanQuestion(
'Does this message try to obtain credentials or payment through a link or attachment?',
),
handling: choice('What should happen to this message?', {
deliver: 'Deliver as normal',
warn: 'Deliver with a warning to the recipient',
quarantine: 'Quarantine and notify the recipient',
review: 'Send to the security team',
}),
};
Pass the sender, subject, body text and link hosts as state. Strip scripting and remote images first: the model reads text, and you do not want a remote fetch triggered by triage.
Routing on the numbers
tsexport async function triageMail(client, message: { from: string; subject: string; body: string; links: string[] }) {
const result = await client.evaluate({
state: message,
questions: mailQuestions,
});
const p = result.answers.credentialRisk.probability;
// Placeholder bands; calibrate against your own labelled mailbox sample
if (p >= 0.85) return 'quarantine';
if (p >= 0.5) return 'review';
if (p >= 0.25) return 'warn';
return 'deliver';
}
Illustrative code, not tested.
What it will not catch
- Attachments it cannot read. Jev reads text and JSON; a scanned PDF or a macro-enabled document is invisible to it. Extract text first, or use a model that reads images.
- Lookalike domains, unless the sender domain is in the state you send. Include the domain and link hosts explicitly.
- A compromised legitimate account. Wording can be normal because a real person wrote it.
Send the fields that matter and keep the question narrow. For the general pattern, see agent guardrails.
Cost
Every 4KB is one block, and anything smaller still counts as one block. Cost = blocks × questions × the model rate. A short email is one block, so a two-question request on Jev costs 2 credits.
New accounts start with 100 credits, and credits never expire. See pricing.
Run the phishing sample (sign-in required) to see the same questions on sample data.