A thinking artifact · synthetic data
Cloze · Brokerage CDP

The customer-data layer under a real-estate book.

Resolve identity → map referrals → activate cohorts. Built bottom-up from a synthetic 20-person book to answer one question: who actually drives your business?

$8.20Mbook volume
$234KGCI
20people
15referrals
20deals
$2.83M
of originated volume is invisible to a flat “referred by” field; it sits with hidden originators (Karen Whitfield, Aisha Patel, Luis Romero) you'd never think to thank. Layer 3 surfaces it.

Synthetic data throughout: a thinking artifact, not a Cloze export. The engine is ~1,160 lines of stdlib Python (resolver → referral graph → cohort analytics), plus ~470 more for the firm layer at the end; this page renders its JSON.

The stack · one pipeline, four layers

Messy contacts, a one-hop referral field, unprovable keep-in-touch: three pains, one stack.

It starts with capture and ends with proof. Layer 1 is where the data comes in; everything downstream depends on Layer 2 getting identity right first.

L1Pluggable source
Form Capture
Pull structured deals off dotloop / DocuSign / the MLS. Cloze already has this: treat it as a pluggable source that feeds Layer 2, never the CRM directly. Nothing here rebuilds it.
L2Built here
Resolve identity
Merge / split / classify a messy import into clean entities. The keystone, and it stands on its own.
L3Built here
Map referrals
A directed graph over the resolved people: multi-hop attribution a flat “referred by” field can't show.
L4Built here
Activate cohorts
Roll deals up to cohorts and prove keep-in-touch lift: the payoff.
Layer 2 · Identity resolution

The keystone. And it stands alone.

