Ingest — two workflows, one roster
We start from the delegate contact list exported from the event’s in-app attendee list — not a clean account list. So one roster drives two linked workflows: a contact workflow (who is this person) and an account workflow (what company do they represent). Everything below is a real piece of code doing one job, and each step hands its number to the next.
| Off the roster | Count |
|---|---|
| Distinct companies | 677 |
| Delegate contacts | 1,150 |
| Companies that arrived with a usable domain | ≈ 87 |
| Contacts with an email or LinkedIn | almost none |
The roster is names only — nothing to match or enrich on yet. Everything after this manufactures the data we need. Tool: made-event-scraper (Firecrawl) + the in-app export.
Find the domains — 677 → 659
A name can’t be matched or enriched, so our domain-finding code resolves each of the 677 companies to its real web domain. This is the unlock — nothing downstream can run without it.
| Companies with a domain | Count |
|---|---|
| At ingest | ≈ 87 |
| After domain-finding | 659 of 677 |
| No domain found (held for manual review) | 18 |
Tool: run_event_domain_finds.
Match to our accounts database
With domains in hand we check every company against our accounts database (Made’s canonical account records) by exact domain. Of the 677, 359 already existed in the database; the rest are net-new candidates that get carried into the next steps rather than dropped.
| Of the 677 companies | Count |
|---|---|
| Matched to an existing account | 359 |
| Not yet in the database (net-new candidates) | 318 |
Contacts ride along — each delegate is attached to their company. Tools: promote_event_to_registry (domain match) · match_event_contacts_to_leads.
Classify — who is a buyer
Next we decide what each company is. This is a fast, cheap name + domain triage — an LLM reads the company name and website (for the matched ones, we already carry a classification in the database) and sorts each into a therapeutic developer (our buyer) or the ecosystem around them. It’s deliberately lightweight: its job is to decide who’s worth pursuing, not to enrich. 230 are developers; the other 447 are ecosystem, held on a separate track — not thrown away.
| Classification of the 677 | Count | Goes where |
|---|---|---|
| Therapeutic developers (buyers) | 230 | into the engine → |
| Ecosystem — other | 313 | separate track |
| Ecosystem — tools / vendors | 77 | separate track |
| Ecosystem — CDMO / CRO | 32 | separate track |
| Ecosystem — academic | 25 | separate track |
Name + domain only — no Clay yet. Firmographic enrichment comes next, and only for the accounts we’re keeping. Tool: classify_event_companies_icp (LLM triage).
A name-only pass isn’t enough — so a strict second check reads each company’s own L3 website and removes anything that isn’t a therapy developer (advisors, CDMOs, tools/vendors a name pass let through). That took the set from 230 to 210 true developers; the 20 removed join the ecosystem track.
New vs. known developers
So of the 230 developers — did we already have them? Mostly, but not all. 173 were already in our accounts database; 57 were genuinely new therapeutic developers we discovered at this event and minted into the database (human-approved, each given a Made-ID). Every attending developer is now in the database, 100% matched. (A later strict re-check then removed 20 non-developers from this matched set — leaving 210 true developers.)
| The 230 therapeutic developers | Count |
|---|---|
| Already in our accounts database | 173 |
| Net-new — discovered here + minted | 57 |
Tools: the orphan-seeder (dedup-guarded mint) + promote_event_to_registry (link-back).
Enrich the developer accounts — Clay
Now that we know who we’re keeping, we enrich them. Every developer account in our database is pushed through Clay to pull full firmographics — size, financing, location, modality signals. This is enrichment for the dossier and the messaging, not the buyer decision (that was step 04). Nearly every one of the 210 developer accounts came back with firmographics; a handful had no record on their domain.
| Clay company enrichment | Count |
|---|---|
| Developer accounts pushed to Clay | 210 |
| No firmographic data on the domain | 7 |
Clay only runs on companies that live in our accounts database — we don’t spend it on the ecosystem we set aside. Tool: Clay “Made Company Enrichment” — the push carries supabase_id so the enrichment writes back.
Contacts at the target accounts
Now the two workflows converge. Of the 1,150 delegates who attended, we keep the ones who actually sit at one of the 210 developer accounts: 319 contacts. Those are the people who matter — everyone else belongs to the ecosystem companies we set aside.
| Delegate contacts | Count |
|---|---|
| Total on the roster | 1,150 |
| At a therapeutic-developer account (carried forward) | 319 |
Reach the contacts — find email & LinkedIn
The 319 came in as names, so FullEnrich finds each one’s work email and reverse-finds their LinkedIn. We do this before enriching them, because Clay’s person enrichment keys on the LinkedIn URL.
| Of the 351 contacts | This run | Total now |
|---|---|---|
| Email found | +468 | 283 |
| LinkedIn found | +92 | 279 |
Tools: FullEnrich — find-email + reverse-find LinkedIn.
Enrich the contacts — Clay
Of the 279 with a LinkedIn, 278 are enriched through Clay to pull their full profile — headline, experience, background — the raw material the persona classifier reads next.
| Clay contact enrichment | Count |
|---|---|
| Contacts enriched | 278 |
Tool: Clay “Made Contact Enrichment” (push carries supabase_id).
Persona — one standardized buyer segment each
Our persona code runs over each of the 319 (title + Clay profile) and assigns exactly one standardized Made buyer segment — the segment the messaging agent reads to pick an angle. Contacts outside our buyer model are tagged NOT_ICP and suppressed.
| Persona | Count | Count | |
|---|---|---|---|
| C-suite | 171 | Regulatory | 11 |
| BD / commercial | 65 | Research | 10 |
| Process dev / eng | 12 | Manufacturing | 6 |
| Quality / analytical | 4 | Clinical | 4 |
| NOT_ICP (suppressed) | 68 |
Tool: classify_contact_persona.
Map to the CRM — Salesforce + HubSpot
With emails and identities in hand, we cross-reference every account and contact against Salesforce and HubSpot — broken out fully, so a rep knows exactly what relationship already exists before a single message goes out. This runs after we’ve found emails, because the email is a match key.
| Accounts (of 230) | Count | Contacts (of 351) | Count |
|---|---|---|---|
| Current customer | 3 | Customer contact | 4 |
| Open opportunity | 13 | In an opportunity | 24 |
| Prior opportunity | 21 | Known in HubSpot | 72 |
| Net-new (no relationship) | 193 | HubSpot MQL | 5 |
| Salesforce lead | 17 |
None were in a prior outbound campaign — this cohort is net-new to outreach. Tools: tag_event_crm_alignment + enrich_event_crm_from_reporting.
The canonical account hub — L3 scrape + live APIs + news
For each of the 210 developers we assemble ONE canonical intelligence record: our L3 scraper reads the company’s own website, and we pull real, sourced signals from live life-science data and our stored news history. (The CRM footprint from step 11 folds into this same record.)
| Source | What it contributes | Coverage |
|---|---|---|
| L3 web scrape | The company’s own site: what they do, modality, manufacturing posture, GMP status, CMC leadership, named CDMO partners, platform. 12 pending — unreadable domains (IR sub-sites / redirects). | 218 |
| ClinicalTrials.gov | Pipeline, phase, NCT identifiers. | 154 |
| SEC EDGAR | Financing & funding filings. | 82 |
| News history | Items from our months of stored news pertaining to these accounts. | 56 |
The Account Intelligence pages are the per-account manifestation of this record — re-enrich the backend and the page updates itself. Tool: run_event_l3_scrape + the LS-intel API pullers.
Map to territory & owner
With everything known, we route each of the 210 developers — twofold, in a strict order: (1) the Salesforce owner if that owner is one of our reps — an owner links to one person; else (2) the geographic territory, which links to a group of two reps — EAST = Chat + Simona, WEST = Karen + Simran; else (3) Joe as the international / no-signal catch-all. Owner and territory are tracked separately, so a pair can split or trade within their region.
| Route | Accounts | Contacts |
|---|---|---|
| US-East (Chat + Simona) | 124 | 155 |
| US-West (Karen + Simran) | 42 | 43 |
| International / unassigned (Joe) | 64 | 153 |
Of these, 27 carry a Salesforce owner who is a rep (that person wins over territory). Tool: reconcile_event_tiers (territory/owner derivation).
Tiers — reps, this is where we need your help
Using everything above — buyer fit, CRM relationship, pipeline, persona coverage — Greg has pre-assigned every one of the 210 developers a tier. This is the one call that gates the whole engine, and it’s where the reps come in: review your accounts and adjust the tier where you know better.
| Tier | Who | What happens |
|---|---|---|
| Tier 1 (16) | Customers & live opportunities | The rep owns it; we can back them with bespoke assets. |
| Tier 2 (34) | CRM-known or high-fit prospects | The rep decides; we build supporting assets. |
| Tier 3 (160) | Net-new developers | The cohort the automated engine runs. |
Set the tiers in the Rep Console — changing a tier or owner there writes back immediately and realigns everything downstream. Nothing sends until the tiers are locked and the messages are approved.
Execution layer — the SSO Matrix agent writes it
Once the tiers are locked, every Tier-3 account receives a coordinated combination of email, LinkedIn, and event-portal messages, managed by Greg and the marketing team. The SSO Matrix agent writes each one: for a single contact it reads who they are, what account they’re at, the account’s modalities and cell-sorting type (from the L3 scrape), and the contact’s Clay profile + persona — then maps to the SSO system to choose one value proposition + one pain point + a call-to-action to meet at the event, and drafts the message for that channel.
| Channel | How the agent writes it |
|---|---|
| A 3-step sequence — each step a fresh angle, same meet-at-Mesa invite. | |
| Connection-only campaigns, monitored; the follow-up message is drafted through the messenger for once an invite is accepted. | |
| Event portal | A short in-app attendee message, no signature. |
See the real drafts on the Messaging page — by rep, by channel. Tool: the MADE SSO agent (select-then-write matrix).
Response handling — Greg in the Campaign Tasks hub
Execution and response are separate jobs. Greg manages the response side in the Made AI Campaign Tasks hub: view every accepted LinkedIn connection and send the follow-up, manage portal messages in the event hub, and triage replies. Email sends run through the EmailBison setup (separate sending domains to protect deliverability), which Greg also manages from the Campaign Tasks page. Every send, reply, and connection is compiled back into the numbers.
One repeatable system
Every step above is a named piece of code that hands its number to the next. Swap the roster and the whole chain re-runs — find domains, match, enrich, classify, reach, persona, CRM-map, build the hub, route, tier, write, send — feeding the same commercial engine every time.