Work, 04 of 06

Prospecting Agent

Research and qualify an entire account list overnight.

Agent. In production. Built for a B2B sales team and run on more than 10,000 accounts across six markets. It saves the team about ten hours a week.

1,520 domains
anchor-point-pm.com
beacon-realty.com
blue-harbor-pm.com
brightline-pm.com
cardinal-property.com
Name and domain, nothing else
Prospecting agent
Researchsix web searches per account
Scoreagainst the written protocol
Rankwith a call note
Overnight, unattended
Ranked workbook
brightline-pm.comP1, top
cardinal-property.comP1, top
harborview-pm.comP2, qualified
juniper-pm.comP2, qualified
ironwood-property.comP3, thin
redstone-pm.comheld, conflict
oakmont-property.comhard stop
Sorted, with evidence and a call note

The problem: research by hand does not scale.

For every account a rep opens the site, checks fit and size somewhere else, hunts for something worth saying, and tiers it. Then the next one. At a few minutes each, a list of fifteen hundred accounts is weeks of selling time spent before anyone knows which accounts were worth it.

brightline-pm.com1 of 1,520
Open the sitewhat do they do
Check fit and sizesomewhere else
Find a signalsomething worth saying
Tier itthen the next one
Minutes spent so far0
At this pace, weeks for the list.

It runs overnight.

Give it company names and domains. It applies the team's written qualification protocol to every account, researches each one on the web, and appends a row to the workbook as it goes. By morning the list is done.

run_batch.py, market 031,520 domains
Processed 1,205Flagged 28Failed 4

Every account gets the same research.

A rep has time to research the few accounts that look promising. The agent runs the same pattern on all of them: several public sources, reconciled into the evidence the protocol asks for, and a reason to call.

One accountbrightline-pm.com, row 417
Company siteservices, locations
County recordsownership, unit counts
Recent newsgrowth, leadership
Job postingshiring, scale
Listing portalspresence, reputation
Size and footprint1,800 to 2,200 units, four markets
Eligibilitythird-party management, confirmed
Growth signaltwo new markets this year
Call-worthy insightnew VP of operations, hired in June
Evidence for the scorethree sources agree

The list comes back ranked.

The workbook is sorted by priority, with the bucket, the evidence, and a call note on every row. A rep opens it and starts at the top.

market_03.xlsx, 1,520 rowsAs received, alphabetical
TopQualifiedThinConflictHard stop
RowCompanyBucketPriority
1anchor-point-pm.comQualifiedP2
2beacon-realty.comHard stop
3blue-harbor-pm.comThinP3
4brightline-pm.comTopP1
5cardinal-property.comTopP1
6cedar-ridge-realty.comQualifiedP2
7coastline-pm.comConflictReview
8copperfield-pm.comHard stop
9crestview-pm.comQualifiedP2
10granite-peak-pm.comTopP1
11harborview-pm.comQualifiedP2
12ironwood-property.comThinP3
13juniper-pm.comThinP3
14lakemont-pm.comQualifiedP2
15maplewood-pm.comTopP1
16oakmont-property.comQualifiedP2
17silverleaf-pm.comConflictReview
18westfield-realty.comQualifiedP2
Row 1, expandedResearch complete
Companybrightline-pm.com
ParentCordell Property Group
Portfolio1,800 to 2,200 units
ModelThird-party management, four markets
SourcesCompany site, county records, recent news
Call noteNew VP of operations hired in June. Open with the two-market expansion.

The winA fully prospected market, and the context to tailor outreach account by account.

The market becomes a number.

Before the run, every row in the list counted as addressable. After it, the team knows how many accounts are actually workable, and can plan coverage, quotas, and hiring against that number instead of the row count.

The raw listevery row counted as addressable
1,520assumed
The qualified marketscored against the written protocol
550workable
Top 9%Qualified 27%Thin 18%Conflict 8%Hard stop 38%

How it's built

The same engine has run six markets. Change the qualification rules and the research sources and it prospects a different industry without a rebuild.

LanguagePython.
Input and outputpandas reads the list, openpyxl writes the workbook.
Concurrencyasyncio, throttled to three accounts at a time by a semaphore, under the API rate limit on purpose.
ResearchAn LLM with a web search tool. It chooses its own searches within a hard cap of six per account.

Decisions

  • Idempotent by domain. Completed domains are read from the workbook at startup and skipped, so a run is safe across kills, restarts, and appended input.
  • Crash-safe writes. The workbook is opened, appended, and saved on every row. Deliberately I/O-heavy: a crash at any moment leaves a valid file and costs one account.
  • Defensive parsing. JSON is pulled from the model's response with a brace-matching regex rather than trusting clean output. A missing priority is derived from a fixed bucket-to-priority map.
  • Failures logged, not retried. Failed rows go to a failures file and are reprocessed on the next run, because they never reached the output.