Before any graph or analytics, you have to know who is who. A 59-row import (nicknames, diacritics, Jr/Sr, spouses sharing an inbox, office lines, junk) resolved into clean entities. (This import fixture is the resolver's own stress set, separate from the 20-person referral book the later layers run on.) The design that matters: assisted, banded, evidence-rich, non-destructive. It merges only what's certain and hands the gray zone to a person with the reasons attached.

59
raw imported rows
42
resolved people
8 auto-merged6 sent to a human 3 households split2 companies kept 3 junk dropped2 shared lines suppressed
Even if the referral graph and cohort layers don't fit Cloze's per-user architecture, the resolver stands on its own: it's the part every CRM needs and few do conservatively. Conservatism is the antidote to the #1 churn driver, complexity: it never silently corrupts a book.

The decision ledger: what it did, and why

Every call carries its evidence. Names are synthetic; the reasoning is the product.

Auto-mergedCertain: a shared hard identifier, compatible names, nothing contradicting.
  • Davdi Nguyen / David NguyenDavid Nguyensame email (dnguyen@gmail.com)
  • Michael OBrien / Mike O'BrienMichael OBriensame phone (3175550188)
  • S. Reyes / Sandra ReyesSandra Reyessame email (sandrareyes@gmail.com)
Sent to a humanLikely, not certain. The engine asks instead of guessing.
  • t nguyen ↔ Thomas Nguyen score 0.7name guessed from the email local-part (initial + surname); verify
  • Topher Bauer ↔ Chris Bauer score 0.85same address corroborates
  • Bob Jensen ↔ Robert Jensen score 0.85same address corroborates
Kept apartShares a key, but the evidence says distinct.
  • John Smith Jr ↔ John Smith Srdifferent generational suffix (JR vs SR)
Households splitOne record, two real people. We flag it; a human assigns who owns what.
  • Greg Park & Linda Parktwo contactsone record holds two first names (Greg / Linda)
  • Jim Sullivan & Patty Sullivantwo contactsone record holds two first names (Jim / Patty)
  • Frank Delgado & Rosa Delgadotwo contactsone record holds two first names (Frank / Rosa)
CompaniesRecognizable orgs, kept as entities, not dropped (Cloze has a Companies type). “&” firm names that read like couples (Miller & Miller Plumbing) are caught before the household splitter, from org nouns or the email domain alone.
  • First American Titlecompanycontains 'title'; role inbox (closing@firstam.com)
  • Front Deskcompanycontains 'front desk'; role inbox (info@brightmls.com)
Dropped (junk)Not a person and not an org. Junk typed into a contact field.
  • “DO NOT CALL”contains 'do not call'
  • “ATT PIN 4471”contains 'pin'
  • “WiFi Password”contains 'password'
Shared lines suppressedAn office or toll-free line is not an identity.
  • 3175550400 phoneon 3 records; not used as a merge key
  • 8005551212 phonetoll-free business line; not used as a merge key

The adversarial set: 28 rows built to break it

The import above is realistic mess; this second fixture is engineered traps. Every decision below is the engine's current output on it, and the pattern is one rule applied everywhere: when the evidence cuts both ways, ask a person instead of guessing.

Demoted, not mergedA shared identifier used to be an automatic merge. When each record also carries its own value for the other identifier, that's the signature of two people sharing a line; the pair goes to a human.
  • Robert Tran ↔ Robert Tran score 0.75but each record has its own phone -> shared family inbox? two people -> review
  • Amy Lin ↔ Amy Chen score 0.75surname differs on a phone-only match (Lin vs Chen); recycled number? -> review
Surfaced with no shared keyA cross-letter homophone, a hyphenated married surname, complementary half-records, a typo'd email domain whose proposed fix reveals the match: pairs an importer keyed on shared identifiers structurally can't see. One of these is two different David Kims; the engine asks, the human says no, and asking is the design.
  • Geoff Barlow ↔ Jeff Barlow score 0.78complementary contact info (one has email, the other a phone); no shared key
  • Priya Anand ↔ Priya Anand-Rao score 0.78surname token subset (Anand / Anand-Rao); hyphenated married name?
  • Dana Wu ↔ Dana Wu score 0.85emails match once the proposed typo fix is applied (dana.wu@gmial.com); fix unconfirmed -> review, never auto
  • David Kim ↔ David Kim score 0.78complementary contact info (one has email, the other a phone); no shared key
Companies, not couples“&” names that read like spouses classify as firms, from an org noun, a repeated name, or the email domain alone; the professor with a .edu address stays a person.
  • Miller & Miller Plumbingcompanyorg noun 'plumbing'; repeated name around '&' (a firm, not two people); name matches email domain (mmplumbing.com)
  • William & Mary Collegecompanyorg noun 'college'; two-name '&' + .edu domain (institutions don't issue joint accounts); name matches email domain (wm.edu)
  • William & Marycompanytwo-name '&' + .edu domain (institutions don't issue joint accounts); name matches email domain (williamandmary.edu)

Still missed, and named: a flipped name order (Zhang Wei / Wei Zhang) never even becomes a candidate pair (needs its own blocking pass; parked), and a nickname pair with two fully-populated records and zero shared identifiers scores below the review bar; the real fix there is multi-value identifiers, on the roadmap. Score on this set: auto-merge precision 1.00, recall including review 0.71. Worse numbers than the clean import, on purpose; publishing them anyway is the point.

Go deeper: the resolver's two companion pages

On the honest edges: measured against Cloze's real importer (a 59-row live test, July 2026), the overlap is real: both merge on a shared email or typed phone when the names agree. The differences are at the edges. An importer can't reach a duplicate with no shared identifier (an email-only record and a phone-only record for the same person), and when a shared identifier meets a changed surname it drops the second record as invalid; this engine links the first case and routes the second to review, and it never discards data. Candor cuts both ways: the adversarial set above initially cracked this auto band too, fixed with guards that demote to review rather than guess. A household split is a flag, not an auto-action: we surface the two people and bundle the shared contact info, but assigning which phone or email belongs to whom is a human call (and cleanly needs multi-valued contact fields, on the roadmap). And middle names compare on the first token, so “Chad Michael” still matches “Chad” rather than mis-flagging as a household.

Layer 3 · Referral graph

Who actually drives your business?

A flat “referred by” field stops at one hop. This traces credit multi-hop, decayed per hop, so the person who seeded a chain gets seen, even when they closed nothing themselves. Nodes are colored by referral archetype (a behavioral attribute Cloze doesn't segment on) and sized by the volume they touch. Hollow rings closed $0 of their own; a dashed ring marks an outlier whale deal. Flip the toggle and watch the hidden originators grow.

Who drives the book (ranked by network influence)

PersonDirect referralsInfluence volume Influence GCIMix L/B/DInfl ÷ direct
Wendy Hart3$3.35M$92K2L/1B/1D1.0×
Greg Donovan5$1.94M$54K2L/4B/0D1.1×
Karen Whitfield hidden originator2$1.83M$47K3L/5B/1D2.8×
Aisha Patel hidden originator1$1.37M$37K3L/4B/0D3.4×
Luis Romero hidden originator1$1.10M$24K3L/4B/1D2.6×
Raj Patel2$985K$29K0L/5B/0D1.0×
Marcus Lin1$205K$6K0L/1B/0D1.0×

$2.83M of originated volume sits with Karen Whitfield, Aisha Patel, Luis Romero, invisible to a one-hop field. Influence is an influence score, not accounting (credit duplicates up the chain). A listing self-markets and spins off buyer leads, so the mix matters as much as the dollar figure.

Deal structure: buy / sell / both / dual agency

Transactions model as deals + sides: a deal is one property; each side ties a contact to it as a buy or a sell, carrying that side's GCI. A deal with both sides = dual agency (you repped buyer and seller, one transaction). So the book classifies every client and flags dual deals, not just a single buy/sell tag, and volume counts the property once even when you earn both commissions.

10
buyers
6
sellers
1
both (buy & sell)
Hannah Vance
1
dual-agency deal
9 Vista Ln: Aisha Patel + Hannah Vance

Referral archetypes: the “beyond what they have”

Cloze segments by stage and lifecycle. None of them segment by referral behavior. Five bins, tendencies not verdicts: a lens. And they're living labels, recomputed from current activity every run: tag a One-and-done as a referrer on your next deal and she moves toward Connector; as the book's average sale price rises, a Harpoon slides toward Connector. Not a permanent stamp.
Property-sourced leads aren't referral-archetyped; they have no referral behavior to classify, so they sit out of these bins (see Lead sources below).

Connectorrefs ≥ 2 · transacts little
Sends you people, closes little themselves. The teacher / sphere connector. Renders hollow: closed $0, yet sits upstream of millions.
Karen Whitfield, Raj Patel
Championdeals ≥ 1 · refs ≥ 2
Transacts and refers habitually. The rare best client, the one to clone.
Greg Donovan
Assembly-linedeals ≥ 3
Steady own volume, rarely refers. The investor / repeat buyer.
Sal Greco
Harpoonrefers a whale
The harpooner: refers occasionally but lands an outlier-value deal. “Whale” = mean + 1.5σ of this agent's own book, so the bin tracks the book, not a fixed dollar figure.
Wendy Hart
One-and-doneno pattern yet
One deal or a stray referral. The long tail, until a single referral cascades, when it reads as a hidden originator by influence (a lucky one-off, not a habit).
Aisha Patel, Brenda Foss, Carlos Mejia, Dana Wells, Derek Tanaka, Diane Okonkwo, Hannah Vance, Luis Romero, Marcus Lin, Nina Kowalski, Paul Bridges, Yvonne Castellano
Lead sources · the second engine

Two engines feed the book: relationships and inventory.

The graph above is mostly your personal-derived engine: people sending people. But a property is a lead-gen node too: a listing's open house spawns buyers who often close elsewhere, and a sale farms its neighbors. Those are property-derived leads. In the graph they hang off the source listing's owner on a dashed line: a real link, but not a referral, so it carries no referral credit. One book, two engines; in production the property side hydrates from the MLS, another source plugging into the same resolved-entity core (Layer 1).

Personal-derived
14
clients via referral · $7.03M · 86% of book
Property-derived
3
leads via listings / farm · $1.17M · 14% of book
open houseopen housefarm1 Lakeshore EstateDiane Okonkwo’s $2.10M listing31 Harbor ViewGreg Donovan’s $400K listingPriscilla Vaughnbuy · 18 Aspen Ct · $390KTheo Marshbuy · 7 Cypress Way · $315KGwen Suttonsell · 44 Harbor View · $465K
1 Lakeshore EstateDiane Okonkwo’s $2.10M listing · $63K commission
  • open housePriscilla Vaughn → buy 18 Aspen Ct$390K
  • open houseTheo Marsh → buy 7 Cypress Way$315K
Lead halo: 2 closed $705K elsewhere: business a flat CRM never ties back to this property.
31 Harbor ViewGreg Donovan’s $400K listing · $10K commission
  • farmGwen Sutton → sell 44 Harbor View$465K
Lead halo: 1 closed $465K elsewhere: business a flat CRM never ties back to this property.

Where the two engines meet

Properties and people aren't separate graphs; they're one. Here a single listing is the hub: a referral brought you the seller, and the listing brought you more buyers. Both engines, one resolved property.

Wendy HartHarpoon · referred the sellerDiane Okonkwo$2.10M listing · the whale1 Lakeshore Estate$2.10M · $63K commissionreferredlistsopen housePriscilla Vaughnbought 18 Aspen Ct · $390Kopen houseTheo Marshbought 7 Cypress Way · $315K
Wendy Hart's referral brought you Diane Okonkwo's $2.10M listing (personal-derived); the open house then brought buyers who closed $705K elsewhere (property-derived). A flat CRM sees a referral and a sale; the CDP sees the whole chain through one resolved property, and it stays readable because you focus on a property, not the whole mesh.
Layer 4 · Cohort & temporal

The prize: proving keep-in-touch ROI.

Cloze's promise is “systematic, not aspirational.” This is the layer that proves it, rolling deals up to the cohorts that touched them, then measuring whether a deliberate touch actually moved the needle.

CohortMembersDeals closed Touched volume% of bookMix L/B/D
Sphere/Partner30$7.03M86%5L/11B/1D
Past Client1316$6.54M80%5L/10B/1D
Cold List42$4.33M53%2L/6B/1D
Christmas Card List76$3.10M38%3L/5B/1D

A Sphere/Partner cohort that closed $0 itself is upstream of 100% of GCI: what the referral graph shows, now in cohort form. % of book runs past 100% because people belong to several lists; honest double-count, not a bug.

Keep-in-touch lift: Holiday card mailing → Christmas Card List
71%
active after the card
(90d window)
14%
same list, prior 90d
(no card)
25%
holdout cohort
(Cold List)
Honest caveat: suggestive, not causal. A warm list and holiday timing, not a randomized trial. The honest claim is “strong signal,” and naming that limit out loud is the differentiator. The analytics tell the truth even when it's hedged.
A coda · the firm layer

Everything above is one agent's book.

A brokerage promises the client a relationship with the firm, but every book is isolated, rightly. So when the roster changes, the firm forgets. The question that answers is the one this whole project started from: how does a brokerage pool its agents' data without breaking the per-user isolation and the real-mailbox moat?

The answer, in one line
Pool at the resolved-entity and analytics layer. Never at the record or mailbox layer.

Each agent's book stays isolated. The pool is a read-mostly governed projection on top: a resolved customer graph plus firm analytics. Inside one book, resolution merges duplicates. Across books it links and never merges, because two agents who both know a client each keep their own relationship and history, and the firm only learns “same human.” That is why Dan's word is customer data pool and not “merge everyone's CRM.”

$90Kfirm GCI
3agents · 2 active
3cross-agent links
4orphaned clients rerouted

The wedge: an agent leaves, and the book does not go dark.

Flip the toggle. 1 of 3 agents departs and the graph routes each orphaned client to the agent who already has a link, not round-robin. 3 of 4 land on a real relationship path, and the one that cannot is flagged as a load-balanced fallback rather than dressed up as a match.

Susan ParkTom Gallagher
medium · referral path
Sphere connection: referred by Helen Park, who is known to Tom Gallagher.
Robert KingMaria Santos
strong · direct link
Direct relationship: already worked / known by Maria Santos.
Frank Daleload-balanced
none · honest fallback
No relationship signal: load-balanced fallback (human review).
Helen ParkTom Gallagher
strong · direct link
Direct relationship: already worked / known by Tom Gallagher.

Co-owned GCI is counted once, in the owning book, and the co-ownership is flagged rather than double-billed. Tom Gallagher earned $10K of influence inside Maria Santos's book by handing over one buyer, which a per-agent production ranking cannot see. Cross-agent links are assisted and banded: a human confirms, and a name-only match is review, never auto.

Governance is the spine, not the headline.

Brokers buy the outcome. Governance is why the agents say yes, and it is the whole difference between this and the surveillance version anyone could build. So the visibility rules ship opinionated: one matrix, not a matrix builder.

What poolsThe agent seesThe broker sees Another agent sees
Records, notes, message content, the mailboxThe moat. This is the row that never moves.Everything, unchangedNothingNothing
Resolved identity links (“same human”)Link, never merge. A false link leaks a client, so name-only is review.Own book, plus an unnamed co-ownership flagAggregate collision countsNothing until both agents confirm
Transaction facts: deals, sides, GCIThe firm already owns these. Pooling them breaks nothing.Own production, plus influence they earned elsewhereFirm rollups by agent and by cohortNothing
Individual activity: calls, opens, cadenceAggregates to the broker are fine. Individual activity is surveillance.Their ownNever, at any granularityNever
At the orphan momentThe one moment naming is on: the client needs an agent today.Sees their book leave with them, in writingA ranked reassignment with the reason shownThe named client, on assignment
The bright line: the graph responds to a departure. It never predicts one at the individual level. Recruiting intelligence pointed outward is a product Cloze already integrates; prediction pointed at your own roster is what burns the trust the layer runs on.
Stays with the firm
Transaction facts and the resolved links
the data prenup
Walks with the agent
Relationship history and the mailbox

Agreed while relations are good, so offboarding stops being a fight, and it cuts both directions: the same architecture is the arrival-side answer to a recruit asking what the firm will be able to see. Every surface answers to five checks:

  1. Does it act for the agent in the moment, or on them?
  2. Aggregates to the broker: fine. Individual activity to the broker: surveillance.
  3. Symmetry: the agent can always see what the firm sees of their book.
  4. Does the intel route opportunity, or feed discipline?
  5. Identity and deal facts pool. Notes, sentiment, and message content never do.

Synthetic 3-agent fixture, ~470 lines of stdlib Python on top of the same resolver above; both this panel and the companion render one JSON the engine emits. Production wires the identical engine to the real per-agent books.