Marketing

Openers From a Sparse Prospect Row: Rules for the Model

Antonio Evans8 min read

A split scene of a spreadsheet row: on the left, cells with missing values (company size, industry) shown as question marks; on the right, a generated opener with a red flag icon and a blank field.
Key points

Key points

  1. 1A model may fill a missing field only when it follows logically from other fields present in the same row, and must leave everything else blank.
  2. 2Names, job titles and company details are never inferred, because a plausible guess there reaches a real inbox as a false claim.
  3. 3A row needs at least two independent, verifiable data points before it can support a credible opener; below that, mark it unsupported and skip it.
  4. 4Contradictions between fields should stop generation and send the row to a human review queue, not to the creative model.

The failure mode you are trying to avoid

Most guidance on cold email openers assumes the data is good. The advice is to reference a specific, verifiable detail: a funding round, a product launch, a role change, a quoted post (Fundraise Insider). A single personalization element, cited to a source, is what separates a real email from a template (Leadhaste). Sales teams are told to use timely signals and to preview every personalization block against real data before sending (Outreach).

That advice breaks the moment the source row is thin. A sparse row is not a small problem. B2B contact data decays at an estimated 25 to 35 percent annually as people change jobs and companies restructure, according to Cleanlist's research as cited by Salesgenie. Poor data quality costs the average organization $12.9 million a year per Gartner, and Validity's CRM data study found 37 percent of CRM users lost revenue directly because of bad data, as summarized by Martal. Some of those rows will be stale, some will be half empty, and some will contradict themselves.

A model asked to "write a personalized opener" will do exactly that, even from a nearly empty row. It completes the missing parts with language that sounds researched. The prospect reads a confident claim about their company that happens to be wrong, and the sender never learns why the reply never came. The rules below are how you stop that without hand-screening every row.

A field-by-field decision table

The central rule is simple: inference is allowed only for fields that are logically derivable from other present fields, and only under explicit conditions. Everything else stays blank.

FieldMay the model infer it?ConditionIf condition fails
CountryYesA valid city is present and maps to exactly one countryLeave blank
Region or stateYesA valid city plus country is present and the mapping is unambiguousLeave blank
Company domainYesLegal company name is present and matches one verified domainLeave blank
Company industryConditionalAn explicit industry code or a source URL stating the industry is presentLeave blank
Time zoneYesCountry is present and the country has a single time zoneLeave blank
Greeting nameNoUse the name exactly as stored, or omit the greetingOmit the greeting
Person's first or last nameNoNever guess or expand an initialLeave blank
Job titleNoCopy only if present and assigned to this personLeave blank
SeniorityNoMust be derived from a present, explicit title by a fixed mappingLeave blank
Company sizeNoCopy only from a cited sourceLeave blank
Funding eventNoCopy only with amount, date and sourceLeave blank
Email addressNoUse exactly what passed verificationFlag the row

Two engineering points hide in that table. First, a mapping is not a guess. City to country works because a gazetteer resolves it deterministically, not because the model has a hunch. Second, "exactly as stored" matters: a name field containing "J." must not become "James."

A second table covers what to do when two present fields disagree, because that is where silent failures live.

SymptomExampleAction
Name and email conflictfirst_name "Dana", email "dana.smith@"Use stored name, do not expand
City and country conflictcity "Austin", country "Canada"Flag for review, no inference
Company name and domain conflictname "Northwind", domain of a different firmFlag for review
Title too generic"Manager"Do not derive seniority
Two or more independent facts absentonly a name and an emailMark unsupported

The second-to-last row is deliberate. "Manager" tells you nothing about whether this person owns budget, and a model that guesses "senior leader" turns a vague field into a confident claim. Treat titles below a minimum specificity as absent.

What counts as a verifiable data point

The threshold of two independent, verifiable points is the decision rule that most changes outcomes. Independence is the hard part. A company name and its domain are not two points, because the domain is derived from the name. A city and a country are not two points for the same reason. What you are counting is facts that could each be checked against a source without the other.

