A brokerage lives or dies on one thing a generic CRM can't do: matching the right buyer to the right listing. Not by a keyword filter on beds and price, but by meaning — "a family wanting a suburban house with a garden" should surface the family home over the downtown loft, even when neither description says "family". This overlay makes the Vector pillar the product: two embedding tables and a cosine match, both directions, over the same bucket.

The problem — and the money

The buyer is the brokerage's ops lead who needs buyer-to-listing matching and a commission split that always balances — inside the CRM, not in a separate MLS tool and a spreadsheet. A vanilla CRM can filter listings; it can't rank them by fit to what a buyer actually wants. The payoff is two hard numbers: the family buyer's nearest listing comes back at cosine 0.272 (the "14 Maple Grove" family home) ahead of the downtown loft at 0.530 — and a close computes a commission split of 12,960 + 8,640 = 21,600, exactly the gross. That's the why — meaning-based matching and a balanced split are the brokerage's core loop.

This is the CRM suite + the real-estate overlay. The seven base skills — core, lead-to-opportunity, account-360, pipeline-forecast and the rest — are unchanged. The overlay only adds listings + buyer prefs, two VECTOR(2048) tables, and a commissions table. Same bucket, one copy of the rows.

What real-estate adds

A small, additive diff on top of the suite (skill: crm/real-estate → the crm/overlays/real-estate contract):

  • Inventory + intentlistings (key listing_id: price, beds, sqft, a description) and buyer_prefs (key contact_email: budget, beds, areas, must-haves, a prefs_text).
  • Two VECTOR(2048) tables — the productlisting_vectors and buyer_vectors, one jina-embeddings-v4 (2048-dim, cosine) embedding row per listing and per buyer. Match ranks by cosine distance, both directions.
  • Commissionscommissions (key deal_id): agent_amount + brokerage_amount must sum to gross; opportunities are repurposed as deals-on-a-listing by convention (no new columns).
  • Two gate changes — lead-to-opportunity scores buyer readiness (financing, timeline, motivation) rather than firmographic fit; account-360's next-best-action suggests the top-matched listings for a buyer, fed by the buyer-to-listing KNN.

Apply the diff — the inventory, the two vector tables, and one embedded listing + buyer:

You

In the crm bucket, apply the real-estate overlay: create listings, buyer_prefs, listing_vectors + buyer_vectors (VECTOR(2048)), and commissions. Embed two listings (a suburban family home '14 Maple Grove' and a downtown loft) and one buyer (wants a 3-bed suburban house with a garden) with jina-embeddings-v4, one vector row per upsert.

DODIL MCP tools called
data_table_createignite_models_embeddata_table_upsert
Agent

Created listings, buyer_prefs, commissions, and listing_vectors + buyer_vectors as VECTOR(2048). Embedded 2 listings + 1 buyer with jina-embeddings-v4 (2048-dim confirmed), one vector row per upsert (2048-dim frame limit); all writes wal_written:true.

Now the payoff — the buyer-to-listing match by meaning, and the commission split that balances:

You

In crm, rank listings for [email protected] by cosine distance to their stored preference vector, nearest first. Then compute a 60/40 commission split on a $21,600 gross and check it sums to gross.

DODIL MCP tools called
data_pgdata_sql
Agent

Match: lst-1 '14 Maple Grove' family home at cosine 0.272 (nearest) ahead of lst-2 downtown loft at 0.530 — the family buyer wanting a suburban house with a garden ranks the family home first. Commission: agent_amount 12960 + brokerage_amount 8640 = 21600 = gross (balances=true).

The next-best-action gate then feeds off that KNN: for a given buyer it suggests the top-matched listings instead of cross-sell whitespace. The gate mechanism and its JSON contract are unchanged from the base account-360 skill; only the prompt and its input change.

Scaffold it — the one-shot

With the DODIL MCP connected, one prompt composes the suite and this overlay:

Scaffold a CRM for my real-estate brokerage — the CRM suite plus the real-estate overlay.
 
Base: the full crm/core suite (accounts, contacts, leads, opportunities, activities; the
account-hierarchy graph; lead-to-opportunity + account-360 + pipeline-forecast).
 
Then apply the real-estate overlay on the SAME bucket:
1. Create listings + buyer_prefs, and listing_vectors + buyer_vectors as VECTOR(2048)
   (jina-embeddings-v4, cosine) — one vector row per upsert.
2. Create commissions (key deal_id); agent_amount + brokerage_amount MUST sum to gross.
3. Repurpose opportunities as deals-on-a-listing; set the pipeline stages new_buyer -> showing ->
   offer -> under_contract -> closed_won/lost.
4. Point lead-to-opportunity at BUYER readiness and account-360's NBA at the buyer-to-listing KNN.
Seed the demo above and show the buyer-to-listing match + the balanced commission split.

Verify

Every number below was live-validated on 2026-09-02 (org IHDIASH, throwaway bucket, torn down after):

# 5 tables incl. listing_vectors + buyer_vectors as VECTOR(2048); all writes wal_written:true
dodil data table list -b "$BUCKET" | grep -E "listing_vectors|buyer_vectors"
# buyer -> listing match: lst-1 (family home) 0.272 nearest, ahead of lst-2 (loft) 0.530
dodil data pg -b "$BUCKET" "SELECT lv.listing_id,
  lv.embedding <=> (SELECT embedding FROM buyer_vectors WHERE contact_email='[email protected]')
  FROM listing_vectors lv ORDER BY 2 ASC"
# commission split balances: 12960 + 8640 = 21600 = gross
dodil data sql -b "$BUCKET" "SELECT (agent_amount + brokerage_amount = gross) FROM commissions"   # true

The five tables, the two 2048-dim embeddings, the buyer-to-listing cosine match, and the balanced commission arithmetic are proven live. Wrapping the matcher / commission-calc as a deployed Ignite app reuses the crm-lead-scorer image/deploy pattern already proven in the base suite.

Connect your tools

Everything the overlay wrote lives in the one DataK3 bucket, reachable by your own stack — a listing portal reads listings over the Postgres wire; a pgvector driver (or a Qdrant/Pinecone client) runs the buyer-to-listing cosine match against the same listing_vectors rows. data connect crm prints the endpoints. Full, live-validated walkthrough: Connect your tools.

Composes

This page is not a fork of the CRM — it is a composition:

  • Base: the seven CRM suite skills (crm/core, crm/lead-to-opportunity, crm/account-360, crm/pipeline-forecast, …) — the system of record, unchanged.
  • Overlay: crm/overlays/real-estate — the additive diff above (listings + buyer prefs, the two VECTOR(2048) matching tables, the commissions table, the buyer-readiness + listing-NBA gates).

Read the base to learn the mechanics; this overlay is the small, industry-specific diff on top.