Review every lead before your agent sends.
Barometer takes an email address and whatever your agent knows about the person, and returns a verdict, a 0–100 score, and the weighted reasons behind it. It is an email verifier that also checks the address belongs to the lead you think it does.
What it checks
Six passes, cheapest first. Each check stops at the first certain answer.
01
Static rules
Syntax, typos (gmial.com), disposable and relay domains, placeholders, noreply, role inboxes.
02
DNS
MX with null-MX, mail provider and security-gateway fingerprint, SPF, DMARC, domain liveness.
03
Outcome history
Bounces, deliveries, and replies reported back through the API feed every future check.
04
SMTP probe
RCPT TO on the real MX without sending mail, plus a random address to detect catch-all domains.
05
Deep evidence
Name ↔ address patterns, company domain, GitHub commit and profile emails, exact-match web search.
06
Reviewer model
When SMTP can't settle it, a model reads the evidence and adjusts the score with a one-line rationale.
Four verdicts, one score
The score starts at 50 and moves with each reason. The verdict is what your agent should do about it.
Send.
The mailbox is confirmed by the mail server or strongly evidenced by history, GitHub, or the web.
Enrich with a deep check, or route to a human.
Likely to deliver but unconfirmed: a catch-all domain, a role inbox, or thin evidence.
Drop it.
It will bounce, or it must not be mailed: disposable, placeholder, noreply, rejected, or bounced before.
Free. Retry later, or let a batch retry it for you.
Greylisted, timed out, or the server said nothing. There is no honest answer yet.
Reasons, like a code review
Every result lists the reasons that moved the score, with a stable code, a weight, and a human-readable detail. Agents branch on codes; people read the details.
| Code | Weight | Meaning |
|---|---|---|
syntax_invalid | fatal | Not a valid address |
placeholder_local / placeholder_domain | fatal | you@, firstname.lastname@, example.com, company.com |
no_reply | fatal | noreply@, mailer-daemon@, notifications@ |
disposable_domain | fatal | Throwaway providers (120k+ domains) |
domain_typo | fatal | gmial.com, acme.con — facts.suggestion holds the fix |
no_mx / null_mx | fatal | Domain cannot receive mail |
smtp_rejected | fatal | Mail server refused the mailbox |
history_bounced | fatal | A hard bounce was reported for this address |
role_account | −20 | info@, sales@, support@ — caps the verdict at risky |
smtp_catch_all | −15 | Domain accepts every address; mailbox not confirmed |
smtp_accepted | +45 (+15 on Yahoo and gateways) | Mail server accepted RCPT TO |
not_catch_all | +5 | A random address was rejected, so acceptance is meaningful |
history_replied / history_delivered | +50 / +35 | Outcomes you or others reported |
github_profile_email / github_commit_email | +35 / +30 | Address is public on GitHub or authored commits |
web_mention | +20 (+28 on own domain) | Exact address found on the public web |
name_pattern_match / mismatch | +12 / −12 | Local part vs. the lead's name |
llm_verdict | −20 … +20 | Reviewer model on ambiguous results (deep tier) |
The deep tier
A fast check costs 1 credit and covers rules, DNS, the SMTP probe, outcome history, and name and company-domain fit. A deep check costs 5 credits and adds public evidence about the person, then hands anything still ambiguous to a reviewer model that can move the score by up to 20 points and explains why in one line.
GitHub commits and profiles
An address that authored public commits or sits on a GitHub profile, linked to the login you pass, is about as strong as evidence gets.
Exact-match web mentions
We search for the address verbatim. A mention on the company's own domain counts for more than one on a random page.
Name and company fit, on every tier
jane.doe@acme.io fits Jane Doe at Acme. j.smith@ at another domain doesn't, and the score says so.
Catch-all domains, resolved
Many company domains accept mail for any address, so a mailbox check can only say “accept-all”. Most verifiers stop there. Barometer detects catch-all with a random-address probe, marks it with smtp_catch_all, and on the deep tier looks for evidence that settles it either way.
{
"verdict": "deliverable",
"score": 82,
"tier": "deep",
"reasons": [
{ "code": "smtp_catch_all", "weight": -15, "detail": "domain accepts every address" },
{ "code": "name_pattern_match", "weight": 12, "detail": "jane.doe@ matches first.last" },
{ "code": "github_commit_email", "weight": 30, "detail": "authored public commits as this address, linked to @janedoe" },
{ "code": "llm_verdict", "weight": 5, "detail": "commit history and name agree; catch-all is not a concern" }
]
}Your policy, kept separate
Deliverability is a fact about the address. Whether you want to email it is your call. Set a default policy on your account or send one per request, and Barometer returns policy.allowed and the violated rules next to the verdict, without bending the score.
- Block TLDs, domains, and local parts you never want to contact.
- Skip role inboxes, free mail, anonymous relays, and social-platform hosts.
- Refuse catch-all domains outright if your sending reputation can't absorb the risk.
"policy": {
"blockTlds": ["ru", "cn"],
"blockDomains": ["qq.com"],
"blockLocals": ["npm"],
"blockRoleAccounts": true,
"blockFreeMail": false,
"blockAnonymous": true,
"blockSocialHosts": true,
"blockCatchAll": false
}Built for agents
Barometer is an API first. Give your agent the MCP server and it can review leads, queue batches, and report outcomes on its own. Pipelines use the REST API, the Node client, or the stormgtm CLI. A plain-text summary for models lives at /llms.txt.
check_lead | Review one lead with optional context, tier, and policy. |
check_batch | Queue up to 10,000 leads; results arrive by polling or webhook. |
batch_status | Read progress and results for a batch. |
report_outcome | Tell Barometer a lead bounced, delivered, or replied. |
credits | Check the remaining balance before a large run. |
The rule we give agents
Send only when verdict == "deliverable" and policy.allowed == true. risky → enrich (tier "deep") or ask a human unknown → free; retry later or batch it after sending → POST /v1/outcomes
Setup for Claude Desktop, Cursor, and other MCP clients is in the docs.
Try it on your own leads
100 free credits, no card. Unknown results never cost anything.