Skip to content
← Processes

Outreach based on government data

Every candidate's website is verified before a credit is spent, tiered by signal strength, then written one grounded opener that is checked for repetition.

Building a cold list by hand usually means one search per city or category, stopping at the first page of results, and sending the same note to everyone regardless of fit. A registry pull can hand over thousands of names in an afternoon — the volume was never the hard part. Knowing which few hundred are actually worth an email, and writing to each one like it was the only one, is.

Public company registries already hold the universe. Web search and an enrichment waterfall already resolve who to write to. The work that's actually hard to automate well is the discipline in between: verifying before spending, tiering by real evidence instead of a guess, and catching the moment a hundred true, personal lines start reading as one template.

What you get

A staged, two-track outbound campaign in which every message is personalized from real evidence, verified before it goes out, and handed to a person to launch.

The part worth getting right

A pulled list is not a qualified list. Registry data alone gets the sector and size band wrong often enough that skipping the website-verification gate turns every later step — enrichment, opener writing, sending — into wasted work on the wrong company. Verifying first is what keeps every downstream dollar spent on a real candidate.

Tiering by evidence, not by segment, is what keeps every opener honest. A company with a real hiring signal or a system fingerprint gets an opener that names it; a company with neither still gets a real line, pulled from its own site — never a default sentence recycled across the tier, because a reader can tell the difference between a fact and a placeholder.

The mechanical check on the full batch is the part that's easy to skip and expensive to skip. Six individually true, individually specific lines can still all lean on the same rhetorical move — a colon, a closing phrase, a sentence shape — and read as automated the moment they're seen together. Counting frame and phrase repetition across the batch, not eyeballing it, is what a naive version misses every time.

The prompt

The real prompt behind the steps above — detailed enough that an agent with a people-search tool, email/phone enrichment, and CRM access can run it as written.

# Build a cold outbound list from public company data

You have access to an official company registry, web search, and an
email-enrichment tool. Run this for **[your target company profile: size,
sector, and company age]**.

## 0. Set up (skip if you're already connected)

If you don't already have live tool access for this, connect it first
— this prompt is only as real as the tools behind it:

1. Create a free account at app.tulina.ai.
2. Add Tulina's MCP server to your assistant: https://mcp.tulina.ai/mcp
3. In Tulina, connect your own API keys for the tools this prompt uses —
   company registry search, web search, and email enrichment.

Once connected, your assistant has real tool access and the rest of this
prompt runs as written. If you also have a job-postings/technology-stack
signal source connected, step 3 gets stronger; the prompt works without it.

## 0b. Already on Tulina? Three things around the run

An account and the MCP server are not the whole setup. Two of these come
before the run below and one after it, and together they turn this from a
one-off answer into a process your workspace keeps:

1. **Activate this process's connectors first.** Call
   `oto_connector(op="list")`, match it against the tools named in step 3
   above, and `oto_connector(op="select", name="...")` every one that
   isn't active yet. Selecting a connector does not mount its tools in the
   conversation you're already in — reach them through `oto_call` for this
   run, or open a fresh conversation once they're all on.
2. **Attach the work to an existing project.** `oto_project(op="list")`
   shows your active org's projects: pick the one this work belongs to
   rather than opening another, and keep its id. The project is where this
   process, the tables it writes to and the connectors it uses hang
   together.
3. **When the run is done, save it as a process — with its graph.** Write
   the body with `oto_procedure(op="set", ...)`, then attach it with
   `oto_project(op="link", project_id=..., target_type="procedure",
   target_ref="<your slug>")`. The body has to carry a drawing: read
   `oto_guide(op="read", slug="procedure-flowchart")` and follow it
   exactly — ONE untagged fenced block in that grammar, opening with the
   trigger and a quoted example of what you'd type to start a run. Tulina
   parses that drawing back into the graph it renders as the process's
   default view, which is what makes it come out in the same style as
   every other process in the app; a drawing the grammar can't read falls
   back to raw characters instead. Saving a process needs org-admin
   rights — without them, hand the finished body to someone who has them.

## 1. Build the universe from public company data

- Pull every company matching your target profile from an official
  registry — the fields that matter are sector, headcount band, and
  company age, not revenue: revenue is worth recording where a clean
  filing exists, but a company with none on file is still in scope.
- Filter to active status and the age/size bands you actually want before
  doing anything else — a first pull that's too broad is fine, a filtered
  list is what the rest of this runs against.
- Write the full list to one running table. Don't re-pull per batch.

## 2. Verify the website before spending a credit

- For each company, one search for its name plus city plus "official
  site." Registry/directory listings (business registries, review sites,
  map listings, marketplace pages) are never the answer — the real site
  is often under a brand name that differs from the legal name, and a
  generic listing snippet usually reveals it.
- Treat this as qualification, not enrichment: a row with no verified
  first-party website doesn't get an email credit spent on it. A website
  that reveals the wrong sector gets dropped, with the reason recorded —
  on a real run, roughly one in four pulled rows turns out to be the
  wrong sector, dissolved, or a subsidiary with no local buyer. Expect
  that ratio; it's not a bug in your query.
- This step is a bulk job — batch it and save results as you go, not only
  at the end. A run that only saves at the end loses everything if
  credits run out mid-batch.

## 3. Tier by the strongest signal you can find

In order of strength:

