Two weeks, and shrinking. The build used to be
the long pole on this project; it isn't any more. What's left that genuinely takes skill is the cost
discipline, the account layer, and the timing between the two tables.
2.1 · What changed
The tables build themselves now.
Sarmad and Kaveen cracked programmatic Clay table creation. Use it — hand-building a 70-column table
from scratch is no longer the standard, it's the fallback.
1
Feed the skill three things
The customer's requirements as written by the architect in Teamwork, this playbook, and the seed IDs for the enrichments — pulled out of the browser's network calls in the target Clay account.
2
It generates the table as JSON
The whole workflow — columns, waterfalls, gates, formulas — emitted as a single importable spec.
3
Import it with the extension
One click, and the table builds. The reference case regenerated RunPod's 71-column contact table from scratch and it does exactly what the hand-built original does.
4
Map the two ends by hand
The only manual work left: the inputs from the webhook (record ID, the CRM lookup column) and the outputs back to the CRM. If you're deploying into an account that already has the CRM integration, even the field mapping comes across.
So what
Call it half the implementation time, if not
more — and understand what that does to the shape of the project. When the build compresses, the
value moves upstream into the blueprint and downstream into the pilot. Sell the thinking, not the
table.
2.2 · The craft
Eight rules that decide the bill.
These come out of all three production builds, not from theory. They're the difference between a
pipeline that costs cents per record and one that costs dollars.
1 · Free before paid
Every waterfall, no exceptions
- The value already in the CRM is rung one
- Paid providers gated on it being absent
- Portnox verifies the submitted email first — a valid work email means zero enrichment spend on that row
2 · CRM lookup before enrichment
Stage 4, always
- Check for an existing account on domain, then name
- Only spend when the ladder comes back empty
- Most inbound at an established company is already known
3 · Sequential gating
Never parallel fan-out
- Provider N+1 fires only when 1…N all returned nothing
- Parallel multiplies cost by the number of providers
- It's the single most common build mistake
4 · Candidate deduplication
Before you validate
- Carry an accumulator of already-rejected candidates
- Skip validation when a later provider returns one you've already failed
- By the eighth tier RunPod's array holds all seven prior rejects
5 · Deterministic before AI
The biggest easy win
- Keyword, name-suffix and domain-extension checks are free
- Patlytics classifies most law firms on three formula columns
- The AI column is gated off all three — it runs only on genuine ambiguity
6 · Cheapest capable model
Tier it deliberately
- Small models for classification and extraction
- Research models reserved for genuinely hard columns
- The most expensive column set to manual-only so it never auto-runs on volume
- Don't pay for web search to parse a string
7 · One company, once
The largest single saving
- Company enrichment lives in its own table
- A lookup gates the route: already enriched, don't re-enrich
- Fifty signups from one company = one company enrichment
8 · Constrain every AI column
Schema + an out
- Explicit output schema on every AI column
- Instruct it to return empty rather than guess
- Low confidence returns null across every field
- Otherwise fallback chains behave unpredictably and you can't debug the bill
2.3 · Reference waterfalls
Order them for the segment, validate every rung.
These are the live orders from the production builds — a starting point tuned by the pilot, not a
constant. One validator vendor per data type: one price point, one standard, one place
to swap it out.
Work email · 7–8 rungs, all validated
FreeCRM value→
Icypeas→Kitt→
LeadMagic→Enrow→
Findymail→Hunter→
Wiza
- Findymail validates every rung in all three builds — accepted only on a verified result.
- Every finder double-gated: skip entirely if the submitted email is already a valid work address.
- Discovered work email goes to its own field. The signup address is the identity the product knows them by — never overwrite it.
Phone · expensive, treat it as opt-in
GateHas email & no CRM phone→
Lyne → PDL → LeadMagic→
Upcell → Wiza → Findymail→
Forager → Prospeo → ContactOut
- Clearout validates every rung; accepted only on a valid status.
- Patlytics deleted the entire phone stack — six vendors — after measuring what it returned.
- Default position: an on-demand checkbox an SDR ticks per record, not a column that runs on every inbound.
LinkedIn — and the AI rung
FreeCRM value→
ReverseContact→
MixRank→
AI fallback · last rung only
The AI web-search step is always the final
fallback, never an early rung — on domain resolution too. It's the most flexible tool in the box and
the easiest one to accidentally run on every record.
2.4 · The point of the project
The account layer.
This is the step the old library entry never had, and it's what separates "we bought enrichment" from
a working inbound motion. Fields feed a scoring model. The association is what makes routing,
territory assignment and account ownership actually work.
1
Run the match ladder in cost order
Account ID first, then normalized domain, then normalized company name. Free CRM lookups sit above every paid step, so the ladder is a cost control as much as a matching mechanism.
2
Branch: update on match, create only on empty
Two gated branches, never both. Merge them into a single resolved account ID column so everything downstream reads one field regardless of which path ran.
3
Hand the ID back across tables
The company table returns the account ID to the person table through a cross-table lookup with a delay sized to the company stage. The person record has been sitting there waiting for it.
4
Write the association, gated on both IDs
Only when person ID and account ID are both present. This is the deliverable — it's what lets an AE see which account a paying user belongs to.
5
Decide the multi-candidate rule up front
What happens when a company resolves to two plausible accounts. Decide it in Blueprint and write it down — otherwise you're making the call live, on a customer's production data, at 5pm.
2.5 · Two tables, and the clock between them
The race condition you will hit.
Company enrichment is shared infrastructure, so it lives in its own table — that's
what makes "one company, once" possible. Which means two tables have to talk, and all three builds sequence
them with explicit delays rather than a scheduler: 5s, 10s, 60s, 300s, 500s, 600s. Size them against
the client's own routing timing, not a default.
- Domain is the join key. Both cross-table architectures key on company domain — normalize to a bare domain early and everything downstream matches.
- The failure looks like bad data, not a bug. Patlytics had the contact table reading company classification 1 second after the trigger, before it had been written. The fix was a 500-second delay. Nothing was broken; it was just early.
- Roughly 25 minutes end to end is normal on the Portnox build — trigger to final Lead write, all of it sequenced on delays.
- Clay's 50k row cap isn't a ceiling. Auto-delete is enabled: oldest rows drop once the table fills, on criteria you set. It runs indefinitely.
Pitfall · the first one you'll hit
Routing fires before
enrichment lands. The CRM assigns the record on creation while your pipeline is still running, so
routing reads empty fields and the enriched data arrives too late to matter.
Measure the CRM's own routing delay during discovery, then either sequence enrichment inside
that window or gate the routing rule on the enrichment completion stamp. And make sure records that fail
enrichment still route rather than stalling forever.
2.6 · Write-back governance
Don't break their data.
A rep corrects a title, your next run overwrites it, and you haven't just lost a field — you've lost their
trust in every field on the record. That's very expensive to win back.
Salesforce
removeNullValues: true — an empty result never clears a populated field
disableAutoAssignmentRules: true — the write never re-triggers assignment mid-flight
- Lead-to-account written to a lookup field (
Account__c on the Portnox build)
- Trigger built as a flow on the qualifying transition, with exclusions in the entry condition
- Enrichment status + timestamp available to routing as a condition
HubSpot
- Same governance — fill blanks only per field, CRM value first in every merge chain
- Workflow fires the webhook; two workflows if company and contact are triggered independently
- Native contact-to-company association written once both IDs resolve
- HubSpot itself can serve as the shared state store between tables — the contact table reads the company record back rather than routing rows
- Guard for the classic dirty-data case: the name field populated with the domain
2.7 · Pilot, then delete things
Nine vendors came out after measurement.
The strongest evidence in this playbook for why the pilot step exists — and why you should expect the
v1 waterfall to be too long.
Patlytics · June → July
The contact table went from 89 columns to 76 with nothing added. The entire
phone waterfall — six vendors plus the rollup — deleted. The email waterfall trimmed from ten finders to
seven, dropping the most expensive per hit. The contact lookup delay moved from 1 second to 500, fixing the
race. The company table needed no changes at all.
Nine vendors removed after measurement, not before. Without a pilot step, the next build reproduces
the June version — and pays for it every month.
Step 1
Run a real sample
Reflecting the actual mix of intake sources and email types. Measure fill rate per field against the baseline, and hand-verify a subset against public sources.
Step 2
Record cost per record
Actual credit consumption per record and per field. Present it with a recommendation on which enrichment steps justify what they cost.
Step 3
Cut what didn't contribute
Reorder by observed hit rate for this segment. Remove providers that added no incremental matches. Downgrade any model a cheaper one matches.
Step 4
Recalculate at full volume
Projected monthly spend against the budget agreed in Blueprint. If they don't line up, say so now — not in the first invoice conversation.
The rollout pattern
Portnox ran the Salesforce write
behind a manual button so a human reviewed every record before anything touched the CRM.
In July — one setting change, nothing else — it flipped to automatic. Ship review-gated, earn trust,
then automate. Copy that progression on every build; it costs you a week and buys you the benefit of
the doubt on everything after.