PairingCounts?Why
Company name plus a specific job titleYesTwo separate fields, separately checkable
A funding event with date plus a product launchYesTwo independent trigger events
City plus country derived from cityNoSecond is derived from the first
Name plus email on the same domainNoEmail adds no information about the company
Person's name plus company nameYesIdentity and employer are separate facts

A worked example makes the arithmetic concrete. Take a list of 1,000 rows where 620 rows carry at least two independent verifiable facts, 300 carry exactly one, and 80 carry none or contradict each other. Under the rule, 620 rows are eligible for opener generation, 300 go to an enrichment queue, and 80 go to human review. If instead you had let the model write openers for all 1,000, you would have produced 380 openers built on inference. At a plausible 5 percent reply rate on good openers, the 620 valid rows might yield about 31 replies, while the 380 manufactured rows mostly produce silence plus a small chance of a complaint about a false claim. The manufactured openers do not just fail, they burn sender reputation.

That calibration matters because reply rates on cold email are low even with good data. Hunter's outreach data puts the average reply rate at 4.1 percent, cited by Mailtrap. Small gains from killing bad openers are worth more than they look, because every bad send also risks the deliverability of the good ones.

Writing the rules as a system prompt

The rules only work if the model sees them in a form it cannot quietly reinterpret. System prompts carry more weight than user instructions because they persist across the whole session and define boundaries, including required formats and prohibited behavior (Tetrate). Long contexts are a known problem: models lose format instructions issued thousands of tokens earlier, and repeating the critical rules immediately before generation restores compliance (the Medium write-up on stable output format). Clear separators and explicit expected outputs reduce ambiguity further (Ubiai).

The practical consequence is a three-part structure: rules at the top, the row in the middle, the non-negotiable output contract at the bottom.

SYSTEM
You write one-sentence cold email openers from a single prospect row.
You may infer a field only if it is logically derivable from other fields
present in the row, and only when the derivation is unambiguous.
Never infer or complete a person's name, a job title, a company name,
a funding amount, a headcount or a claim that the row does not contain.
If a field needed for the opener is absent, omit it. Do not soften a gap
with vague phrasing such as "growing fast" or "industry leader".
If two fields contradict each other, return status "review".
If fewer than two independent, verifiable facts are present,
return status "unsupported" with an empty opener.

USER
Row:
  first_name: Dana
  company_name: Northwind Logistics
  title: (blank)
  city: Austin
  country: (blank)

OUTPUT CONTRACT (mandatory)
Return JSON with keys in this order: status, opener, inferred, flags.
status is one of "ok", "unsupported", "review".
inferred lists only fields you derived, each with the rule that allowed it.

Two design choices in that block earn their keep. The inferred list forces the model to show its work on every derived field, so an auditor can reject a bad rule without reading every opener. The ordered JSON keys follow the advice to put short fields first and long ones last to reduce truncation risk (Medium).

You also want a stop list of vague escape phrases. "Industry leader," "growing fast" and "your impressive work" let a model produce a sentence from nothing. Ban them in the system prompt and check for them in validation.

Worked examples: thin rows and corrected output

Three real shapes of bad row, run through the contract.

Example 1: near-empty row. The row contains only first_name: Dana and an email address. No company, no title, no city. Under the rule this is zero independent facts beyond identity, so it is unsupported.

{"status":"unsupported","opener":"","inferred":[],"flags":["fewer than two independent facts"]}

Example 2: derivable field. The row has first_name: Dana, company_name: Northwind Logistics, city: Austin, and a blank country. Two independent facts are present (name and company), and city to country is a legal derivation.

{"status":"ok","opener":"Dana, I work with logistics teams in Austin on route planning and wanted to ask how Northwind handles peak-season scheduling.","inferred":["country=United States from city=Austin"],"flags":[]}

Note what the opener does not say. It does not claim a title, a headcount or a growth trajectory. The one specific hook, the city, came from a deterministic mapping and is disclosed in inferred.

Example 3: contradiction. The row has company_name: Northwind Logistics and a domain belonging to a different firm. That is a review row.

{"status":"review","opener":"","inferred":[],"flags":["company_name and domain disagree"]}

