The data model
Thunder Graph tracks four kinds of records. Understanding the difference explains why some searches and scores apply to one but not another.
Firms (investors)
Investment firms โ VCs, PE funds, family offices, corporates. Each carries structured criteria (sectors, stages, check size, geography, thesis) that the matcher runs on. table: investors
Companies
Operating companies โ clients, targets, and portfolio companies. Firmographics (revenue, headcount, funding). table: companies
Contacts
People โ with a title, firm, location, personas, and a relationship warmth score. table: contacts
Organizations
The dedup layer that unifies firms and companies under one canonical name. Rebuilt nightly, so its ids are not stable โ durable records key on firm/contact identity instead. table: organizations
Warmth score
Warmth is a 0โ100 measure of how strong a relationship is, computed identically for every person and every firm from real interaction history (Gmail, Calendar, Fireflies meetings, HubSpot, WhatsApp, LinkedIn, Luma events). It is the sum of four components, each capturing a different dimension of a real relationship. graph/warmth.mjs ยท score-warmth.mjs
The four components (sum to 0โ100)
1 ยท Recency (0โ30) โ how recently did you last interact?
A straight-line decay over three years. A contact touched today scores the full 30; one last touched exactly three years ago scores 0. This deliberately long horizon lets genuinely strong but dormant relationships still surface across the team.
e.g. last touch 6 months ago โ 30 ร (1 โ 182/1095) = 25.0. One year ago โ 20.0. Two years ago โ 10.0.
2 ยท Frequency (0โ30) โ how often, recently?
Counts interactions in the last 6 months (180 days), worth 6 points each, capped at 30. So five or more touches in six months maxes this component.
3 ยท Depth (0โ25) โ was it substantive?
Not all contact is equal โ a meeting means far more than a one-line email. Depth is a weighted sum of interaction quality over the last 12 months, capped at 25.
| Interaction type | Depth weight | Reading |
|---|---|---|
| Meeting (Fireflies / calendar) | 8 | the strongest signal of a real relationship |
| Luma event (checked in) | 5 | showed up to an event you hosted |
| Call ยท WhatsApp | 4 | direct, personal channel |
| LinkedIn message | 3 | light but intentional |
| Note ยท LinkedIn connect ยท event RSVP | 2 | weak signal of intent |
| 1 | the baseline touch |
4 ยท Directionality (0โ15) โ did they reach out to you?
An inbound message (them โ you) is a much stronger signal than outbound alone. Reciprocity earns the most.
| Condition | Points |
|---|---|
| At least one inbound message | +10 |
| More than two inbound messages | +3 more |
| At least one outbound message | +2 |
Maximum 15. When warmth is derived from aggregate rollups (no per-message direction available), directionality is 0 โ the score is conservative rather than guessed.
The labels
The 0โ100 score maps to a label used everywhere in the UI:
| Label | Score range | Meaning |
|---|---|---|
| ๐ฅ Hot | 80โ100 | active, deep, recent relationship |
| Warm | 55โ79 | a real relationship, maintained |
| Lukewarm | 30โ54 | some genuine history |
| Cold | 10โ29 | thin โ a touch or two |
| Dormant | 0โ9 | little or no interaction on record |
Whose relationship? โ the warmth owner
A contact's warmth is the maximum over every Thunder teammate of that teammate's own interaction history with the person. The teammate who produces the max is the warmth owner โ the best intro path, shown as "best intro via โฆ" on the record. So warmth answers two questions at once: how strong is this relationship and who on our team owns it.
Firm-level warmth
A firm is as warm as its warmest person โ or a direct firm-level relationship edge, whichever is stronger.
Two details that keep it honest
- De-duplication. HubSpot auto-logs Gmail and Calendar, so one real email or meeting can appear 2โ3 times across sources. Before scoring, same-type events within a short window (email/call โค 3 min, meeting โค 30 min) are merged, so Frequency and Depth reflect real interactions, not double-counts.
- Durable community bonuses. Some cohorts carry a manual boost that survives the nightly recompute,
added on top of any interaction score: Post-Exit Founders (PEF) +20 ยท $100M Exits podcast guest +50.
They stack โ
warmth_bonusis the sum of a contact's community tags, so a guest who is also a PEF member gets +70. A no-touch member floors at their bonus value; a touched member gets score + bonus, capped at 100.
- A founder you met twice in the last quarter (2 meetings), exchanged 4 emails with, who emailed you first, last touch 3 weeks ago:
- Recency = 30 ร (1 โ 21/1095) โ 29.4 ยท Frequency = min(30, 6 ร 6) = 30 ยท Depth = min(25, 2ร8 + 4ร1) = 20 ยท Directionality = 10 (inbound) + 2 (outbound) = 12
- Total โ 91 โ ๐ฅ Hot.
Relevance & compatibility
When you run Find intros, every candidate firm gets a relevance score (0โ100) measuring how well the firm's investment criteria fit the company โ a faithful re-implementation of Thunder's production matching model over our mirrored data. graph/compatibility.mjs
Two lanes, two weight tables
A capital raise and a company sale are scored by different weight tables, because the signals that predict a good investor are not the signals that predict a good acquirer. The mandate's intent picks the lane automatically โ you never choose it.
| Lane | Used when | Dominant signals |
|---|---|---|
| Raise default | raise_capital mandates (venture, growth, buyout equity, debt) | declared criteria fit โ sector + funding stage |
| Sell-side ma_sell | be_acquired mandates โ a full or partial sale | demonstrated behaviour โ have they bought companies, can they afford this one, do they take this stake |
Why they differ (2026-08-03): funding stage is a VC-round concept driven by a dropdown that sell-side clients leave blank, so on a sale the dominant component scored a flat 0 for everyone. The sell-side lane replaces it with evidence a banker would actually ask for.
Raise lane โ the eleven components (raw points)
Each criterion contributes raw points. Sector dominates; the rest refine. compatibility.mjs ยท W
Five of these can go negative: a thesis mismatch actively counts against a firm. Sector โ40 (no thematic overlap at all), acquisition alignment โ20 (disqualified type), data confidence โ15 (a record with no web domain or no firm type โ usually not a firm at all), product stage โ3, geography โ3 (they list geographies and none match), check size โ2. A profitable, non-growing company also loses a further 6 product-stage points against a pure VC. Product stage can reach 18 โ an advanced product paired with an early capital stage earns +3 ("further along than the round implies").
Sell-side lane โ the fifteen components
The sell-side lane keeps every raise component (re-weighted) and adds five that only make sense when someone is buying the company. compatibility.mjs ยท W_MA
| Sell-side-only component | What it measures |
|---|---|
| Acquisition capability 30 | Have they actually bought companies, and recently? 5+ deals in 36 months earns full marks, 1โ2 earns 65%, a firm that transacts but has never acquired earns 35%, and a firm with a record showing zero acquisitions is penalised. A deal closed within 12 months adds 3; nothing for 36 months subtracts 3. |
| Control fit 22 | Does the stake they take match the stake being sold? The minority-vs-majority separator: a growth fund that has only ever taken 20% is a poor fit for a full exit however well its sectors line up. Measured stake behaviour wins; declared stages, thesis focus tags, then firm type corroborate when we have no measured behaviour. |
| EV capacity ยฑ20 | Jason's 4ร rule โ can they afford it? Capacity โฅ 4ร the deal earns full marks, 1โ2ร earns 15%, below half the deal is a full penalty. Capacity comes from market cap or enterprise value first, then the largest cheque they have actually written, and only last from a revenue proxy. Unknown capacity is neutral, never an exclusion. |
| Strategic overlap 14 | The bolt-on story: adjacent sectors, shared business model, shared revenue streams, shared geography. Deliberately double-counts signals that also score elsewhere โ for a sale, "sells the same way to the same customers" is the synergy thesis. |
| Deal context ยฑ10 | What the banker typed into the Context box. A buyer the client named gets the full +10 and is flagged a dream buyer; a name on the exclusion list gets โ10. Otherwise: profitable + debt-free paired with a control buyer, no customer concentration paired with a proven acquirer, and price expectation matched against a distressed posture. |
Sector is the gate
Sector is treated as the imperative signal, co-equal with funding stage. Any core (primary) sector overlap earns near-full credit; no thematic overlap at all is a โ40 penalty (โ34 on the sell-side lane, keeping the gate proportional to that lane's sector weight). Firms listing more than 12 sectors are treated as generalists and dampened โ down to half credit โ so a match has to be a specific theme, not a firm that "invests in everything." Secondary/adjacent sectors expand recall but count at 40% weight, never as a core match.
From raw points to a 0โ100 score
The summed raw points are squashed through a logistic (sigmoid) curve โ this compresses the extremes the way the production model does, so scores cluster meaningfully instead of spreading linearly. Each lane has its own midpoint, because the sell-side lane has a higher positive ceiling (~173 raw points vs ~147); reusing the raise midpoint saturated every decent buyer into the high 90s.
The raise midpoint moved 45 โ 35 on 2026-08-13, alongside the funding-stage cut. It is not a free parameter: it re-centres the squash so that removing 18 points of stage weight does not shift every client-visible score downward. Measured across the 1,446 firms on the seven scored raise lists, the median relevance is unchanged at 71.
The sell-side midpoint of 85 was calibrated by sweep, not guessed: at 85 a demonstrated control buyer with capacity lands ~97, a minority-only fund on a full-exit mandate ~61, a sub-scale strategic ~50, a firm with zero recorded acquisitions ~38, a disqualified VC ~15. It is a function of the weight table โ any weight change requires re-running the sweep. graph/compat-test.mjs
Firm-type weighting
The score is then multiplied by a firm-type weight (0โ1) set by the deal's intent. A firm that is the wrong type for the deal ("off-type", weight 0) is floored at 0.05 โ deep-demoted and sorted to the bottom, flagged, but never deleted (it may still be a useful sounding board). An unknown firm type is neutral: 0.5 on a raise, 0.2โ0.3 elsewhere. recommend.mjs ยท FIRMTYPE_WEIGHTS
On a raise, the weight is not set by intent alone โ it is set by the instrument the company selected at intake (venture equity, buyout equity, or debt). This is the real VC-vs-PE-vs-lender separator: a venture fund is not a weaker fit for a debt raise, it is no fit, so it scores 0 and is demoted out of the list rather than docked a few points.
| Firm type | Raise ยท venture equity | Raise ยท buyout equity | Raise ยท debt | Be acquired | Acquire | Partner |
|---|---|---|---|---|---|---|
| Venture Capital Fund | 1.0 | 0 | 0 | 0 | 0 | 0 |
| Corporate VC | 1.0 | 0.6 | 0 | 0.8 | 0 | 1.0 |
| Private Equity | 0 | 1.0 | 0.3 | 1.0 | 0 | 0 |
| Family Office | 1.0 | 1.0 | 0.4 | 0.8 | 0 | 0.5 |
| Syndicate | 1.0 | 0 | 0 | 0 | 0 | 0 |
| Accelerator | 1.0 | 0 | 0 | 0 | 0 | 0.25 |
| Private Credit | 0 | 0.3 | 1.0 | 0 | 0.8 | 0 |
| Commercial Bank | 0 | 0 | 0.8 | 0 | 0.9 | 0 |
| Incubator | 0.25 | 0 | 0 | 0 | 0 | 0.25 |
The debt column was retuned on 2026-08-13 from the curation record: family offices 0.7 โ 0.4 and commercial banks 1.0 โ 0.8. On the two debt mandates in the data, family offices were a third of the list and the reviewer dismissed 66 of the 67 they looked at. A family office does occasionally write private debt, so this is a demotion below the credit funds that do it routinely โ not a zero.
How results are ranked
The score is relevance and nothing else. Warmth and the owner path are computed for every firm and shown on each card, but they are never folded into the number.
This is a deliberate decision (2026-06-29): an earlier version blended in relationship warmth and the owner path, which buried genuinely relevant firms behind whoever we happened to know. Now the number answers one question โ "is this firm a fit for the deal?" โ and you sort or filter by warmth separately when you want to prioritize who's easiest to reach. graph/recommend.mjs
The list order is not just the score
Sorting purely by score put a well-documented generic buyer above a partner the client actually asked for, because the partner is privately held and loses on data richness. So the list applies four deterministic keys before the score โ a rule, not another round of weight tuning (2026-08-04):
| # | Sort key | Why |
|---|---|---|
| 1 | On-type before off-type | wrong-type firms sink to the bottom whatever they score |
| 2 | Fit tier โ ๐ฏ slam dunks, then possible fits, then everything else | multi-dimensional confirmation outranks a high score on thin data |
| 3 | Existing relationship โ a dream buyer the client named, then an ecosystem partner the seller is built on | "a direct integration is more relevant, there is already a relationship" |
| 4 | Relevance score, then warmth, then confidence | the tie-breakers within a tier |
Keys 3 and 4 are the only place relationship data touches ordering, and only as a tie-break inside a tier โ it never changes the score itself.
Fit tiers
Because a raw relevance score can look high on thin data, candidates are also sorted into fit tiers that require multi-dimensional confirmation โ a tier is never a single threshold. This is what the ๐ฏ / tier-2 badges on target-list cards mean.
| Tier | Every one of these must hold |
|---|---|
| ๐ฏ Slam dunk (tier 1) |
firm-type weight โฅ 0.8 (clearly the right type) ยท a core sector match (not just an
adjacent one; if the company has 3+ core themes, at least 2 must match) ยท multi-component criteria
confirmation โ raw points clear the lane's sigmoid midpoint (35 on a raise, 85 on a sale)
ยท plus one lane-specific condition:
|
| Possible fit (tier 2) | plausible firm type (weight โฅ 0.5) ยท any sector overlap ยท relevance โฅ 45. A real fit that's missing one slam-dunk condition. |
| Other | everything else, including off-type firms and โ on a sale โ any firm with a negative acquisition alignment. Collapsed behind a toggle, never mixed into the main list. |
Tier 1 is criteria-driven, not score-threshold-driven: sparse firm tag data caps scores, so a hard relevance bar would make the top tier depend on data density instead of actual fit. The production match-score prior (which tends to make everything look 82โ100) can never mint a slam dunk by itself. graph/recommend.mjs
Mandate verification
After matching, each top candidate is screened against the firm's own written thesis plus reality data (real ticket window, 36-month activity, true investor type from Inven) to answer: would this firm actually do this deal? Screening runs per lane, derived from the mandate's intent + financing type + structure. graph/verify-mandate.mjs
| Lane | Mandate |
|---|---|
ma_sell | sell-side M&A โ full control sale |
ma_sell_minor | sell-side โ minority / partial stake |
raise_venture | venture / growth equity raise |
raise_buyout | buyout / control equity raise |
raise_debt | debt / credit financing |
Hard reality checks run first with no LLM (e.g. a firm whose minimum ticket is $193M is excluded from a $60M deal instantly, for free). What survives goes to a Sonnet screen. Each firm gets a verdict:
โ covers the firm's thesis + reality credibly cover this mandate โ excludes a concrete reason it won't (auto-demoted to Other) ? unclear not enough signal to decide
Verdicts cache for 60 days (invalidated when fresher reality data lands), keyed by firm + lane + deal-size bucket, so the same firm isn't re-screened across deals of the same shape.
Origination score
The Origination engine surfaces companies that look like they're about to need a banker. Each prospect's score is an additive sum of independent signals โ the higher the score, the more reasons to reach out now. graph/originate.mjs
| Signal | Points | What it means |
|---|---|---|
| Warm path | +30 | a warm contact (warmth โฅ 55) at the company โ we can actually reach them |
| Lukewarm path | +18 | a lukewarm contact (warmth โฅ 30) |
| SEC Form D filed | +25 | recently filed a raise โ re-raise clock + M&A appetite |
| Pulse intent | +20 | recent news mentioning raising / acquisition / sale exploration |
| Raise window | +20 | seed/A/B stage + company 2โ8 years old โ re-raise clock |
| $100M Exits podcast guest | +15 | a pre-qualified founder with a warm hook |
| Scale fit | +15 | revenue in the millions โ transaction-sized |
| Form D officer in our network | +10 | a named filer is already a contact |
| Scale fit (growth/profitable stage) | +10 | later product stage, if revenue unknown |
Every prospect card lists exactly which signals fired and why, so the score is always explainable โ never just a number.
Learned ranker
The matcher improves over time by learning from real outcomes. Every recommendation stores the exact per-component scores that produced it (the "why-breakdown"), so when a firm later progresses down the funnel โ or passes โ we can measure which components actually separate winners from losers. graph/learn.mjs
Outcomes are weighted by depth
A closed deal tells us far more about a good match than a bare reply; an informed pass tells us more than silence. Each outcome is weighted by how far it got:
| Outcome | Weight | Outcome | Weight |
|---|---|---|---|
| Committed | 1.5 | Meeting | 0.7 |
| Term sheet | 1.1 | NDA | 0.5 |
| IOI | 1.0 | Responded | 0.3 |
| Diligence | 0.9 | Passed (informed) | โ1.0 |
| Materials sent | 0.8 | Passed (no response) | โ0.6 |
| Dismissed before outreach | โ0.4 |
A dismissal during curation is the weakest negative in the set โ the market never saw the firm, so it reflects our judgment rather than theirs.
For each compatibility sub-weight it computes a magnitude-weighted lift โ how much higher that component scores among firms that progressed versus firms that passed โ and writes a proposal to nudge the weight. Nothing is applied automatically. A human reviews each proposal on the Portfolio tab and clicks Adopt or Reject; adopting applies a bounded step (at most ยฑ20% per adoption). The 100%-relevance ranking decision is never touched โ only the compatibility sub-weights inside relevance.
Personas & the AI prompts behind them
Every contact can carry one or more personas โ their professional role(s). A person can be several (a post-exit founder who now angel-invests is Founder + Angel). The canonical taxonomy:
Founder Operator Angel VC LP PE/Buyout Corporate/Strategic Advisor Banker Recruiter Service Provider Board Member
Personas are set in priority order: a human edit always wins; then a HubSpot self-selection ("What best describes you"); then AI inference. Provenance and a confidence value are stored on every contact so you can see where a label came from. graph/enrich.mjs
Prompt A โ normalize a HubSpot self-selection confidence 0.95
When a contact answered HubSpot's "What best describes you", the AI just maps their words to our taxonomy.
You are a data normalizer. Map HubSpot "What best describes you" selections to this canonical taxonomy: Founder, Operator, Angel, VC, LP, PE/Buyout, Corporate/Strategic, Advisor, Banker, Recruiter, Service Provider, Board Member. Input may be: comma-separated, pipe-separated, JSON array, or free text. Output ONLY a JSON array of canonical labels (exact case-sensitive match). If empty or unmappable, return [].
Prompt B โ post-exit founder (PEF community) confidence 0.80
PEF members come with a rich roster profile (exit company/title/year, current status, industry). Because they founded and exited a company by definition, "Founder" always applies; the AI adds today's roles from their current-status text.
You classify a post-exit founder's professional personas from their community-roster profile. This person is a member of the "Post-Exit Founders" (PEF) community โ they founded and exited (sold or took public) a company, so "Founder" ALWAYS applies. Add any ADDITIONAL personas their CURRENT activity clearly supports. Canonical taxonomy (use exact labels): Founder, Operator, Angel, VC, LP, PE/Buyout, Corporate/Strategic, Advisor, Banker, Recruiter, Service Provider, Board Member. Mapping guidance for the "current status" text: - "VC", "investor", "fund", "general partner" => VC ; "angel", "angel investing" => Angel ; "LP", "limited partner" => LP. - "advisor", "consultant", "consulting", "coaching", "fractional" => Advisor ; "board", "board member", "director" => Board Member. - "operator", "CxO at", "operating", "running/building a company", "founded a new company" => Operator (and Founder already applies). - "PE", "private equity", "buyout", "search fund", "acquisition entrepreneur" => PE/Buyout. Only add a persona the text actually supports. Return ONLY a JSON array of 1-4 canonical labels, ALWAYS including "Founder".
Exited: Parallel Markets Inc as CEO (2025) Current status: Founded a New Company, VC / Investor Industry: B2B SaaS, Fintech Functional expertise: Product, GTM Current title: (none)
โ result: Founder Operator VC. "Founder" is guaranteed even if the model omits it.
Prompt C โ infer from minimal signals confidence 0.60
For everyone else, the AI infers conservatively from title + email domain + firm โ and returns nothing rather than guess when signals are too weak.
You are a data analyst inferring professional roles from minimal signals. Be conservative; only include personas you are reasonably confident about.
Infer role personas for this person. Title: {title} Email domain: {domain} Firm: {firm} Choose from: Founder, Operator, Angel, VC, LP, PE/Buyout, Corporate/Strategic, Advisor, Banker, Recruiter, Service Provider, Board Member. Return a JSON array of 1-3 likely personas. If signals are too weak, return [].
Focus tags
Some investment strategies aren't in the sector tree (a "search fund" isn't a sector). Focus tags capture those thesis concepts. An AI reads each firm's own written thesis and assigns tags from a fixed vocabulary โ only what the firm itself focuses on backing, not words that merely appear in the text. These power niche searches like "firms that back search funds". graph/enrich.mjs ยท search.mjs
You tag investment firms with strategy/focus tags from this EXACT vocabulary (never invent tags): search_funds, entrepreneurship_through_acquisition, micro_pe, rollups, buyouts_smb, b2b_saas, vertical_saas, marketplaces, deep_tech, climate, defense, ai_native, cybersecurity, โฆ (40+ tags). Read each firm's own thesis text. Tag only what the FIRM ITSELF focuses on investing in โ e.g. tag search_funds only if they BACK search funds / searchers, not if the text merely mentions the words. 0-6 tags per firm; [] when nothing clearly applies.
Where AI is used โ and where it isn't
AI is used for language and classification tasks; all scoring math above is deterministic code, not an LLM. Models run on AWS Bedrock, tiered by task for cost and quality.
| Tier | Model | Used for |
|---|---|---|
| Drafting | Claude Opus 4.6 | client-facing intro emails, reply drafts, client reports (quality-critical, low volume) |
| Mid | Claude Sonnet 4.6 | profile extraction, persona & focus-tag classification, mandate screening, reply triage, natural-language search parsing |
| Fast | Claude Haiku 4.5 | bulk pulse / news summaries (simple, high volume) |
The golden rule holds everywhere AI touches outbound: the machine drafts, a human clicks send. No email, stage change on a judgment call, or weight adjustment is ever applied without explicit human approval. Every AI-written value is stored with its source label ("ai" vs "human" vs "hubspot") and a confidence, and a human edit always wins and is never overwritten.
Funnel stages
Once a firm is contacted for a live mandate, it moves through the investor process ladder. Every stage change writes an activity-log row โ that's the compliance audit trail.
| Stage | Meaning |
|---|---|
research โ approved โ queued | curation: identified, shortlisted, queued for a wave |
contacted โ responded | outreach sent; a reply came back |
nda โ meeting โ materials_sent | engaged: NDA, first meeting, deck/data sent |
diligence โ ioi โ term_sheet | progressing: diligence, indication of interest, term sheet |
committed ยท passed ยท dormant | terminal: won, declined (with a reason), or gone quiet |
A passed outcome records a reason from a fixed taxonomy (too early/late,
sector fit, geo fit, check size, valuation, portfolio conflict, no capacity, process timing, no response) โ
which feeds the learned ranker and the conversion analytics.
Glossary
| Term | Definition |
|---|---|
| Warmth owner | the Thunder teammate with the strongest relationship to a contact โ the best intro path. |
| Off-type | a firm of the wrong type for the deal's intent (e.g. a VC on a control-buyout mandate); deep-demoted to ~5% and sorted last. |
| Core vs expanded sector | a core sector is one the user actually named; expanded sectors are synonym matches used for recall only, at reduced weight. |
| Scoring lane | which weight table a mandate is scored with โ default (raise) or ma_sell (sale). Set by the mandate's intent, not chosen by hand. |
| Dream buyer | a firm the client named in the deal context. Scores the full deal-context weight and is promoted straight to tier 1 โ they asked for it. |
| Ecosystem partner | a platform or integration the seller is built on. Not a score bonus: it sorts ahead of unrelated firms inside the same tier. |
| Acquisition capability | sell-side only: evidence the firm has actually bought companies (deal count over 36 months, recency of the last close). |
| Control fit | sell-side only: whether the stake the firm typically takes (majority vs minority) matches the stake being sold. |
| Data confidence | a โ15 demotion for a record we don't trust enough to rank: no web domain, or no firm type. Usually a sign the row is an operating company or a person filed as a firm. The fix is the Data review queue; this only stops such rows ranking meanwhile. |
| EV capacity | sell-side only: what the buyer could plausibly pay โ market cap or enterprise value, else the largest cheque they've written, else a revenue proxy. Unknown is neutral. |
| Sweet spot / check size | a firm's typical single-investment size; the "range" is the set of check-size bands it invests across. |
| Mandate | a signed client engagement with economics (retainer, success fee, exclusivity, target size). |
| Pulse | recent public news about a firm or company, fetched live and summarized. |
| Community / list (contact tag) | a curated people group (e.g. "PEF") โ a searchable dimension independent of investor status. |
| Firmographics | a company's structured facts (revenue, headcount, funding raised, founded year, ownership), sourced from Inven. |
| IOI / LOI / term sheet | indication of interest โ letter of intent โ term sheet: escalating stages of buyer/investor commitment. |
GTM events
Go-To-Market โ Events productizes Thunder's private-event motion โ dinners (the founding case), breakfasts, roundtables, receptions (dinners.event_type; the invitation copy follows the type). Each event is a host engagement (engagements.intent = host_dinner, excluded from every deal list) plus a dinners row carrying date, city, metro (the hard location gate โ a London dinner only considers London people), venue, theme, the ideal-attendee description, an optional Luma link, and priority clients (linked client engagements whose matched investors get a boost on the invite list).
Invite-list score (0โ100), four components โ computed by graph/dinner-recommend.mjs, breakdown stored per row in recommendations.score_breakdown. The only LLM call in the pipeline parses the ideal-attendee text into targeting (prompt dinner-targeting-parse); the ranking itself is deterministic. Location is a hard gate, not a score: a candidate must match the dinner's metro (contact-level first; firm-HQ fallback is flagged on the row).
| Component | Max | What earns it |
|---|---|---|
| profile_fit | 35 | persona matches targeting (15) ยท firm type matches (10) ยท targeted seniority (5) ยท sector/keyword hit in title/thesis/tags (5) |
| client_association | 25 | the person's firm on a linked priority client: live funnel row (10) ยท shortlisted/upvoted recommendation (8) ยท positive match feedback (4) โ each ร the link's weight, summed, capped |
| warmth | 30 | warmth_score/100 ร 20 ยท Swarm 2nd-degree connection (strong 6 / medium 4 / any 2) ยท prior dinner/event attendance (checked-in 8, RSVP'd 4, +2 per extra event, cap 10) |
| reachability | 10 | verified email 4 (unverified 2) ยท LinkedIn URL 3 ยท touched in the last 90 days 3 |
The dinner funnel (v.65). Committing the shortlist creates one funnel row per guest (investor_process, source dinner, no mandate) and the 4-touch plan dinner_invite: email 1 โ email 2 (+4 business days) โ LinkedIn invite-or-DM by connection state (+3bd) โ final email (+5bd), every draft approval-gated and sent by the same windowed scheduler as deal campaigns. The dinner stage ladder ends rsvp_yes | declined โ attended; those stages sit outside the scheduler's arming gate, so an RSVP/decline/check-in automatically freezes the guest's remaining touches. RSVP state flows from the Luma guest CSV (luma_attendees) nightly, on every fresh import, and on demand; guests registering under an unknown email are linked by a human on the RSVPs tab. The capacity projection (guests ร touches vs mailboxes ~40/day, a 0.5 share of the LinkedIn budgets, +12 business-day cadence span) is recomputed live and warns when the projected last touch lands within 3 days of the dinner.