1. **A relevant open role** — anything back-office: order processing,
   billing, admin, customer service. If you have a job-postings source,
   query it by company name directly; searching job boards by keyword
   instead returns staffing agencies hiding the real employer, not the
   company itself.
2. **A known back-office system** — if you have a technology-stack
   signal source, check for it.
3. **Recent, relevant press** — an acquisition, a new location, a
   franchise deal, an investment, a generational handover. Filter hard:
   an old story, a routine mention, or a profile piece isn't a trigger.
4. **Nothing** — still gets an opener, written from the company's own
   site. This is most of the list, not a fallback case to skip.

Record which signal each row got, and the evidence itself (the posting
title, the system name, the headline) — step 5 writes from this, never
from a guess about the segment.

## 4. Resolve email in bulk

- Submit in batches of 20 through an enrichment waterfall — larger
  batches get rejected outright, and one malformed row can fail the
  whole batch, so validate names are present before submitting.
- Poll until each batch finishes rather than assuming a fixed wait.
- Expect the tool to correct the domain when the real mailbox lives
  elsewhere from the site you found.
- A miss on email that still returns a verified profile match isn't a
  dead end — route that row to a different channel instead of dropping
  it. An email on an unrelated or foreign-HQ domain is the wrong buyer;
  drop that one for real.

## 5. Write one opener per row, then check the batch for a pattern

Every row gets its own opening line, written from its own evidence —
the signal from step 3, or the company's own site for tier 4. One
sentence, two short ones at most, under 35 words, formal register, no
em dash. It states one specific fact a stranger couldn't have guessed
and turns it toward the actual daily pain in the same breath. Never
invent a fact — if nothing specific is findable, mark that row's
confidence low, and never send a low-confidence line.

**Rotate across several structural frames, so a hundred true lines don't
read as one template:**

- **Density** — a number against a headcount: *"47 accounts on file,
  4 people touching every one of them — a ratio that only tightens as
  the roster grows."*
- **History** — the company's own longevity: *"[Company] has run the
  same regional routes since 1998. The trucks got faster. The paperwork
  behind them didn't."*
- **Flow** — people and volume in motion: *"Three reps on the road, two
  people at a desk turning what they bring back into orders that
  actually ship."*
- **Event, addressed directly** — from the step-3 signal: *"You're
  hiring an ops coordinator this month. Most of that role, on paper, is
  re-entering what already arrived once."*
- **Long tail, plainly** — two flat sentences, no twist: *"[Company] has
  supplied independent retailers since 2003. A lot of small orders,
  entered by hand, one at a time."*
- **Question** — built from a fact on their own site: *"How many of your
  [N] regional accounts still order by phone or email?"*

Then run a mechanical check over the whole batch before anything moves
forward — count, don't eyeball:

| Check | Cap |
|---|---|
| Same structural frame | no more than 30% of the batch |
| Lines built on a colon pivot | 20% |
| Lines closing on the same stock phrase | 20% |
| Same opening two words, grouped | no group over 5% |
| Em dash, or over 35 words | 0 — reject and rewrite |

Rewrite the surplus into an under-used frame and re-run the check. A
batch that hasn't passed doesn't move to step 6 — this catches what
individually-true lines miss when read as a set.

## 6. Load the campaign, ready for a person to launch

- Route each row to the track matching its signal strength: rows with a
  real trigger (role, system, press) into your highest-touch track,
  everything else into your standard track.
- A simple three-touch structure holds up well: touch one leads with the
  opener and one clear value line; touch two, a few days later,
  references what the delay is now costing them and — if you have real,
  named public customers — names one and asks a different, more direct
  question; touch three, about a week later, closes the loop rather than
  pushing again, and offers to redirect to whoever else might own this.
- Before loading anything, read back what you just wrote and confirm the
  opener field actually changed per row — a write that silently fails
  ships a generic line where a personal one should be, with no visible
  symptom.
- Stage everything, then stop. The agent prepares the campaign; a person
  reviews and launches it. Never call a send/launch action yourself.

## Output

Report: how many companies pulled, how many passed the website gate,
how many landed in each signal tier, how many resolved to a usable
email or fallback channel, how many openers passed the mechanical check
on the first pass vs. needed a rewrite, and the campaign staged for
review.

Questions about this process

Yes — an agent with access to an official company registry can pull every business matching a target profile, verify each one's real website before spending any enrichment credit, and tier them by the strongest signal found.

By writing one opening line per company from real evidence, then running a mechanical check across the whole batch for repeated phrasing and structure — individually true lines can still read as one template when seen together.

Yes — a website-verification gate runs before any paid step, since roughly a quarter of any pulled registry list turns out to be the wrong sector or already gone.

No — everything is staged and verified, then the agent stops. A person reviews and launches.

Related processes

  • Build a target list from a sentence

    Describe the companies you want in one sentence, and get them sourced, scored on dated signals, enriched, deduplicated against your CRM, and staged as a campaign.

  • Find doctors and clinics

    A places census of doctors and clinics gets cross-referenced against France's practitioner registry and facility directory so nothing is missing from a city's real coverage.

  • Outreach based on Slack membership

    Membership in a Slack community is the qualification, so everyone in it is in scope, resolved by name and corroborated against their own words.

Experience Tulina for 14 days.

By continuing, you agree to our Terms of Use and Privacy policy.