The corrected output for exaxmple 3 is nothing to send. That is the point. The system's job is to stop the row before it becomes a claim about a third party. Sources on data enrichment draw the same line: enrichment adds verified detail from ranked sources, while cleansing fixes what is already there, and the two are routinely confused (Salesmotion). Guessing inside the opener is neither.

A validation checklist before anything ships

Rules in a prompt drift. Add a check between generation and sending. Every item below can be automated.

  • status is ok before an opener enters the send queue.
  • inferred contains no protected fields (name, title, company name, size, funding).
  • Every inferred entry names the rule that produced it.
  • Opener contains no stop-list phrase such as "growing fast" or "industry leader."
  • Opener contains at least one token drawn from the row verbatim, so it cannot have come from general knowledge.
  • flags is empty for every row that will send.
  • Review rows are counted and routed to a person, not deleted.
  • A monthly sample of 50 sent openers is read against the original row and a live source.

The last item is not optional housekeeping. Because 25 to 35 percent of contact data decays each year (Salesgenie), a rule set that passed in one quarter will meet different rows in the next. The sample catches rule drift and source drift at the same time.

Where enrichment ends and the model begins

There is a real temptation to let the model fix thin rows by writing around the gap, and a related temptation to let a larger pipeline "figure out" the missing fields. Both blur a clean division of labor. Enrichment is the job of adding verified, sourced detail from external data, and it should run continuously rather than as an annual cleanup (Martal). Opener writing is the job of turning two or three verified facts into one specific sentence.

Keep them separate and each becomes measurable. The enrichment queue has a size and a fill rate. The review queue has a size and a cause breakdown. The opener pipeline has a count of rows that passed. When a row cannot support a credible opener, that is a data problem for the enrichment queue, not a creative problem for the model.

If you would rather hand the honest version of this workflow to someone else, Quanta Experts builds the rules, the prompt contract and the validation checks against your own data. If you are wiring the model calls yourself, Quanta Inference reaches text models through one OpenAI-compatible API key, which suits a per-row classification step that must run cheaply across a large list.

FAQ

FAQ

What should the model do when a prospect row has only a name and an email?

Mark it unsupported and produce no opener. A name and an email do not give you two independent, verifiable facts about the person's work, because the email adds nothing checkable. The row belongs in an enrichment queue, not in the send queue.

Is it acceptable to infer a job title from an email signature or a domain?

No. Copy a title only when it is present and assigned to that person in the row. Inferring seniority invites a false claim about someone's role, and the recipient is the one person guaranteed to notice the error.

How do I handle two fields that contradict each other, such as a city and a country?

Stop generation and return a review status with the conflicting fields named. Contradictions usually mean two sources were merged badly, and a model given contradictory inputs will pick one at random. A person should resolve the row before any opener is written.

Does a longer system prompt make the model more reliable at following these rules?

Not by itself. Models lose instructions buried deep in long contexts, so repeat the critical rules and the output contract immediately before generation, and keep the format simple and single. Then verify compliance with an automated check rather than trusting the prompt.

What should happen to review and unsupported rows after they are flagged?

Route them, do not delete them. Unsupported rows go to enrichment, where verified detail can be added from ranked sources. Review rows go to a person who can check the contradiction against a primary source and correct the record.

Sources

Sources

  1. The Best Cold Email Opening Lines That Actually Get ...
  2. Best Cold Email Opening Lines That Get Replies Every Time
  3. Personalization Agent for Sequence Call Tasks
  4. 11 Best B2B Data Enrichment Tools & Software in 2026
  5. B2B Data Enrichment: Tools, AI & Strategy for 2026
  6. Cold Email Personalization: How to Do It Right 2026
  7. System Prompts: Design Patterns and Best Practices
  8. Prompt Engineering: Stable output format in long contexts
  9. Ensuring Consistent LLM Outputs Using Structured Prompts
  10. B2B Data Enrichment: Better Data, Better Pipeline
About the author

About the author

Antonio Evans
Antonio Evans

Antonio Evans is the founder of Quanta Intelligence and a fractional CTO who builds HIPAA-ready AI systems for health and life-science companies. Before that he was technical co-founder of FriendsEAT for twenty years, CEO of Socialdraft, and a data engineer at IBM. Antonio lives with his dog Santino in Lisbon, Portugal.

All articles