---
title: "What an AI sales agent must know before acting"
url: "https://lookvalid.com/blog/industry/ai-sdr-data-quality.md"
canonical_url: "https://lookvalid.com/blog/industry/ai-sdr-data-quality"
last_updated: "2026-10-22"
type: "conceptual"
summary: "Gate every step of an AI sales agent on lookup results: domain mail setup, role mailboxes, disposable domains and phone number type, with working code."
related: ["https://lookvalid.com/products/email-domain-check.md", "https://lookvalid.com/products/phone.md", "https://lookvalid.com/docs/mcp.md", "https://lookvalid.com/docs/quickstart.md", "https://lookvalid.com/glossary/role-account.md"]
---

# What an AI sales agent must know before acting

Gate every step of an AI sales agent on lookup results: domain mail setup, role mailboxes, disposable domains and phone number type, with working code.

An AI sales agent will happily write a perfect email to an address that cannot receive it, or queue a call to a number that does not exist. The fix is not a smarter model but a cheap check in front of each action. This post shows which contact signals matter, what our lookups return for them, and how to turn them into a gate your agent cannot skip.

## Check the domain before you write the message

The cheapest failure to prevent is mail to a domain that accepts none. A domain can publish a null MX record, a single MX with preference 0 and a lone dot as the exchange, to say it takes no mail. A domain that publishes it must not publish any other MX record [1]. Without an MX record at all, senders fall back to the domain address records and keep retrying for about a week before giving up [1]. An agent that writes and schedules a message to such a domain spends tokens and sender reputation for nothing.

Our [email domain check](https://lookvalid.com/products/email-domain-check.md) reads public DNS for the domain behind an address. It reports MX records, a null MX flag, an implicit MX flag for the address record fallback, the SPF and DMARC records it finds, whether the domain is a known disposable provider or a free mailbox provider, and whether the local part is a role mailbox. It never opens a connection to the mail server, so the field smtp_checked is always false and a good result does not prove that a particular mailbox exists.

Role mailboxes are worth separating from people. RFC 2142 lists the conventional names: info, marketing, sales and support for business functions, abuse, noc and security for network operations, and postmaster, hostmaster and webmaster for services [2]. A message to one of them reaches a shared queue, so an agent that writes as if to a named person should route it differently or skip it.

## Check the number before you queue the call

The [phone lookup](https://lookvalid.com/products/phone.md) parses a number against the numbering plan and returns the E.164 form, national and international formatting, the country, an area code region for North American numbers and a number type such as mobile, fixed line, voip or toll free. The type comes from libphonenumber metadata, which assigns a type whenever feasible and distinguishes fixed line, mobile, toll free, premium rate, shared cost, VoIP and others [3]. Its own documentation separates a quick length check from full validation using length and prefix information [3].

This check is about the numbering plan only. It does not contact a carrier, so it cannot say that a number is switched on, ported or reachable, and the response says so in a notes field. Use it to reject numbers that cannot exist and to pick the right channel, not to promise delivery.

## Turn signals into gates

A gating table for an outbound agent

| Signal | Value | What the agent does next |
| --- | --- | --- |
| deliverability_signal | undeliverable | Stop. Do not write or send. Mark the contact for new data. |
| deliverability_signal | risky | Hold for a person to review before any send. |
| disposable | true | Skip the address. Look for another contact at the account. |
| role_account | true | Send only a role-appropriate message or route to the account team. |
| spf.valid | false | Log it. A domain can have only one SPF record, and more than one is an error [4]. |
| Phone lookup | not found | Do not dial. The number does not fit the numbering plan. |
| number_type | mobile or fixed_line | Choose the channel that matches the type. |
| number_type | toll_free, premium_rate or voip | Hold for review. These types rarely reach a named person. |

Two requests give the agent both signals. The bodies below are the ones the API accepts; each costs one call and each returns a small JSON record the gate can read.

Check the domain behind an address

```bash
curl -X POST https://YOUR_API_HOST/v1/email-domain-check \
  -H "Authorization: Bearer $LOOKVALID_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"email":"sales@example.com"}'
```

Check a phone number against the numbering plan

```bash
curl -X POST https://YOUR_API_HOST/v1/phone \
  -H "Authorization: Bearer $LOOKVALID_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"phone":"+14155552671"}'
```

The function below takes the data object from each reply and returns one decision. Keep it in code, not in the prompt, so the model cannot talk its way past it.

A gate that reads both results

```ts
type EmailData = { deliverability_signal: 'good' | 'risky' | 'undeliverable'; disposable: boolean; role_account: boolean | null };
type PhoneData = { number_type: string } | null; // null when the lookup found no valid number

export function nextStep(email: EmailData, phone: PhoneData): 'send' | 'review' | 'skip' {
  if (email.deliverability_signal === 'undeliverable' || email.disposable) return 'skip';
  if (email.deliverability_signal === 'risky' || email.role_account) return 'review';
  if (phone && ['toll_free', 'premium_rate', 'voip'].includes(phone.number_type)) return 'review';
  return 'send';
}
```

## Put the checks where the agent can call them

- Call the domain check when a contact enters your system, and again before a sequence starts, since DNS changes.
- Call the phone lookup once, store the E.164 value, and reuse it.
- Log every gate decision with the field that caused it, so you can explain a skipped contact later.

The same lookups are available to AI clients as tools over [MCP](https://lookvalid.com/docs/mcp.md), which suits an agent that decides for itself when to check. Start with the [quickstart](https://lookvalid.com/docs/quickstart.md), then add the [email domain check](https://lookvalid.com/products/email-domain-check.md) in front of your first send.

## Sources

1. [RFC 7505: A "Null MX" No Service Resource Record for Domains That Accept No Mail](https://www.rfc-editor.org/rfc/rfc7505), read 2026-10-19
2. [RFC 2142: Mailbox Names for Common Services, Roles and Functions](https://www.rfc-editor.org/rfc/rfc2142), read 2026-10-19
3. [libphonenumber: the Google library and metadata behind phone number types](https://github.com/google/libphonenumber), read 2026-10-19
4. [RFC 7208: Sender Policy Framework (SPF)](https://www.rfc-editor.org/rfc/rfc7208), read 2026-10-19

By LookValid data team. Published 2026-10-19, updated 2026-10-19.

## Related

- [Email Domain Check API](https://lookvalid.com/products/email-domain-check.md)
- [Phone Numbering-Plan Validation API](https://lookvalid.com/products/phone.md)
- [MCP server](https://lookvalid.com/docs/mcp.md)
- [Quickstart](https://lookvalid.com/docs/quickstart.md)
- [What is Role account?](https://lookvalid.com/glossary/role-account.md)
