BioCreative Strategies × CARR Biosystems Azure Migration Program

Platform Value & System Overview

What the CARR platform is and does today - the context beneath the migration.

CARR System Overview

Download .docx

CARR Biosystems Intelligence Platform — System Overview

For: CARR Biosystems Leadership & BioCreative Internal | Version: 3.5 | Date: May 11, 2026 | Prepared by: BioCreative Strategies


What Is This Platform?

The CARR Biosystems Intelligence Platform is a custom-built web application that gives your team a single place to see every company in the cell & gene therapy space, track competitors, manage your sales pipeline, run LinkedIn + email campaigns, and access deep market research — all updated automatically.

Think of it as your team's command center for market intelligence and sales operations.


The Data Journey — How Your Database Was Built

Your platform didn't start empty. Every account in the system went through a structured data pipeline before your team ever saw it. Here's how:

Step 1: Initial Seeding from BioCreative Hub

BioCreative maintains a master database of 17,290 life science companies (100% classified, 0 unclassified) with 228,000+ contacts, 3,400+ clinical trials, 2,900+ NIH grants, 2,900+ patents, and 2,800+ SEC filings. We ran sync_cgt_accounts_from_hub() to pull the CGT-relevant subset into CARR:

  • 845+ CGT accounts inserted (219 therapeutic developers, 56 CRO/CDMOs, 570 academic institutions)
  • Filtered by CGT keywords in company descriptions and relevant subcategories
  • Deduplicated by domain against existing records

Step 2: CARR's Own Company List Merged

Jake and Dan provided CARR's existing ~1,100 company list. We processed it through our import pipeline:

  • carr_account_import_v1.ipynb — Cleaned, normalized, and loaded into the database
  • carr_account_matcher.py — Matched CARR's list against Hub records (548 exact matches, 202 fuzzy matches, ~300 net-new)
  • Net-new accounts were imported back to the Hub master DB for future enrichment
  • Result: ~2,050 total accounts after merge

Step 3: Contact Import

Contacts came from multiple sources across two rounds:

  • Round 1 (Mar 3): ~1,076 contacts migrated from Hub across ~136 accounts
  • Round 2 (Mar 4): 4,684 contacts from PhantomBuster/Clay scraping imported via Hub
  • LinkedIn URL backfill: 2,195 of 2,598 ICP accounts now have LinkedIn URLs (84% coverage)
  • Round 3 (May 11): 2,021 contacts from Clay Find-People pipeline synced via import_hub_contacts_v2 RPC. Also auto-created 220 new companies in CARR.
  • Current total: 104,333 contacts across the database (81,301 from Hub, 22,983 from sync, 49 from HeyReach)

Step 4: Life Science API Intelligence

We matched real-world research data from public APIs to your accounts:

  • ClinicalTrials.gov1,778 clinical trials matched to CARR accounts by sponsor name
  • NIH RePORTER1,842 NIH grants matched to academic institutions by organization name
  • SEC EDGAR → SEC filings for public CGT companies (viewed live from Hub)
  • PatentsView → Patent data for CGT companies (viewed live from Hub)
  • These sync automatically every Sunday to pick up new trials and grants

Step 5: AI Classification & Enrichment

Every non-academic account went through a multi-layer enrichment pipeline:

Hub L2 Deep Research (synced automatically from BioCreative Hub):
- 22-key JSONB with clinical phase, funding stage, technology platform, therapeutic modality, pipeline products, total funding, key investors, competitors, and more
- 2,973 accounts now have rich Hub L2 data (75% coverage)
- Also syncs: human_summary, ai_summary, sp_target_tier, ai_modality

CARR-Specific Enrichment (carr_account_enrichment_v1.ipynb v2):
1. Light Enrichment — Web search to gather basic company info (skips accounts with Hub L2 data)
2. Classification — AI categorizes: therapeutic_developer, service_provider, academic_institution, etc. + subcategory (td_clinical, service_cdmo, etc.)
3. Deep Enrichment — CARR-specific intel stored in carr_enrichment_data: centrifugation relevance, manufacturing scale, bioreactor type, competitors, key partnerships. Hub enrichment_data is preserved as-is.
4. ICP Scoring — Deterministic scoring using both Hub L2 and CARR enrichment data

Result: 3,945 accounts with icp_segment (99.6%), 2,323 with ICP tier. Academic accounts get intelligence from grants/trials rather than enrichment. Total ICP-relevant: 3,404 of 3,960.

Step 6: Data Cleanup & Normalization

Multiple cleanup passes ensured data quality:

  • carr_status normalized from 21 dirty variants → 6 clean values, then mapped 1:1 into account_tier (now labeled "Account Status" in the UI). The carr_status column is retired from the UI.
  • funding_status normalized from ~85 free-text values → 13 clean enums (seed, series_a, public, private, etc.)
  • modalities[] backfilled from classification for 1,268 accounts
  • is_icp_relevant flag set: 3,946 relevant, 530 non-ICP (financial partners, generic service providers)

Step 7: Account Operating Model Applied (March 2026)

The newest layer — a structured pre-pipeline qualification system:

  • Account Status assigned (account_tier column): unreviewed, cold, validated_target, nurture, pipeline_ready, customer, disqualified, parked
  • Buying Intelligence fields: buying_mode, budget_confirmed, fit_confirmed
  • Pipeline Gate Logic: An account is "pipeline ready" when buying_mode is growth/trouble/overconfident AND budget AND fit are confirmed
  • Gold Sheet tab added to every account detail page — consolidated intelligence view

Where Does the Data Come From?

Your platform pulls data from 5 sources, most of it automatically:

1. BioCreative Life Science Database (the "Hub")

The master database of 17,290 life science companies (100% classified) that BioCreative maintains.

  • 3,946 companies in your database (3,391 are ICP-relevant targets)
  • 102,153 contacts across those companies (7,623 with email)
  • 386 news articles from industry sources
  • 1,778 clinical trials matched to your target accounts
  • 1,842 NIH grants matched to academic institutions

1b. BioCreative Academic Intelligence Pipeline (from the Hub)

A dedicated research intelligence system that tracks academic institutions, their labs, and principal investigators:

  • 4,842 labs synced from the Hub (research focus, PI, website, email, therapeutic areas)
  • 14,019 principal investigators synced (8,136 with email, 2,304 linked to labs)
  • ~751 academic institutions with hierarchy data (parent/child relationships)
  • Data sourced from NIH grants (2,395 PIs), ClinicalTrials.gov (2,059 PIs), and GlobalData (9,565 PIs)
  • Lab discovery via Brave Search + AI parsing of lab websites

2. HeyReach (LinkedIn Outreach)

  • 32 campaigns across 5 LinkedIn accounts (including 10 follow-up infra campaigns configured per sender)
  • 629 leads loaded across all campaigns, 530 connection requests sent, 86 accepted
  • Automated lead list creation: create-heyreach-lead-lists edge function creates HeyReach lists from campaign contacts
  • Automated send pipeline: send-linkedin-messages edge function delivers ready_to_send outreach messages via HeyReach API (pg_cron every 2h)
  • Reply capture: heyreach-webhook (v25) receives all 11 HeyReach event types and links replies back to outreach messages
  • Campaign/lead sync every 6 hours via pg_cron

3. EmailBison (Email Outreach)

  • 6 sending email accounts connected across 3 domains: explorecarr.com, carrbiosystemsoutreach.com, carrbiosystemsconnect.com
  • Each account linked to a sending persona (Jacob Andrews, Jeff Plambeck, Andrew Hallet, Bethanne Deuel, Nico Summaria)
  • Currently warming — inboxes are building reputation before campaign launch (0 active campaigns)
  • Full automation deployed: Sync pulls campaigns/contacts/stats every 6h, Push sends ready_to_send outreach every 2h, Webhook captures real-time events (opens, replies, bounces)
  • See EMAILBISON_MODULE.md for the complete technical reference

4. AI-Powered Tools (March 2026)

Outreach Message Generator

Inside the Campaigns page, click any contact's "Generate" button to create a personalized LinkedIn or email message. The AI combines 5 data layers into a single prompt:

Data Layer Source Table What It Provides
Contact Role Classification contacts.marketing_persona + contacts.segment_data 6 classified buyer personas (executive, technical, research, operations, quality_regulatory, clinical) + rich classification payload (persona_summary, messaging_angle, pain_points, value_hook, buying_context, decision_role)
Account Enrichment companies.enrichment_data Centrifugation relevance, manufacturing scale, separation technology, bioreactor type, key partnerships
Client Positioning client_config.outreach_positioning CARR products, 5 value proposition pillars (matched to recipient's role), competitors, 7 ICP groups, Path to Patients program benefits, banned/preferred vocabulary, tone rules, publications, cell type positioning, messaging variant configs
Sender Identity team_profiles LinkedIn headline, about section, position description — AI writes in the sender's voice
Account Category companies.primary_category Therapeutic developer, CRO/CDMO, academic, investor, service provider — changes the framing

6 role-based messaging personas — Each maps to specific pain points, value propositions, and a messaging angle (e.g., Technical → "technical expertise" angle with "scaling bench to GMP" pain points). Commercial/Sales/Marketing roles are excluded from outreach (they don't buy centrifuges). These are woven naturally into messages, never listed explicitly.

5 message types: Connection Request (300 chars), Connection Follow-up (600 chars), InMail (1,900 chars), Cold Email (600 chars), Follow-up Email (400 chars).

2 messaging variants (A/B):
- Traditional — Professional, curious, brief industry connection. Soft opening with open-ended questions.
- Path to Patients — Purpose-driven, consultative. Leads with shared purpose of getting therapies to patients faster. Frames CARR as a partner, not a vendor.

3 entry points:
1. Campaign Contacts — Full outreach modal with all types, both variants, enrichment badges, and role classification
2. Lead Follow-up — Lightweight modal for HeyReach accepted connections, sender auto-matched from login
3. Batch Generation — Bulk generation by buying persona + ICP tier via campaign_goals, with EmailBison push

AI models: Claude Sonnet 4 claude-sonnet-4-20250514 (primary), GPT-4o-mini (fallback). Edge function: generate-outreach-message (v32/deploy v42). Batch: batch-generate-outreach.

Outreach Messaging Matrix

A DB-driven messaging strategy table (outreach_messaging_matrix) that maps ICP segments × buying personas to pain points, value props, messaging angles, and hook types. The AI outreach generator calls resolve_messaging_strategy() to find the best-matching strategy for each contact.

  • CARR-specific seed data: Therapeutic Developers (5 personas), CDMOs (3 personas), Academic (2 personas), plus default fallbacks
  • Scoring algorithm: Matches on modality, platform type, clinical stage, and company size
  • 3-tier resolution: DB matrix → hardcoded SSO matrix → category fallback

Contact Intelligence

The Contact Intelligence Modal provides a 3-tab deep view of any individual contact, accessible from Account Detail (Contacts tab), Target Universe (Review Panel), and Campaign Contacts:

  • Profile & Classification — Marketing Persona (Decision Maker, Budget Holder, Technical Evaluator, Internal Champion, Day-to-Day User, Procurement/Legal), Buying Persona (Miller Heiman roles), decision maker toggle, outreach status tracking, tags, notes, opportunity associations, campaign history
  • Engagement Timeline — Chronological view of outreach messages, campaign enrollments, and opportunity associations from v_contact_engagement_timeline
  • Actions — Follow-up scheduling (auto-creates Task Center tasks), contact info summary, engagement counters

Contact Classification:
- L1 (Seniority)classify_contacts_seniority() parses job titles into 7 levels (C-Level, VP, Director, Manager, Senior, Mid-Level, Junior)
- L2 (Buyer Segment)buyer_segment, seniority_classified, decision_role, segment_confidence, segment_data columns for AI-powered enrichment
- Stats view: v_contact_classification_stats provides aggregate classification metrics

Content Studio

AI-powered LinkedIn post creation using your team's voice profiles, hook library (8 styles), and content pillars (5 themes). Multi-source synthesis from news and custom input. Drafts only - a human reviews and posts; there is no automated posting. Edge function: generate-content.

Brand & Positioning Data Layer (March 2026)

All AI-generated content and outreach messages are now brand-aligned through a structured data layer:

  • 4 master reference documents were created from a full Firecrawl site scrape of carrbiosystems.com (44 pages), 8 PPTX positioning decks (Path to Patients, Allogeneic, iPSC, Scalability, Cell Processing Platform, etc.), and CARR's internal input documents
  • outreach_positioning database config (~17K characters) stores the EF-consumable version: company identity, mission, tagline, value pillars, products with specs, competitive matrix (6 head-to-head comparisons), 7 ICP groups, Value Proposition Canvas (5 pillars), Path to Patients program (pricing, rentals, buyback), 6 role messaging overrides, tone rules, banned phrases, preferred vocabulary, publications, and cell type positioning
  • The AI outreach generator matches VPC pillars to the recipient's role (e.g., Manufacturing → High Performance + Scalable Processing; Quality → Closed System + Automation) and injects Path to Patients benefits when using the P2P messaging variant
  • The AI content generator uses the full positioning context (mission, products, competitors, tone rules, vocabulary) to ensure every LinkedIn post, email, and InMail reflects CARR's authentic voice

This means the AI writes with CARR's actual product specs, competitive advantages, and approved language — not generic industry phrasing.

5. Manual Input (Your Team)

  • Pipeline opportunities — create and manage in Pipeline page
  • Events — add industry events in Event Intelligence
  • Tasks — create in Task Center
  • Targeting actions — review and classify accounts in Target Universe

What Updates Automatically?

8 automated sync jobs run without any action from your team:

What Syncs How Often What It Does
News Articles Every 4 hours Pulls new CGT industry news from the Hub
HeyReach Campaigns Every 6 hours LinkedIn campaign stats, leads, connections
LinkedIn Message Delivery Every 2 hours Sends ready_to_send outreach messages via HeyReach API
EmailBison Sync Every 6 hours Email accounts, campaigns, contacts, daily stats from EmailBison API
EmailBison Push Every 2 hours Pushes ready_to_send email outreach messages to EmailBison campaigns
New CGT Companies Weekly (Sunday 2am) Adds newly discovered CGT companies from the Hub
Clinical Trials Weekly (Sunday 3am) Matches new clinical trials to your target accounts
NIH Grants Weekly (Sunday 4am) Matches new NIH grants to academic targets

Account Operating Model

Your platform uses a structured approach to move accounts from raw data to closed deals. Think of it as a funnel with two distinct zones:

Pre-Pipeline: Target Universe (Account Status)

Every account starts as Unreviewed and moves through statuses as your team learns more:

Status Meaning What Happens Here
Unreviewed Not yet looked at Default state for newly added accounts. Nobody has reviewed the Gold Sheet yet.
Cold Reviewed, no engagement Account has been reviewed but no outreach or engagement yet.
Validated Target Confirmed CARR fit Team has confirmed this is a real target worth pursuing.
Nurture Periodic touch Not ready to buy now, but worth staying in touch with. Monthly/quarterly follow-ups.
Pipeline Ready Gate passed Buying mode + budget + fit all confirmed. Ready to create a formal pipeline opportunity.
Customer Existing customer Already using CARR products. Focus on expansion and retention.
Disqualified Not a fit Wrong modality, no budget, competitor locked in, etc.
Parked Temporarily shelved Might be relevant later. Acquisition in progress, leadership change, etc.

Pipeline Gate

An account is Pipeline Ready when three conditions are met:
1. Buying Mode is Growth, Trouble, or Overconfident (not Even Keel or Unknown)
2. Budget Confirmed — they have budget allocated or can get it
3. Fit Confirmed — CARR's products solve their specific problem

When the gate is met, the account can be promoted to a formal pipeline opportunity.

In-Pipeline: Sales Pipeline (Miller Heiman Strategic Selling)

Once an account passes the pipeline gate, opportunities are tracked through 5 active stages:

Stage Probability What's Happening
Strategic Foundation 20% Blue Sheet live. Mapping all buying influences, identifying Coach, defining Single Sales Objective.
Stakeholder Alignment 40% Building individual relationships and win results per stakeholder. Green Sheets per call.
Solution Development 60% Translating CARR's offering into account-specific language. Solution scoring against criteria.
Proposal & Navigation 75% Formal proposal out. Navigating Economic Buyer, Technical Buyer objections, internal politics.
Best Few / Close 90% All red flags resolved. Close mechanics — contract, budget release, timeline.

Plus Closed Won (100%) and Closed Lost (0%).

Gold Sheet (Account Detail — First Tab)

Every account has a Gold Sheet tab — a single-page intelligence summary showing:
- Account Identity — Category, development stage, ownership, founding year, employee count, HQ location, territory, Account Status, source of identification
- Buying Intelligence — Buying mode, budget confirmed, fit confirmed, current solution, warm intro availability, champion identified, competing vendors
- Signal Counts — contacts, pipeline opps, clinical trials, NIH grants, news articles
- Active Pipeline Opportunities — with stage, deal value, and Single Sales Objective
- Recent Activity — targeting actions, tier changes, reviews

Blue Sheet / Meeting Prep (Opportunity Detail — 5th Tab)

Every pipeline opportunity has a Meeting Prep tab implementing the Miller Heiman Blue Sheet methodology:

  • Pre-Flight Wizard — Before creating a Blue Sheet, a checklist wizard helps classify opportunity contacts (buying role + relationship strength), set a stage-appropriate meeting objective (with suggested goals per pipeline stage), and define an advancement goal. Contact classifications are saved, and the data pre-fills the Blue Sheet form.
  • 8-Section Blue Sheet — Objectives, Prospect's Concept, Questions Planned (confirmation / new information / attitude), Information to Share, Commitment to Request, Credibility Elements, Anticipated Objections, Post-Meeting Debrief.
  • DOCX Export — Full Blue Sheet exported as a formatted Word document.
  • Task Center Integration — Upcoming meetings with preps in "planning" or "ready" status appear as Task Center tasks with priority based on meeting proximity.
  • Debrief → Pipeline Activity — Completing a debrief auto-logs a pipeline activity with learnings, red flags, and next actions.

What Each Page Does

Dashboard (/)

Landing page with at-a-glance stats: total companies, contacts, and recent news.

Markets

Page What It Does
Accounts Browse and filter all 3,946 companies. Filter by Account Status, category, subcategory, region, sales rep, modality, therapeutic areas, clinical phase, development stage, funding status, company size, and more. Click any company to see its full profile.
Account Detail Deep profile for each company. Gold Sheet (first tab) shows consolidated intelligence. Therapeutic developers get 11 tabs; academic institutions get 14 tabs (adds PIs, Labs, Children). Includes clinical trials, NIH grants, SEC filings, patents, CARR fit assessment, pipeline opportunities, news, and engagement history.
Academic Market Dedicated academic institution explorer. 6 stat cards (institutions, labs, PIs, trials, grants, contacts), filterable table with labs/PIs columns, parent-only toggle, clickable parent links, CSV export. Click any institution for a 6-tab detail view (PIs, Labs, Children, Contacts, Clinical Trials, NIH Grants).
List Builder Advanced contact search across 102,153 contacts. Filter by seniority (C-Level, VP, Director, etc.), department, company attributes. Export filtered lists as CSV for campaigns.

Intelligence

Page What It Does
News 386 industry news articles with priority scoring, competitor mentions, and opportunity flags. Auto-syncs every 4 hours.
Events Track industry events (conferences, trade shows). Add events manually.

Operations

Page What It Does
Target Universe Pre-pipeline command center. Review 3,391 ICP-relevant accounts. Set Account Status, buying mode, budget/fit flags. Assign reps, set follow-up dates, bulk-update. Pipeline gate indicator shows when accounts are ready to promote.
Campaigns Unified view of all LinkedIn (HeyReach) and email (EmailBison) campaigns. 18 UX campaigns, 5 sending personas. See sends, opens, replies, connections.
Pipeline Miller Heiman Strategic Selling pipeline with 5 active stages. Create opportunities with Single Sales Objective. Track contacts by buying role (Economic, User, Technical, Coach, Champion). Drag-and-drop stage changes. 6 products tracked. Opportunity detail has 5 tabs: Strategy, Timeline, Contacts, Research, Meeting Prep (Blue Sheet with Pre-Flight Wizard).
Content Studio LinkedIn content creation: hook library (8 hooks), content pillars (5 themes), AI-assisted post generation.
Team Profiles Voice interview → AI-generated LinkedIn profile and content style guide per team member.

Analytics & Other

Page What It Does
Metrics Full analytics: company breakdowns by Account Status/category/modality/phase, contact metrics by seniority, Hub research matching stats.
Research Library 30 deep research documents: 6 domain reports, 12 deep research studies, 4 strategic frameworks, 8 positioning decks — all specific to CGT centrifugation market.
Task Center Unified task inbox from 8 sources: manual tasks, meeting action items, pipeline next actions, target follow-ups, contact follow-ups, onboarding tasks, pipeline follow-ups, and meeting preps (upcoming Blue Sheets).
Settings Client configuration and sync history (1,972 logged operations).

The Bigger Picture

┌──────────────────────────────────────────────────────────────────────┐
│                     EXTERNAL DATA SOURCES                            │
│                                                                      │
│  ┌──────────────┐        ┌──────────┐        ┌────────────┐         │
│  │ BioCreative  │        │ HeyReach │        │ EmailBison │         │
│  │ Life Science │        │ LinkedIn │        │   Email    │         │
│  │   Hub DB     │        │ Outreach │        │  Outreach  │         │
│  │  17,290      │        │24 camps  │        │ 6 accounts │         │
│  │  companies   │        │campaigns │        │ 3 domains  │         │
│  └──────┬───────┘        └────┬─────┘        └─────┬──────┘         │
│         │                     │                    │                 │
│    every 4h +            every 6h           every 6h sync           │
│    weekly                (pg_cron)          every 2h push           │
│                                             + real-time webhook      │
└─────────┼─────────────────────┼────────────────────┼────────────────┘
          │                     │                    │
          ▼                     ▼                    ▼
┌──────────────────────────────────────────────────────────────────────┐
│                   CARR BIOSYSTEMS DATABASE                            │
│                                                                      │
│  Companies: 3,946    Contacts: 102,153   News: 386                 │
│  Clinical Trials: 1,779   NIH Grants: 1,842                        │
│  Campaigns: 18 UX / 32 HR   Leads: 629   Research Docs: 30         │
│                                                                      │
│  Academic: 4,842 Labs  ·  14,019 PIs  ·  751 Institutions           │
│  81 database views  ·  82 functions  ·  11 automated cron jobs      │
└───────────────────────────────┬──────────────────────────────────────┘
                                │
                                ▼
┌──────────────────────────────────────────────────────────────────────┐
│               ACCOUNT OPERATING MODEL                                │
│                                                                      │
│  ┌─────────────────────────────────┐   ┌──────────────────────────┐ │
│  │  PRE-PIPELINE (Target Universe) │   │  IN-PIPELINE (Pipeline)  │ │
│  │                                 │   │                          │ │
│  │  Unreviewed → Cold → Validated  │──▶│  Strategic Foundation    │ │
│  │  → Nurture → Pipeline Ready     │   │  → Stakeholder Alignment │ │
│  │                                 │   │  → Solution Development  │ │
│  │  Buying Mode + Budget + Fit     │   │  → Proposal & Navigation │ │
│  │  = Pipeline Gate                │   │  → Best Few / Close      │ │
│  │                                 │   │  → Closed Won / Lost     │ │
│  └─────────────────────────────────┘   └──────────────────────────┘ │
└───────────────────────────────┬──────────────────────────────────────┘
                                │
                                ▼
┌──────────────────────────────────────────────────────────────────────┐
│                CARR INTELLIGENCE PLATFORM (22 pages)                  │
│                                                                      │
│  Markets:      Accounts · Academic Market · List Builder             │
│  Intelligence: News · Events                                         │
│  Operations:   Target Universe · Campaigns · Pipeline                │
│                Content Studio · Team Profiles                        │
│  Analytics:    Metrics · Research Library · Task Center               │
└──────────────────────────────────────────────────────────────────────┘

Key Workflows

1. Finding & Researching Target Companies

Accounts → filter by category, modality, clinical phase, therapeutic areas, funding status, region → click to see full profile → Gold Sheet tab for consolidated intelligence → Clinical Trials, NIH Grants, Patents tabs for deep research → move to Target Universe to set tier and assign rep.

2. Qualifying Accounts (Target Universe → Pipeline)

Target Universe → review account → set Account Status (unreviewed → cold → validated target → nurture) → assess Buying Mode → confirm Budget and Fit → when Pipeline Gate is met → create formal Pipeline Opportunity with Single Sales Objective.

3a. Building a Broad Campaign (List Builder)

List Builder → filter contacts by cell type, seniority, territory, department → select contacts → click "New Campaign" → name it, choose platform → set status to Active when ready → BioCreative launches in HeyReach/Bison within 24 hours.

3b. Building an Account-Specific Campaign (Account Detail)

Accounts → find target company → click into Account DetailContacts tab → filter by department and seniority → select the right people → add to campaign → set status to Active → BioCreative launches within 24 hours. Best for precise, account-level outreach.

4. Managing Sales Pipeline

Pipeline → create opportunity with Single Sales Objective → assign to stage → track contacts by buying role (Economic, User, Technical, Coach) → log activities → move through stages → close.

5. How New Accounts Get Added

  • Automatic: sync_cgt_accounts_from_hub() runs every Sunday — new CGT companies discovered in the Hub are automatically added to CARR
  • Manual request: Ask BioCreative to run the import notebook (carr_account_import_v1.ipynb) for a specific list
  • After import: New accounts enter as Cold tier, then go through the enrichment pipeline (classification → deep enrichment → CARR fit assessment) before they're ready for your team to review

6. Campaign Activation & Performance Tracking

Campaigns are created in Planning status. When the rep is ready, they set the campaign to Active — BioCreative builds and launches the campaign in HeyReach/Bison within 24 hours. Campaigns page shows all campaigns with sends, opens, replies, and connection rates by sending persona. Stats auto-update every 6 hours.

7. Staying on Top of Market Intelligence

News (updated every 4h) + Research Library (30 deep research docs) = comprehensive market awareness.


Data Pipelines — Behind the Scenes

These are the tools BioCreative uses to keep your data current. You don't need to touch these, but they're here for reference:

Pipeline Tool Schedule
Account Seeding sync_cgt_accounts_from_hub() Weekly (Sun 2am)
Academic Labs Sync sync_academic_labs_from_hub() Manual (re-runnable)
Academic PIs Sync sync_academic_pis_from_hub() Manual (re-runnable)
Academic Hierarchy sync_academic_hierarchy_from_hub() Manual (re-runnable)
Clinical Trials sync_clinical_trials_from_hub() Weekly (Sun 3am)
NIH Grants sync_grants_from_hub() Weekly (Sun 4am)
News sync_news_from_life_science() Every 4h
HeyReach Sync sync_all_from_heyreach() (pg_cron) Every 6h
EmailBison Sync pg_cron → EF sync-emailbison v1.2 Every 6h at :30
EmailBison Push push-to-emailbison edge function (pg_cron) Every 2h
EmailBison Webhook emailbison-webhook edge function Real-time
Account Import Colab notebook (carr_account_import_v1.ipynb) Manual
Contact Import Colab notebook (carr_contact_import_v1.ipynb) Manual
AI Classification Colab notebook (carr_unified_classifier_v1.ipynb) Manual
AI Enrichment Colab notebook (carr_account_enrichment_v1.ipynb v2) Manual
Contact Classification Colab notebook (carr_contact_classifier_v4.ipynb) Manual
LinkedIn Message Delivery cron_send_linkedin_messages() (pg_cron) → send-linkedin-messages EF Every 2h
Lead List Creation create-heyreach-lead-lists edge function Manual
HeyReach Reply Capture heyreach-webhook edge function (v2.2) Real-time

Questions? Contact BioCreative Strategies — this platform is fully managed and continuously updated.

Value Package - Index

Download .docx

CARR × BioCreative — Month 4 Walkthrough Package

For: Jake Andrews, CARR Biosystems
From: Brian Elbert, BioCreative Strategies
Date: May 14, 2026
Purpose: A layered tour of the system underneath the UX — what was built, how it works, what each layer would look like if assembled outside this engagement, and where the value compounds.


How to read this

The CARR Biosystems Intelligence Platform is twelve layers deep. The send-message button at the top of the app is one of them. The other eleven are what make any message worth sending.

This package walks through all twelve, one per file, in roughly the order data flows from raw inputs to a sent outreach. Each file is short enough to read in 5 minutes and is meant to be opened in any order — sections cross-link.

Where it's useful, each section ends with a "What this layer looks like elsewhere" note showing the typical commercial alternatives and rough pricing. That's not a sales pitch — the goal is to make the choices visible, so when CARR's team picks up parts of this system to run on their own, you know what you're choosing for and against.

This document is honest. It includes what's working at scale, what's working but underused, what's still in build/warm-up, and where the friction has been real on both sides.


The twelve layers

# File One-line summary
01 01_what_carr_gave_us.md The starting inputs from CARR — what we built on
02 02_market_intelligence_layer.md Brand bible, positioning, voice, design — derived from CARR's own decks + site
03 03_database_architecture.md Hub-and-spoke design, CARR's own Supabase, the sync pattern
04 04_account_universe.md 17K Hub TAM → 3,964 CARR-specific CGT accounts, ICP v2 scoring
05 05_account_enrichment_pipeline.md Hub L2 + CARR deep enrichment (centrifuge fit, separation tech, scale)
06 06_contact_discovery.md 104K contacts from PhantomBuster + Clay Find-People + Sales Nav
07 07_contact_enrichment_personas.md Clay full enrichment → 6-persona buyer classification
08 08_messaging_system.md 38-row SSO matrix, Path-to-Patients variant, account signals injection
09 09_live_intelligence_apis.md Real-time news, trials, grants, patents — auto-synced
10 10_outreach_infrastructure.md 3 warmed email domains, 5 HeyReach seats, EmailBison instance
11 11_supporting_assets.md Research docs, landing pages, branded assets, Edge Functions, custom scripts
12 12_market_alternative_costs.md The whole stack assembled commercially — rough cost reference
_appendix_citations.md External sources cited, linked

Quick-look numbers (live, May 13 2026)

Layer What it is Where it stands
Database CARR Supabase (drzxmokguptvwptuqjcv) 446 migrations, 18 Edge Functions, 95 views, 111 functions, 17 cron jobs
Accounts CGT-filtered universe 3,964 total · 3,406 ICP-relevant · ICP v2 scored · 7-status lifecycle
Contacts Discovered & loaded 104,333 total · 8,268 with email · 7,610 senior · 3,275 Clay-enriched
Personas L2-classified 3,558 contacts classified across 6 marketing personas
Messaging SSO matrix engine 38-row matrix (segment × persona) · 5 message types · 2 variants (Traditional + Path to Patients) · v55 EF deployed
Live intel Auto-refreshed 704 news articles · 1,862 trials · 5,000 NIH grants
LinkedIn HeyReach (5 seats) 37 campaigns · 765 leads loaded · 800 CRs sent · 157 accepted · 11 webhook events live
Email EmailBison + 3 warmed domains 5 mailboxes warmed · 4 evergreen campaigns staged · 0 sent (final activation pending)
Brand Master docs + DB-injected positioning 4 master docs · 30 research docs · 17K-char positioning JSON in client_config · 3 landing pages
Team UX React app 22 pages · 6 active users · LinkedIn/Email follow-up queues live
Engagement Months 1–3 10 meetings (~600 min) · 120+ email threads · 11 CARR/BW people engaged

Numbers source: docs/CARR_SYSTEM_OVERVIEW.md v3.5, docs/CARR_MONTH_THREE_REVIEW.md, docs/CARR_LAUNCH_READINESS_2026-05.md, docs/SSO_MATRIX_DEEP_DIVE_2026-05-11.md, live DB queries.


Honest framing — what's working, what's not, what needs CARR

Working at scale

  • Data plumbing. Hub → CARR sync runs weekly. News refreshes every 4h. ICP scoring, persona classification, message generation all reproducible from notebooks anyone can re-run.
  • Brand/positioning data layer. Every AI-generated message pulls from a 17K-char positioning JSON built from CARR's own decks + a 44-page Firecrawl of carrbiosystems.com. Banned phrases, preferred vocabulary, and Path-to-Patients framing are enforced at generation time.
  • Live intelligence. 1,862 trials and 5,000 grants are matched to specific accounts. Account signals are injected into outreach generation as of v55.
  • Infrastructure. All HeyReach + EmailBison plumbing is wired end-to-end. Webhooks live. Reply capture works.

Working but underused

  • 6-persona messaging matrix. 38 rows live in the DB. 2,650 contacts are persona-classified. The reps haven't yet sent at volume from this matrix.
  • Path-to-Patients variant. Wired in the EF; no UX control yet in the CARR app to toggle from traditional to path_to_patients per send.
  • Target Universe. 478 unreviewed accounts on Nico's desk alone — bulk-review UX exists but throughput is low.

Build/warm-up

  • EmailBison campaigns — 4 evergreen campaigns staged with 500 contacts loaded, 0 sent. Final activation pending vault-secret confirmation and rep sign-off.
  • HeyReach seats is_active=false — upstream seat-management quirk; auth is valid, sends still work via resumeFinishedCampaign:true, but this is on the bug list.

Where CARR's input has been the bottleneck

  • Pipeline opportunity list never shared (no source-of-truth deal list to map against the universe).
  • Paul (EMEA) and Kelvin (APAC) onboarding details never received — ~1,200 accounts can't activate without them.
  • Marketing team (Colleen) content priorities never received — Content Studio infrastructure live but no published output.
  • HubSpot / D365 access never granted.

This isn't blame — it's context. Several of these blockers are listed in docs/CARR_MONTH_THREE_REVIEW.md §7 as carried-from-Month-2 items. The work that was built worked around them; the work that's stalled needs them.


How this is meant to be used

  1. Today's meeting (May 14): Walk top-to-bottom, file by file, ~10 min per layer. Pause where it's most useful.
  2. Going forward: Treat each file as the canonical reference for that layer. When something in the UX feels broken, pull the matching file to see what's underneath, then triage with the right context.
  3. For Jake's own learning: Sections 03–08 are the data engineering and AI structure layers — the same patterns you'd build into the Azure environment you discussed with John Katsapis. The patterns transfer; the stack choice is yours.

Cross-references

  • docs/CARR_SYSTEM_OVERVIEW.md v3.5 — the platform overview written for CARR leadership; this package goes deeper on the layers underneath
  • docs/CARR_MONTH_THREE_REVIEW.md — honest Month 1–3 assessment, SOW vs delivered
  • docs/CARR_MONTH_FOUR_PLUS_ROADMAP.md — three forward options (VPS build / scale current / Azure migration)
  • EMAILBISON_MODULE.md, docs/runbooks/heyreach.md, docs/runbooks/emailbison.md — operational runbooks
  • docs/SSO_MATRIX_DEEP_DIVE_2026-05-11.md — canonical messaging system audit

What CARR Gave Us

Download .docx

01 — What CARR Gave Us (The Starting Inputs)

Parent: 00_INDEX.md · Reading time: 5 min · Tone: factual inventory, no judgment

This is the ground truth of what BioCreative had to work from at the start of the engagement and what arrived during it. Every layer downstream was built on these inputs plus what we sourced and enriched ourselves. Knowing this matters because it explains where the foundational positioning, voice, and target lists came from, and which parts of the system would benefit most from additional CARR input going forward.


Documents received (inventory)

Stored in carr-biosystems-hub/Inputs/:

# File Type Size What it gave us
1 Approved Email Templates. Evergreen429.docx Templates 19 KB Reference text for tone alignment in email cold + follow-up types
2 Brian and Jake connect_20260421.{docx,json,txt} Meeting transcript ~340 KB raw + transcript Strategy conversation, Jake's framing of priorities
3 Jake and Brian connect_20260424.{docx,json,txt} Meeting transcript ~310 KB raw + transcript Azure/Supabase discussion, Claude rollout, Forsythe context
4 Brian and Jake connect - news letter and any others_20260501.{docx,json,txt} Meeting transcript ~140 KB raw + transcript Newsletter direction, May handoff items
5 CARR_Biosystems_MSA_SOW_Combined (BW-CC rev. 2.5.26)_Accepted_for Sig-020626.pdf Contract 434 KB MSA + SOW — defines the 3-month engagement scope
6 CARR_MESSAGING_POSITIONING_REVIEW_JA Input 20260402.docx Positioning review 56 KB Jake's edits on the positioning doc — only formal CARR-side content edit received to date
7 CGT EE Scrape-US Accounts missing contacts.csv Account list 4.4 MB Early-stage account list (US-only, missing contacts)
8 DoNotContactList.xlsx Compliance list 9.5 KB Source for the 15-row do_not_contact_list table
9 Workflow for CBS Prospecting Target Universe.docx Process doc 21 KB CARR's existing prospecting workflow — baseline before the platform
10 contacts upload 032326.csv Contact list 4.6 MB March-vintage contact bulk for import staging
11 jeff_batch_for_clay-Default-view-export-1774647329637.csv Clay export 37 KB Jeff's batch for Clay enrichment (round 1)
12 nico_templates_parsed.txt Templates 9 KB Nico's preferred-template language → fed into writing-rules guardrail
13 unifuge-ufmini---product-sheet---07092024.pdf Product spec 406 KB UniFuge UF Mini spec sheet — feeds products block in positioning JSON

Also referenced but not in Inputs/:
- 8 PPTX positioning decks (Path to Patients, Allogeneic, iPSC, Scalability, Cell Processing Platform, etc.) — provided via SharePoint links, processed into research docs
- Recordings of meetings 1–10 (~600 minutes total) — transcribed, RAG-indexed, used for context


What's notably absent

These are gaps that have been called out in writing across CARR_MONTH_THREE_REVIEW.md §7 and prior reviews. Listing them here is for context, not to assign fault:

  • No pipeline opportunities file. No D365 / HubSpot export, no spreadsheet of active deals, no Closed-Won list. We have no source-of-truth "these are the accounts and contacts we are actively selling to right now" reference to map the universe against.
  • No formal ICP definition document from CARR. The ICP we built was reverse-engineered from the existing account list, public-domain CGT market structure, the positioning decks, and signals from CARR's product positioning (centrifuge/separation equipment → CGT manufacturing buyers).
  • No buyer interview transcripts. Pain points and value props are derived from CARR's marketing materials (Path-to-Patients deck, scalability deck), not from voice-of-customer recordings.
  • No CRM access. Made repeatedly through Savannah (Marketing Ops). Could not be granted at this time.
  • Paul (EMEA) and Kelvin (APAC) onboarding details never received. ~1,200 accounts in their territories cannot be activated for outreach without the necessary inputs (LinkedIn URLs, email domains, persona inputs).
  • No formal voice training message from Jake. Sender persona voice is derived from Jake's LinkedIn headline + about + email examples observed in meeting transcripts.
  • Limited messaging/positioning feedback turnaround. Jake provided one round on April 2; no formal sign-off cycle exists for subsequent positioning updates.

What was sourced or built where CARR didn't provide

This is the bulk of what's downstream in this package. Examples:

Layer If CARR provided What we did instead
ICP definition Reverse-engineered from existing accounts + CGT public-domain market structure (see 04_account_universe.md)
Voice of customer Synthesized pain-points from positioning decks + meeting transcripts + public CGT manufacturing literature
Target universe ~1,100 accounts (CARR's list) Merged with 17K Hub TAM, deduplicated, classified, enriched, ICP-scored → 3,964
Contact universe A few CSVs (jeff_batch + 03-23 upload) Discovered via PhantomBuster + Sales Nav + Clay Find-People → 104,333
Brand voice Master Brand Voice doc derived from website + decks + transcripts
Pricing structure UniFuge UF Mini product sheet only Pulled remaining product specs from public site + decks
Pipeline opportunities Empty — Pipeline page exists, no data flowed in

What this means going forward

The system is built. It works whether or not additional CARR-side content arrives. But three categories of CARR input would materially raise the quality of the next phase, in order of value:

  1. A current pipeline list (even a 1-page spreadsheet — Account · Contact · Stage · Single Sales Objective · Last Activity). The Miller Heiman pipeline, Blue Sheet generation, Gold Sheet enrichment, and account-signal injection all become more valuable when they have actual deals to attach to. Today they have ~0 active opportunities to operate on.
  2. Paul + Kelvin onboarding (full names, business emails, LinkedIn URLs, sender-domain preference). Unlocks ~1,200 EMEA + APAC accounts.
  3. A handful of buyer interview recordings or notes — even informal "here's what closed our last 3 deals" debriefs. The 38-row SSO matrix is real, but it's currently inferred. With actual conversation data it'd self-correct.

Cross-references:
- SOW commitments + delivery scorecard: docs/CARR_MONTH_THREE_REVIEW.md §6
- Carried-forward open items: docs/CARR_MONTH_THREE_REVIEW.md §7
- Meeting log: docs/CARR_MONTH_FOUR_PLUS_ROADMAP.md §1

Market Intelligence & Brand Layer

Download .docx

02 — Market Intelligence & Brand Layer

Parent: 00_INDEX.md · Reading time: 6 min

The first thing the system does before sending a single message is decide what CARR sounds like. This is the brand/positioning/voice layer — sourced from CARR's own materials, distilled into machine-readable form, and injected into every AI-generated piece of content downstream.


What was built

Master reference documents (in repo)

Four canonical docs that any AI generation pulls from:

File What it captures
Research/CARR_BRAND_BIBLE.md Identity, values, positioning, target audience, brand archetype, tone
Research/CARR_MASTER_BRAND_VOICE.md Voice attributes, vocabulary (preferred + banned), sentence patterns, tone-by-audience
Research/CARR_MASTER_DESIGN.md Visual system, colors, typography, design principles (for landing pages + image gen)
Research/CARR_LANDING_PAGES.md Landing-page architecture, content patterns, hero-section templates
Research/Carr BioSystems/CARR_MESSAGING_POSITIONING_REVIEW.md Living positioning doc — 42 KB markdown version of Jake's April 2 edits

Deep research corpus (30 documents)

In Research/Carr BioSystems/:
- Core Positioning Docs/ (12 items) — Distilled from CARR's 8 PPTX decks
- Deep Research Docs/ (12 items) — Industry-level research (CGT market structure, separation tech competitive landscape, modality-specific trends, Path-to-Patients framing)
- Domain Documents/ (6 items) — Domain-specific reference (allogeneic, iPSC, scalability, cell processing platform, etc.)

Source materials processed

To produce the above, we processed:
- Full Firecrawl scrape of carrbiosystems.com — 44 pages, raw HTML + branding extraction, stored as Research/scrape_data/all_pages.json and homepage_html.html
- 8 PPTX positioning decks — provided via SharePoint, transcribed to text, fed into research synthesis
- 10 meeting transcripts — RAG-indexed in the Hub Knowledge Base
- 2 video assets — UniFuge Centrifuges multitools and UF Pilot Animation (transcribed in Research/video_transcripts/)
- CARR_MESSAGING_POSITIONING_REVIEW_JA Input 20260402.docx — Jake's only formal positioning edit


How it's used at runtime

The handwritten markdown above is the source of truth for humans. For AI generation it gets distilled into a single DB-stored JSON:

Research/CARR_MASTER_POSITIONING.md (human-authored)
    ↓ (one-time + on-edit sync)
client_config.outreach_positioning (~17K characters of JSON, 34 top-level keys)
    ↓ (queried by every EF call)
generate-outreach-message v55 + generate-content-multi-source

What lives in the positioning JSON (outreach_positioning row in client_config)

Verified May 11 via docs/SSO_MATRIX_DEEP_DIVE_2026-05-11.md:

Block What it contains Used by EF?
company, mission, tagline, parent_context Identity strings, Barry-Wehmiller context yes (identity strings)
service_model, company_description "Who you are writing as" framing yes
value_pillars (5 pillars) The 5 core value props yes
value_proposition_canvas Role-angle → pillar map (Manufacturing → High Performance + Scalable; Quality → Closed System + Automation, etc.) yes
products UniFuge UF Mini, UF Pilot, ScalePrep, etc. with specs yes
competitive_positioning 6 head-to-head matrices (Cytiva, Sartorius, Thermo Fisher, etc.) — matched at gen time by account.separationTechnology yes
icp_groups (7 groups) td_allogeneic, td_autologous, iPSC, MSC, etc. — each with pain points + lead-in phrases yes
messaging_variants traditional + path_to_patients framings yes
role_messaging_overrides Per-persona override of default messaging yes
tone_rules_global (12 rules) Tone-by-audience guardrails yes
banned_phrases, preferred_vocabulary Explicit do-not-use / prefer-this lists yes (rendered as guardrails in prompt)
path_to_patients_program P2P pricing, rentals, buyback program details yes (only when variant = path_to_patients)
publications Filtered by clinical stage when relevant yes
cell_type_positioning How to talk about CAR-T, iPSC, MSC, NK, etc. not yet surfaced (deferred)
cta_patterns, discovery_questions Content-studio side (LinkedIn posts) content gen only

The 17K-char JSON is what makes the AI write with CARR's actual product specs, competitive advantages, and approved language — not generic CGT industry phrasing.


How it shows up in real outreach

Every generated message includes (in this order, per generate-outreach-message v55):

  1. Sender identity block (from team_profiles)
  2. Target contact block (Clay summary + L2 segment data)
  3. Account positioning context keyed off the account's ICP group → injected lead-in
  4. Account-specific block (modality, dev stage, scale, separation tech) + competitive line if applicable
  5. Messaging Strategy (3-tier: matrix → icp_groups → role fallback)
  6. Messaging Variant (Path-to-Patients block if selected)
  7. Value Pillars (1–2 matched to the role angle)
  8. Recent Account Signals (news/trials/grants — see 09_live_intelligence_apis.md)
  9. Custom context (operator free-text)
  10. Message instructions (type, length, tone, goal)
  11. Products / Tone rules / Banned phrases / Preferred vocabulary

The matrix matches in 90%+ of cases. When it doesn't, the system falls back to icp_groups lead-ins and then to hardcoded DEFAULT_ROLE_MESSAGING. generation_metadata.messagingSource records which tier fired (db_matrix / db_matrix_cgt / role_fallback).


Live evidence

From the May 11 smoke test (real run, archived in outreach_messages):

  • Target: Harish Santhanam, VP Cell Therapy Tech Ops, Juno Therapeutics (CAR-T, 9 trials, public)
  • Result: 910-char InMail, subject "CAR-T processing challenges from bench to commercial scale"
  • Persona matched: TECHNICAL (Tier 1 — db_matrix_cgt)
  • Lead in: "Juno's CAR-T programs moving through clinical development likely face the classic challenge of maintaining cell viability and recovery when scaling separation protocols…"
  • Source mix: Matrix angle (technical_expertise → scalable processing) primary, account trials (NCT07335562, NCT07115745) as supporting context

The matrix angle dominated; trials provided conceptual support without being quoted as NCT IDs (per the "use AT MOST ONE" instruction in the signals block).


What this layer looks like elsewhere

Companies typically assemble this through some combination of:

Component Typical alternative Rough cost reference
Brand bible + voice doc Brand-strategy firm (1-time engagement) A focused brand-strategy engagement typically runs $25K–$120K depending on scope and firm tier; positioning-only sprints from boutique strategy firms can run $10K–$40K. Public price points are scarce because most firms scope custom.
Messaging matrix (pain × persona × value) RevOps / demand-gen consultant + Miller Heiman or Challenger framework Miller Heiman Group (now Korn Ferry) framework training + a workshop-style engagement is typically a 4–6 figure annual investment per team
Sales enablement content per persona Sales enablement platform (Highspot, Seismic, Showpad) + content team Highspot enterprise plans are quoted (not published); third-party listings reference roughly $30K–$75K/yr
Voice-aligned message generation Lavender, Regie.ai, Twain, etc. (LLM email assistants) Lavender Pro is $29/user/mo public; Regie.ai team plans are quoted; both are general-purpose, not CARR-positioned
Real-time tone enforcement at generation Custom integration on top of an LLM API DIY engineering effort — typically multi-month build

The point of this comparison isn't to say BC's stack is cheaper. It's that the assembly itself — the work of translating CARR's specific decks, products, P2P program, vocabulary, and competitive position into a machine-consumable layer that runs at every message — is the asset. Whatever stack runs underneath, this layer is portable. (See 12_market_alternative_costs.md for the full reference.)


Cross-references

  • Full brand source files: Research/ (CARR_BRAND_BIBLE.md, CARR_MASTER_BRAND_VOICE.md, CARR_MASTER_DESIGN.md, CARR_LANDING_PAGES.md)
  • 30-doc research library: Research/Carr BioSystems/
  • Master positioning review: Research/Carr BioSystems/CARR_MESSAGING_POSITIONING_REVIEW.md
  • Positioning JSON in DB: client_config.outreach_positioning (see docs/SSO_MATRIX_DEEP_DIVE_2026-05-11.md §3 for the full key map)
  • How the prompt is assembled: 08_messaging_system.md

Database Architecture

Download .docx

03 — Database Architecture (Hub-and-Spoke)

Parent: 00_INDEX.md · Reading time: 6 min

The CARR platform isn't a single database. It's a spoke that pulls from a much larger hub. This pattern is what makes the live-intelligence layer (news, trials, grants, patents) work at all — and it's directly portable into whatever the next-generation Azure-based environment you've been discussing with John Katsapis ends up looking like.


The architecture in one diagram

┌────────────────────────────────────────────────────────────────┐
│  BIOCREATIVE HUB  ·  Supabase project mjsgtszehjltxmbxtctz     │
│  "Life Science Market Database"                                 │
│                                                                 │
│   17,290 life-science companies (100% classified)               │
│   228,000+ contacts                                             │
│   3,400+ clinical trials  ·  2,900+ NIH grants                  │
│   2,900+ patents  ·  2,800+ SEC filings                         │
│   4,842 academic labs  ·  14,019 principal investigators        │
│   Hourly news pipeline, matched trials + grants                  │
└──────────────┬─────────────────────────────────────────────────┘
               │                            
               │   sync RPC functions (vault-secured PostgREST)
               │   - sync_cgt_accounts_from_hub()   (weekly Sun 2am)
               │   - sync_clinical_trials_from_hub()(weekly Sun 3am)
               │   - sync_grants_from_hub()         (weekly Sun 4am)
               │   - sync_news_from_life_science()  (every 4h)
               │   - sync_academic_labs_from_hub()  (manual / re-runnable)
               │   - sync_academic_pis_from_hub()   (manual / re-runnable)
               │
               ▼
┌────────────────────────────────────────────────────────────────┐
│  CARR SPOKE  ·  Supabase project drzxmokguptvwptuqjcv           │
│  "carr-biosystems-hub"                                          │
│                                                                 │
│   3,964 CGT-relevant companies (filtered from Hub TAM)          │
│   104,333 contacts (Hub-sourced + Clay + PhantomBuster)         │
│   704 news articles (matched to CARR's targets)                 │
│   1,862 clinical trials (matched by sponsor)                    │
│   5,000 NIH grants (matched to academic accounts)               │
│                                                                 │
│   18 Edge Functions · 17 cron jobs · 95 views · 111 functions   │
│   446 migrations of accumulated schema work                     │
└────────────────────────────────────────────────────────────────┘

Why hub-and-spoke (not a single database)

Three reasons:

1. The Hub is multi-client. It's where BioCreative does universe-wide research and enrichment. Clinical trial matching, news scraping, persona research, lab discovery — these run once at the Hub and flow into every spoke. If we ran them per-client, each client would pay full price for work that's largely shared (every CGT therapeutic-developer company exists in every CGT-focused engagement's universe).

2. CARR owns its spoke. The CARR Supabase project (drzxmokguptvwptuqjcv) is in CARR's organization. CARR-specific data, edits, custom enrichment, pipeline activity, rep notes — they all live in CARR's DB. If the engagement structure ever changes, CARR keeps the spoke. Hub-side data is queryable read-only.

3. Sync = source-of-truth flow. Sync functions are explicit, logged, and one-way for Hub→Spoke data. The spoke can override anything (e.g., CARR's carr_enrichment_data column lives next to Hub's enrichment_data — Hub never overwrites CARR's). Logs are in sync_log (1,972 logged operations as of last count).


What lives in the CARR spoke

Schema counts (as of May 5, 2026 audit)

Category Count Notes
Tables 80+ Plus 95 views and several materialized rollups
Migrations applied 446 Each represents one structural decision, named + dated
Edge Functions 18 All deployed at current versions (see CARR_LAUNCH_READINESS_2026-05.md)
Database functions 111 RPCs, triggers, sync functions, classifiers
Cron jobs 17 16 healthy + 1 fixed mid-May
Indexes 200+ Including 13 FK indexes added in the May Phase-2 security wave
RLS policies 100+ Locked down across 3 audit waves

Core tables (the ones that matter)

Table What it is Rows
companies Account universe 3,964
contacts All discovered people 104,333
outreach_messages Every generated message + delivery state 1,635+
outreach_messaging_matrix The 38-row SSO matrix (§08) 38
client_config Positioning JSON, sender mappings, etc. 1 client config row
news_intelligence Hub-synced news matched to CARR targets 704
account_clinical_trials Hub-synced trials matched to accounts 1,862
account_grants Hub-synced grants matched to accounts 5,000
heyreach_campaigns / heyreach_leads / heyreach_connections LinkedIn pipeline state 37 / 632 / 147
bison_email_accounts / bison_campaigns / bison_replies Email pipeline state 5 / 30 / live
team_profiles 9 sending personas (Jake, Jeff, Andrew, Bethanne, Nico + EMEA/APAC + Soukaina + Steffen) 9
do_not_contact_list Compliance list 15
pipeline_opportunities Miller Heiman opps ~0 active
rep_note_validations HITL validation of rep-entered notes 518

Schema discipline

The 446 migrations aren't an accident — they're how every structural change is captured atomically:
- Migration name + timestamp = full audit log of what changed and when
- Migrations roll forward; nothing is silently mutated
- A migration like add_account_signals_snapshot_to_outreach_messages (May 11) shows exactly what was added, why, and produces a partial index that can be queried for adoption

This is how the system stays portable: any future migration of the CARR spoke to Azure / PostgreSQL Flexible Server / a CARR-managed Postgres instance can replay these migrations to reproduce the schema.


Security posture

The CARR spoke went through three security audit waves between Months 1–3 (documented in CARR_MONTH_THREE_REVIEW.md §2). Result:

  • All views set to SECURITY_INVOKER (no view-level privilege escalation)
  • Anon-role policies removed where they existed
  • All SECURITY DEFINER functions in public schema have explicit safe search_path (verified May 5 audit — CARR_LAUNCH_READINESS_2026-05.md §"Search-Path Regression Check")
  • Webhook idempotency enforced by unique constraints (HeyReach eventId, EmailBison event_id)
  • All API keys in vault.decrypted_secrets, never in code or env files

This matters because before scaling outbound volume, an unprotected view or an injectable function could leak a target list or break compliance. The audit waves cost time in Month 3 but are non-negotiable before email sends scale.


How this transfers to Azure (when/if you migrate)

The hub-and-spoke pattern is database-agnostic. The components that move 1:1:

  • Schema (446 migrations) → SQL is standard PostgreSQL; replays on Azure Database for PostgreSQL with minor adjustments
  • RLS policies → Identical, RLS is PostgreSQL-native
  • Edge Functions (18 Deno-runtime functions) → Port to Azure Functions (Node.js or Python runtime)
  • Cron jobs (17 pg_cron) → Either keep on Azure PG (it supports pg_cron) or move to Azure Functions Timer Triggers
  • Vault → Azure Key Vault
  • Sync functions → HTTP calls to Hub's PostgREST API — work identically from any client

The piece that wouldn't transfer cleanly is the Supabase realtime/auth layer — but that's the platform layer, not the data architecture. See docs/CARR_MONTH_FOUR_PLUS_ROADMAP.md §4 (Option C: Enterprise Migration) for the full Azure path.


What this layer looks like elsewhere

Commercial alternatives to building a hub-and-spoke data platform:

Component Typical alternative Notes
Multi-tenant data warehouse Snowflake / Databricks / BigQuery + reverse-ETL (Hightouch, Census) Snowflake's published list price is $40+/credit; a small team typically lands in the $1K–$5K/mo range for usage alone. Hightouch's "Starter" plan is $0; Pro starts at $1,250/mo per their public pricing page.
Per-client data marts A dedicated PG instance per client + custom sync pipelines Engineering build, ongoing maintenance. AWS RDS or Azure DB pricing varies by instance size.
Schema versioning Liquibase / Flyway / Sqitch Free tools, but require engineering discipline
RLS Custom in app layer or PostgreSQL native PostgreSQL native is what we use; same as Snowflake row access policies

The architecture choice (PostgreSQL + sync RPCs) is one of several reasonable choices. What's portable is the pattern — separation of universe-wide hub from client-owned spoke.


Cross-references

  • Architecture overview: docs/architecture.md
  • RLS reference: docs/rls.md
  • Sync log reference: context/database/data_flows.md
  • Hub-to-CARR sync map: context/database/hub_to_carr_sync_map.md
  • Full schema reference: context/database/schema_reference.md
  • Azure migration analysis: docs/CARR_MONTH_FOUR_PLUS_ROADMAP.md §4

Account Universe & ICP Scoring

Download .docx

04 — Account Universe & ICP Scoring

Parent: 00_INDEX.md · Reading time: 6 min

This layer is the answer to "who should CARR be talking to, and in what priority order?" It's the most foundational decision in any outbound program — everything downstream operates on the universe and ranking this layer produces.


The universe in four numbers

Number What it represents
17,290 Total life-science companies tracked in the BioCreative Hub (100% classified, the multi-client TAM source)
3,964 Companies pulled into CARR's spoke after CGT filtering
3,406 Of those, marked is_icp_relevant = true — the active universe
2,323 Currently ICP-scored across the v2 model (4 dimensions)

The 3,406 ICP-relevant universe is the working set every campaign, every list, every Target Universe review operates against.


How the universe was built (step by step)

Step 1 — Hub seeding

sync_cgt_accounts_from_hub() pulled the CGT-relevant subset from the 17K-company Hub TAM into CARR. Filter logic:
- Companies tagged with CGT-relevant keywords in enrichment_data.modalities[] or ai_subcategory
- Plus academic institutions with CGT-relevant grant/trial activity
- Plus CRO/CDMOs with CGT capability in their public profile
- Deduplicated against existing CARR rows by domain

Result: 845+ initial accounts (219 therapeutic developers, 56 CRO/CDMOs, 570 academic institutions) per the CARR_SYSTEM_OVERVIEW.md v3.5 record.

Step 2 — CARR's own list merged

Jake and Dan provided CARR's ~1,100 existing accounts. Processed through:
- carr_account_import_v1.ipynb — clean, normalize, load
- carr_account_matcher.py — match against Hub records (548 exact matches, 202 fuzzy matches, ~300 net-new)
- Net-new accounts pushed back to the Hub master DB so future Hub-side enrichment captures them too
- Resulting blended universe: ~2,050 total after merge

Step 3 — Universe expansion via continued Hub sync

The Sunday 2am sync_cgt_accounts_from_hub() cron has been running for months. As BioCreative discovers new CGT companies anywhere in the Hub (via Cat-A intel pipelines, news matching, trial sponsor extraction), CARR's spoke gets them on the next sync. Universe has grown from ~2,050 → 3,964.

Step 4 — Multi-layer classification

Every non-academic account went through:

Stage What it produces Coverage
Hub L2 deep research (auto-synced) 22-key JSONB: clinical phase, funding stage, modality, platform, pipeline products, total funding, investors, competitors 2,973 / 3,964 (75%)
CARR-specific enrichment carr_enrichment_data JSONB: centrifugation fit, manufacturing scale, bioreactor type, key partnerships, separation tech Run iteratively; preserves Hub data
ICP classification companies.icp_segment = therapeutic_developer / cdmo / academic / service_provider / financial_partner / default 3,945 / 3,964 (99.6%)
ICP v2 scoring companies.icp_tier = Tier 1 / 2 / 3 / 4 / 5 / Out of Scope 2,323

Detail of the enrichment pipeline is in 05_account_enrichment_pipeline.md.


ICP v2 — how scoring actually works

The Month 3 work rebuilt scoring from a blunt 3-tier (Tier 1/2/3) into a more nuanced 4-dimension model: calculate_icp_score_v2() (PL/pgSQL function).

The 4 dimensions

Dimension What it asks Where signal comes from
Modality fit Does this company work in CGT modalities CARR's equipment serves? companies.modalities[], enrichment_data.modality, derived from trials
Stage fit Is the company at a clinical/manufacturing stage where they buy this equipment? enrichment_data.clinical_phase, derived from trials, funding stage
Scale fit Does their manufacturing volume actually need centrifuge separation at CARR's scale? carr_enrichment_data.manufacturing_scale, employee count, bioreactor inferences
Equipment readiness Are they in a buying window (new facility, new program, new modality)? News signals, trial start dates, grant awards, funding events

Each dimension produces a sub-score. Total maps to icp_tier. Sub-scores are stored so you can see why an account is Tier 1 vs Tier 3.

Why this matters operationally

The system can answer: "Show me all Tier 1 therapeutic developers with at least one active Phase 2 trial and no separation tech vendor listed." — that's a single SQL query against the joined ICP score + trials + enrichment tables. Without the structured scoring, the equivalent ask is a research project.


The 7-status account lifecycle (the other axis)

ICP fit is one axis (how good a target is the company on paper). Engagement status is the other axis (where are they in our actual outreach lifecycle). These are independent. See skills/target_universe_tiers.md for the canonical reference.

Status Meaning Outreach allowed? How it gets set
unreviewed Not yet looked at No (filtered out) Default for all imports
cold_target Reviewed + accepted, eligible for cold outreach Yes Rep review or bulk action
warm_target Engaged at least once (reply/connect) No (suppressed) Auto-promotion on signal + manual
active_prospect In an active conversation No (suppressed) Manual
customer Closed-won No (suppressed) Manual / pipeline event
disqualified Permanently out of scope No Rep review

Three EFs guard the SUPPRESSED_TIERS list: batch-generate-outreach, push-to-emailbison, send-linkedin-messages. Once an account hits warm_target, the system stops cold-touching it automatically — preventing the most common B2B compliance/CX failure (someone replies, the queue keeps sending them sequence steps).

Auto-promotion (signal → status change)

Two webhooks handle this:

Signal Source What fires
Email reply (categorized as actual reply, not bounce/OOO/unsub) EmailBison LEAD_REPLIEDemailbison-webhook promoteToWarm()cold_targetwarm_target
Email "interested" tag EmailBison LEAD_INTERESTEDemailbison-webhook Same
LinkedIn connection accepted HeyReach CONNECTION_REQUEST_ACCEPTEDheyreach-webhook Same

All promotions log to account_activities with the signal source. Idempotent — re-running the same webhook is a no-op.


Current distribution (live, mid-May 2026)

From CARR_MONTH_THREE_REVIEW.md §4:

Tier Accounts What it means
unreviewed 2,088 Awaiting ICP v2 review
cold 798 Initial outreach pool (engagement axis)
nurture 343 Warm, long-term engagement
disqualified 85 No fit
parked 74 Paused (acquisition, leadership change, etc.)
customer 17 Active customers
validated_target 1 Confirmed high-priority

Note: unreviewed at 2,088 is the largest bucket. This is where the rep-review throughput ceiling shows. Nico alone has 478 unreviewed accounts in his territory. The bulk-review UX exists; uptake has been low.


Where the universe gaps still need CARR

Two things would meaningfully sharpen this layer:

  1. A pipeline-opportunity list — even informal. Right now pipeline_opportunities is empty. With a list of active deals, the system can:
    - Promote those companies to active_prospect automatically
    - Backfill buying_mode, budget_confirmed, fit_confirmed from rep memory
    - Surface contact gaps (deal vs known contacts at that account)
    - Inform the ICP score with closed-won feedback (accounts most like recent wins get a lift)
  2. A closed-won list (last 12–24 months) — same idea, ICP-tuning. If the system knows CARR's last 20 wins, ICP scoring can favor accounts that pattern-match.

What this layer looks like elsewhere

Component Typical alternative Notes
TAM / universe building ZoomInfo, Apollo, LeadIQ, Cognism ZoomInfo Advanced is quoted, not published; third-party tracker tools commonly cite five-figure annual subscriptions for the deeper data feeds. Apollo's published pricing tops out at $99/user/mo on their public plans page.
ICP scoring 6sense, Demandbase, MadKudu, RollWorks (Account-Based Marketing platforms) All quote-only. Industry research (e.g., Forrester / Gartner ABM platform evaluations) consistently places enterprise ABM in the high-five-to-six-figure annual range.
Account-status lifecycle CRM-native (HubSpot, Salesforce) + sales ops process Built-in to most CRMs; cost is in the CRM seat
Lifecycle automation Custom workflow tools (HubSpot workflows, Salesforce flows, Zapier) Per-seat or per-task

The choice in this engagement was: rather than pay ZoomInfo + 6sense + a CRM workflow license, build the equivalent inside CARR's own Postgres so the data and logic stay in CARR's control. That's a tradeoff with pros and cons — 12_market_alternative_costs.md lays it out.


Cross-references

  • ICP scoring model: context/icp/scoring_model.md
  • Account classification: context/icp/account_classification.md
  • Target Universe taxonomy + auto-promotion: skills/target_universe_tiers.md
  • Account enrichment pipeline: 05_account_enrichment_pipeline.md
  • Live data flows: 09_live_intelligence_apis.md

Account Enrichment Pipeline

Download .docx

05 — Account Enrichment Pipeline

Parent: 00_INDEX.md · Reading time: 6 min

A name and a domain isn't a target. To message someone usefully you need to know: what modality is the company actually working in, what clinical stage they're at, what manufacturing scale they're operating at, who their competitors are, what equipment they currently use, and whether anything in their recent history opens a buying window. This layer answers all of that, automatically, for thousands of accounts.


The two-stage enrichment model

CARR uses a layered enrichment pattern. Hub-side enrichment is universe-wide (every CGT company gets the same baseline treatment). CARR-side enrichment is on top of that and is CARR-specific (centrifuge fit, separation tech, manufacturing scale — only relevant to CARR's product).

┌─────────────────────────────────────────────────────────────┐
│ HUB-SIDE (universe-wide, shared across all BC clients)      │
│                                                             │
│  L1 — Rule-based                                            │
│    └─ ai_subcategory, primary_category, is_life_sciences    │
│                                                             │
│  L2 — AI deep research (Claude Sonnet + web scraping)       │
│    └─ enrichment_data (22-key JSONB):                       │
│         modality, clinical_phase, funding_stage,            │
│         technology_platform, pipeline_products,             │
│         total_funding, key_investors, competitors,          │
│         ai_summary, human_summary, etc.                     │
└─────────────┬───────────────────────────────────────────────┘
              │ synced to CARR (preserved as-is, never overwritten)
              ▼
┌─────────────────────────────────────────────────────────────┐
│ CARR-SIDE (CARR-specific, runs only on CGT-relevant accts)  │
│                                                             │
│  Light enrichment — web search (Brave) + basic facts        │
│    └─ skips if Hub L2 data exists                           │
│                                                             │
│  Classification — Claude AI                                 │
│    └─ icp_segment (TD/CDMO/academic/SP/financial/default)   │
│    └─ ai_subcategory (td_clinical, service_cdmo, etc.)      │
│                                                             │
│  Deep enrichment — Firecrawl + Brave + Claude               │
│    └─ carr_enrichment_data JSONB:                           │
│         centrifugation_relevance, manufacturing_scale,      │
│         bioreactor_type, separation_technology,             │
│         key_partnerships, equipment_signals                 │
│                                                             │
│  ICP v2 scoring — deterministic, uses both layers           │
│    └─ icp_tier (Tier 1 / 2 / 3 / 4 / 5)                     │
└─────────────────────────────────────────────────────────────┘

Critical rule (codified in SPOKE_ENRICHMENT_PATTERN.md): Hub enrichment_data is never overwritten by spoke code. Spokes use a [client]_enrichment_data column so universe-wide intelligence and client-specific deep dives coexist.


The tools used at each stage

Stage Tool What it does
Light enrichment Brave Search API Pulls 3–5 search results per company, AI extracts basic facts
Site scraping Firecrawl When deeper detail needed, scrapes the company's own site (about page, technology page, news)
Classification Claude Sonnet 4 (claude-sonnet-4-20250514) Maps free-form descriptions → structured ICP segment + subcategory
Deep enrichment Claude Sonnet 4 + retrieved web content Extracts CARR-specific signals: separation tech, bioreactor type, scale
Verification validate-data-flag Edge Function Rep-driven re-check: when a rep flags "this is wrong", system re-runs verification
ICP scoring calculate_icp_score_v2() (PL/pgSQL, deterministic) Uses Hub L2 + CARR enrichment + signals to assign tier

Two notebooks orchestrate this and are re-runnable:

  • scripts/colab/carr_account_enrichment_v1.ipynb — main enrichment runner
  • Manual triggers via Hub MCP for batch reprocessing

What carr_enrichment_data actually contains

For a fully-enriched therapeutic developer, the JSONB block has roughly:

{
  "centrifugation_relevance": "high",
  "manufacturing_scale": "clinical_pilot_to_commercial",
  "bioreactor_type": "stirred_tank_bioreactor",
  "current_separation_technology": "Cytiva ÄKTA + Beckman Coulter Optima",
  "key_partnerships": ["Lonza", "Catalent"],
  "equipment_signals": [
    {"signal": "Phase 2 facility expansion announced", "date": "2026-03-14", "source": "press_release"},
    {"signal": "New CTO with manufacturing background", "date": "2026-02-20"}
  ],
  "carr_fit_summary": "Allogeneic CAR-T pipeline, two Phase 2 trials. Current Cytiva-based downstream — likely candidate for UniFuge UF Pilot at clinical scale.",
  "competitive_overlap": ["Cytiva", "Beckman"],
  "objections_anticipated": ["validated_workflow_change_cost"]
}

This is not generic enrichment. Apollo, ZoomInfo, etc. don't have "what separation technology does this CGT company currently use" as a field — because it requires CARR-specific domain reasoning. That's why it's built rather than bought.


How the enriched data is used downstream

Downstream layer What it pulls from enrichment
Message generation competitive_positioning match, carr_fit_summary, manufacturing_scale into the prompt's "Their company" block
ICP scoring All four dimensions read from the JSONB
Target Universe UI "CARR Fit" badge on account rows, surfaced in Gold Sheet
Account Detail Gold Sheet First-tab consolidated intelligence view
Campaign list-building Filter by manufacturing_scale, bioreactor_type, separation_technology
Pipeline Blue Sheet generation Pre-fills Anticipated Objections, Credibility Elements

Coverage today

From the May 11 system overview:

Coverage metric Value
Accounts with icp_segment 3,945 / 3,964 (99.6%)
Accounts with Hub L2 enrichment 2,973 / 3,964 (75%)
Accounts with carr_enrichment_data (CARR-side deep) Run on Tier 1/2 priority; runs are batch and resumable
Accounts with ICP tier 2,323 (active)
Accounts with account_signals (news/trials/grants) 89% of CGT-active accounts have at least one signal

The 25% gap on Hub L2 coverage is primarily:
- Very small / very new companies (web footprint too thin for reliable extraction)
- Stealth-mode companies (deliberate web absence)
- Academic institutions (use grants/trials instead of enrichment)


Verification — the rep loop

A key Month-3 addition: rep_note_validations table (518 verdicts to date) closes the loop between rep observations and AI enrichment.

Rep enters note ("this company was acquired by X" / "they're a small-molecule company, not CGT")
   ↓
validate-data-flag EF runs (Brave Search + Firecrawl + Claude verification)
   ↓
Verdict: confirmed (21) | refuted (5) | inconclusive (53) — sample numbers from Nico's notes audit
   ↓
Recommended action: accept rep claim / update DB / flag for human review
   ↓
Rep approves → DB updated; rep rejects → kept as-is

This was built in response to the Nico-notes audit (April 22, 2026) which found:
- 49 of his 222 notes were "too small / too early" calls — a heuristic the AI couldn't replicate without him
- 23 notes were "wrong therapeutic space" — companies that had pivoted away from CGT
- 5 of 79 validated claims were refuted by the agent (e.g., Treadwell — rep said "small molecule," agent found "clinical-stage oncology")

So the system is now structured to:
- Capture rep observations attributably (per-user performed_by_id on account_activities)
- Re-validate stale rep notes (>180 days flag)
- Bring rep + AI verdicts into a weekly review digest

Full reference: docs/NICO_FEEDBACK_SYNTHESIS.md.


What this layer looks like elsewhere

Component Typical alternative Notes
Universe-wide enrichment Apollo, ZoomInfo, Cognism, Crunchbase Pro Apollo's public page lists plans up to $99/user/mo; ZoomInfo and Cognism are quote-only and routinely cited in the high-four-to-five-figure annual range. None of them carry CGT-specific signals like manufacturing scale or separation technology.
Company deep research Clay (waterfall enrichment + AI) Clay publishes credit-based pricing — their "Pro" tier starts at $349/mo on the public pricing page; enterprise plans are quoted. Clay is used inside this engagement for the contact layer (see 07_contact_enrichment_personas.md), not for the company-side deep dive.
Domain-specific enrichment (CGT-aware) None at scale — would require a custom data team or specialist vendor Pharma intelligence platforms like GlobalData / Citeline carry trial and pipeline data; they're typically annual subscriptions in the five-figure range.
Site scraping Firecrawl (used), Apify, Bright Data Firecrawl is pay-per-credit, public pricing tiers from $0 free → enterprise quote.
AI extraction Claude / GPT-4 / Gemini APIs Per-token; running enrichment at CARR's universe scale is small relative to platform costs (cents per company, not dollars).

The CARR-specific reasoning (separation tech, manufacturing scale, equipment-buying signals) is the part that doesn't exist off the shelf. That's domain knowledge encoded into the prompts + the structured output schema.


Cross-references

  • Enrichment runbook: skills/account_enrichment.md
  • Hub-spoke enrichment rules: biocreativeaihub/departments/client-mgmt/launch/SPOKE_ENRICHMENT_PATTERN.md
  • Account classification rules: context/icp/account_classification.md
  • Rep validation pipeline: docs/NICO_FEEDBACK_SYNTHESIS.md
  • ICP scoring model: context/icp/scoring_model.md

Contact Discovery

Download .docx

06 — Contact Discovery

Parent: 00_INDEX.md · Reading time: 5 min

Knowing the company is step one. Knowing who at the company to talk to is the much harder problem. This layer is how 104,333 contacts ended up in the CARR DB, mapped to the right accounts, with seniority and department parsed, and pre-filtered to exclude departments that don't buy centrifuge equipment.


The contact universe in numbers

From skills/contact_management.md v1.2 (May 11):

Metric Count
Total contacts 104,333
With email 8,268 (7.9%)
With LinkedIn URL 104,333 (100%)
With marketing_persona (classified) 2,650 (2.5%) — see 07_contact_enrichment_personas.md
With Clay headline (eligible for classification) 3,275 (3.1%)
With Clay summary 1,091 (1.0%)
With Clay experience summary 590 (0.6%)
Senior contacts (Director+) 7,610 (7.3%)
Distinct companies represented 2,609

Source breakdown

Source Contacts % Notes
life_science_db (Hub-sourced) 81,301 78% PhantomBuster + Clay Find-People runs at the Hub, synced to CARR
sync (CARR-side imports) 22,983 22% Bulk CSV imports (jeff_batch, contacts upload 032326, etc.)
heyreach 49 <1% Captured from HeyReach connection records

The three discovery pipelines

Pipeline 1 — Manual import (CSV / Excel)

CSV/Excel → contacts_staging table → match company → INSERT contacts
  • Notebook: scripts/colab/carr_contact_import_v1.ipynb
  • Staging table buffer prevents direct INSERT mistakes
  • Match on linkedin_url (unique key) to avoid duplicates
  • Trigger canonicalize_contact_fields() runs on insert/update — normalizes seniority + department automatically

This is how the early CARR contact files (jeff_batch_for_clay, contacts upload 032326.csv) entered the system.

Pipeline 2 — Hub PhantomBuster sync

Hub new_contacts (import_source=phantombuster) 
  → sync_to_carr.py (on Ops VPS)
  → import_hub_contacts RPC

What's behind it:
- Sales Navigator searches at the Hub level — for each CGT modality, seniority band, and department
- PhantomBuster runs the scrape (Sales Nav → CSV of LinkedIn profiles with title, company, location)
- Each LinkedIn URL is canonicalized + persisted to new_contacts at the Hub
- Sync function pushes them into CARR only if the parent company is already in CARR's universe with is_icp_relevant = true

This is the workhorse — 81K+ contacts came in via this route.

Pipeline 3 — Hub Clay Find-People sync (added May 11, 2026)

Hub new_contacts (source_database=clay-webhook)
  → sync_clay_fp_to_carr.py (Ops VPS)
  → import_hub_contacts_v2 RPC

Clay's "Find People" feature takes a list of company domains and finds people at those companies matching role criteria. Difference vs PhantomBuster:
- Better email discovery (Clay does waterfall email enrichment in-line)
- Auto-creates companies in CARR if they don't exist yet (220 new companies auto-created in the May 11 run)
- Slower per contact, costs more, but better-quality data

Most recent run (May 11): 2,021 contacts inserted + 220 companies auto-created in a single batch.

Workflow doc: .windsurf/workflows/sync-clay-fp-to-carr.md (in Hub repo).


What happens automatically on every contact insert

Trigger canonicalize_contact_fields() runs on INSERT and UPDATE:

Raw job_title → seniority_normalized
   "VP of Manufacturing"           → VP
   "Senior Director, Quality"      → Director (Senior)
   "Process Development Scientist" → Individual Contributor

Raw job_title → department_normalized
   "VP of Manufacturing"           → Operations
   "Senior Director, Quality"      → Quality
   "Process Development Scientist" → Engineering

is_outreach_target = false WHEN department_normalized IN
   (Sales, Marketing, Business Development, Legal,
    Finance, HR, IT, Investment, Advisory)

The exclusion list matters — these departments don't buy centrifuge equipment. Excluding them at insert time prevents downstream waste: the campaign builder, message generator, and enrichment runner all skip non-buyer departments. (Per the April 14 alignment: see system memory.)


How contacts are mapped to accounts

Every contact has a company_id FK → companies.id. The match happens via:
1. Exact match on company_domain (most reliable)
2. Fuzzy match on company_name for unmatched (uses PostgreSQL pg_trgm similarity)
3. Manual review queue for low-confidence matches

Result: 104K contacts mapped across 2,609 distinct companies. Average ~40 contacts per company, but skewed — Tier 1 CGT companies often have 100+ contacts each because of dedicated scraping cycles.


The 2-step gate to outreach eligibility

Not every contact in the DB is in the outreach pool. Two filters apply:

Step 1 (auto): is_outreach_target = false for non-buyer departments
   → ~80K contacts → ~30K remain

Step 2 (campaign-level): account must have account_tier != unreviewed
                         AND contact must have marketing_persona classified
                         OR be in an explicit campaign target list
   → ~30K remain → ~2.6K classified, in active campaign pools

The 30K → 2.6K gap is the Clay-enrichment + classification bottleneck (see 07_contact_enrichment_personas.md). Until contacts have Clay data, the AI persona classifier can't run on them reliably. This is the single biggest contact-side scaling lever.


What this layer looks like elsewhere

Component Typical alternative Notes
Contact list-building Apollo (built-in scraping), ZoomInfo, Cognism, LeadIQ All quote-only at scale; Apollo's public plans top out at $99/user/mo with usage caps. None of them carry CGT-specific filtering.
Sales Navigator scraping PhantomBuster (used) + Sales Nav license, TexAu, Bardeen, Captain Data Sales Nav is $99/user/mo (LinkedIn published price). PhantomBuster is a credit system, public plans $69-$129+/mo.
Email enrichment Clay (used), Apollo email finder, RocketReach, Hunter, Anymailfinder Clay Pro $349/mo+ (public). Apollo's email enrichment is per-credit. RocketReach team plans from $83/user/mo (public).
LinkedIn ↔ company matching Built into Apollo / ZoomInfo natively Their data model handles this; we built it because contacts come from multiple sources
Seniority / department parsing Built into Apollo / ZoomInfo; manual otherwise Our canonicalize_contact_fields() does this deterministically on every insert
Department-level exclusion at insert Custom logic everywhere This is where most teams leak budget — they pay Clay/Apollo for emails of people who would never buy their product

The choice in this engagement: rather than pay Apollo/ZoomInfo's seat license to access their contact universe with their filters, build the contact universe inside CARR's DB with CARR-specific filters. The tradeoff is upfront engineering (notebooks + sync + trigger) vs ongoing license cost.


Where this could scale further

Three levers, in priority order:

  1. More Clay credits → more contacts classified. The biggest gap. 30K outreach-eligible contacts vs 2.6K classified. Each Clay enrichment runs at ~$0.50–$1.50 depending on data depth. Scaling to 10K classified would cost ~$7K–$15K in Clay credits, if CARR wanted to underwrite that pace.
  2. Phantom Buster for newer cohort discovery. Hub-side discovery is paused on the slowest CGT subcategories. Could be re-fired with focused search criteria from rep input.
  3. Apollo or LeadIQ as a backup waterfall for missing emails. Currently emails come from Clay only. Adding a fallback waterfall would raise email coverage from 7.9% → ~30%, especially in the senior bands where Clay coverage is weaker.

Cross-references

  • Contact management runbook: skills/contact_management.md
  • Hub sync workflow: .windsurf/workflows/sync-clay-fp-to-carr.md (Hub repo)
  • Contact data model: context/database/schema_reference.md
  • Contact classification (downstream): context/icp/contact_classification.md
  • Persona classification (next layer): 07_contact_enrichment_personas.md

Contact Enrichment & Personas

Download .docx

07 — Contact Enrichment & Persona Classification

Parent: 00_INDEX.md · Reading time: 6 min

Knowing a contact's name, title, and company is the start. To personalize a message at scale you need to know which buying persona they map to — because the pain points, value props, and tone for an Operations VP at a Phase 2 CAR-T company are completely different from a Research Director at the same company. This layer runs two AI passes (one for raw enrichment, one for classification) to assign every eligible contact to one of six personas.


The two-pass model

Step 1 — Enrichment (Clay)
   contact (name, LinkedIn URL) 
     → Clay waterfall enrichment
     → clay_headline + clay_summary + clay_experience_summary
     → email discovery (when missing)

Step 2 — Classification (Claude)
   contact + Clay data + company context
     → Claude AI persona classifier (Colab notebook v4 or v2)
     → marketing_persona (1 of 6)
     → segment_data JSONB (persona_summary, messaging_angle, 
        pain_points, value_hook, buying_context, decision_role,
        confidence)

The gate: Step 2 only runs on contacts where clay_headline IS NOT NULL. That's why only 2,650 of 104K contacts are persona-classified — the bottleneck is Clay enrichment, not the classifier.


The 6 marketing personas (CARR-specific)

These were re-designed in April 2026 specifically for centrifuge-equipment buyers. From skills/contact_management.md:

Persona Maps to buying persona Target roles
executive_leadership CTO / CEO buying influence C-Suite, SVP, VP-of-the-whole-thing
technical_leadership Process Development Lead Director/VP Process Development, Engineering
research_leadership Process Development Lead (research-side) VP R&D, CSO, Research Director
operations_leadership VP Manufacturing VP Ops, VP Manufacturing, COO, Supply Chain
quality_regulatory_leadership Quality / Regulatory buying influence VP Quality, Regulatory Affairs
clinical_leadership Quality / Regulatory (clinical-side) VP Clinical, CMO, Medical Director

What was removed and why

commercial_leadership was removed in April 2026 — Sales, Marketing, BD have no buy decision for CARR centrifuge equipment. Keeping them in the personas wasted Clay credits and produced bad messages. ~175 contacts were re-classified out. (See f0b88d0b memory entry for the realignment record.)

Distribution today

From CARR_MONTH_THREE_REVIEW.md §4, 3,558 contacts classified by May 6:

Persona Count Δ from Month 2
executive_leadership 764 +266
quality_regulatory_leadership 734 +153
operations_leadership 613 +114
clinical_leadership 510 +163
technical_leadership 510 +129
research_leadership 427 +83

(Note: 3,558 in the Month 3 review vs 2,650 in the May 11 skill doc — the latter reflects post-cleanup numbers after some reclassifications.)


The classifier (under the hood)

Two notebooks (both Colab-ready):

Notebook Best for Notes
carr_contact_classifier_v4.ipynb (v4.2) Standard runs Reads Clay data → Claude classification → writes marketing_persona + rich segment_data JSONB. Cell 5 writes the EF-consumed fields.
carr_l2_persona_classifier_v2.ipynb (v2.1) Advanced runs Auto-tier loop (Tier 1–6 by Clay data richness), resume-safe batching, cost tracking, fatal-API detection.

What v4 actually writes into segment_data (these are the fields the message-generator reads at runtime):

{
  "persona_summary": "Senior operations leader at a Phase 2 CAR-T developer. Manages tech transfer and scale-up for clinical trial supply.",
  "messaging_angle": "scalable_processing",
  "primary_pain_points": [
    "Maintaining cell viability at scale",
    "Bridging clinical to commercial manufacturing",
    "Reducing downstream processing bottlenecks"
  ],
  "value_hook": "UniFuge UF Pilot enables clinical-to-commercial scale-up without revalidating the separation workflow",
  "buying_context": "Likely in process design phase ahead of BLA — equipment decisions get locked here",
  "decision_role": "technical_buyer",
  "confidence": "high",
  "buyer_segment": "OPERATIONS"
}

That JSONB is then what feeds the generate-outreach-message EF when this contact gets a message generated.


The persona-resolution priority chain (at message-generation time)

Even after classification, the EF has a priority chain to derive the buying persona at runtime. From docs/SSO_MATRIX_DEEP_DIVE_2026-05-11.md §2:

1. contacts.buyer_segment (L2 classifier output — most reliable)
2. contacts.marketing_persona (Clay-derived label)
3. contacts.role_type (L1 enrichment fallback)
4. contacts.department_normalized (rule-based)
5. C-Level / VP seniority → EXECUTIVE (catch-all for senior contacts)
6. Default fallback: EXECUTIVE

This means every contact gets some persona resolution even if classification hasn't run. Quality degrades down the chain, but messages still get generated.


Clay enrichment — what it actually provides

Per skills/contact_management.md:

Field What it gives the classifier
clay_headline Current professional headline (Sales Nav doesn't always have this)
clay_summary Their LinkedIn About section — gives voice, focus, expertise
clay_experience_summary Career arc — tells you whether they're a senior IC or someone in transition
Email discovery (waterfall) Highest-confidence email; this is where the 7.9% email coverage comes from

Coverage: 3,303 contacts enriched (3.2%) — same as Step 1 gate.


How this flows into outreach (real example)

A contact like Harish Santhanam (VP Cell Therapy Tech Ops, Juno) gets:

  1. Clay enrichment — pulls headline + summary + experience
  2. v4 classifier runs → marketing_persona = technical_leadership, segment_data filled with technical-buyer angle, pain points around scale-up
  3. At message-generation time — EF reads segment_data → buying_persona = TECHNICAL → matrix lookup (therapeutic_developer, TECHNICAL) → CGT match boost → angle = technical_expertise → pain points + value props pulled from matrix row
  4. Message produced (verified May 11 smoke test): InMail subject "CAR-T processing challenges from bench to commercial scale", opens with a technically-grounded pain point, recommends UF Pilot, soft CTA.

This is what the layered system buys you. None of the AI gymnastics works if the persona is wrong at the front of the chain.


The Clay-credit ceiling (and how to break it)

The single biggest scaling lever in this layer:

  • 30K contacts in CARR are outreach-eligible (passed the department filter)
  • Only 3,275 have Clay enrichment data
  • Only 2,650 are classified

To classify another 5K contacts requires:
- ~5K Clay enrichment runs (depending on data depth, $0.50–$1.50 each)
- ~$2.5K–$7.5K in Clay credits
- ~2–3 days of run time on the existing notebook
- $0.002–$0.005 per contact in Claude API costs (negligible)

This isn't a technical problem — the pipeline is built and tested. It's a credit budget decision.


What this layer looks like elsewhere

Component Typical alternative Notes
Contact-level enrichment Clay (used), Apollo enrichment, ZoomInfo, RocketReach Clay Pro $349/mo+ public; Apollo/ZoomInfo quote-only; all are per-contact-credit.
AI persona classification Custom on top of an LLM API; some ABM platforms have built-in scoring (6sense, Demandbase) The CARR-specific 6-persona model with CGT-aware pain points doesn't exist off-the-shelf.
Department/seniority normalization Built into Apollo / ZoomInfo natively Ours runs in a Postgres trigger on every insert
Buyer-influence mapping (Miller Heiman) Korn Ferry / Miller Heiman training, Salesforce Strategic Selling app Framework-level work; pricing is workshop or per-seat
Voice-of-customer for pain points Customer interviews, win/loss analysis (Klue, Crayon), Gong call analysis Klue is quote-only; Gong starts ~$1.5K/user/yr per third-party trackers. Different category but feeds the same matrix data.

Cross-references

  • Contact management skill: skills/contact_management.md
  • Classifier notebook v4: scripts/colab/carr_contact_classifier_v4.ipynb
  • Classification deep dive: context/icp/contact_classification.md
  • Messaging integration (downstream): 08_messaging_system.md
  • SSO matrix mapping: docs/SSO_MATRIX_DEEP_DIVE_2026-05-11.md §2

Messaging System (SSO Matrix)

Download .docx

08 — Messaging System (The SSO Matrix Engine)

Parent: 00_INDEX.md · Reading time: 7 min · Canonical reference: docs/SSO_MATRIX_DEEP_DIVE_2026-05-11.md

This is the engine. Everything above (universe, enrichment, personas, brand voice) feeds in. Every outreach message — LinkedIn connection, InMail, cold email, follow-up — comes out of this layer. It's where the layered system either pays off or fails. As of May 11, it's running v55 of the Edge Function with account-signals injection live.


The Single Sales Objective (SSO) Matrix

outreach_messaging_matrix table — 38 active rows mapping (icp_segment × buying_persona × optional cgt_focus) to a messaging strategy.

Each row contains:
- pain_points — 3–5 role-specific pain points
- value_propositions — 3–5 matched value props
- messaging_angle — the lens (e.g., technical_expertise, scalable_processing, compliance_focus)
- hook_type — opener pattern (e.g., pain_acknowledgment, industry_signal, peer_reference)
- cta_options — 2–3 call-to-action variants
- subject_line_templates — for email types

Coverage by segment × persona (from May 11 audit)

icp_segment EXEC TECH OPS QA/REG RESEARCH CLINICAL
therapeutic_developer 7 (cgt) 7 (cgt) 1 3 (cgt) 2 2 (cgt)
cdmo 1 1 1 1
academic 1 1 1 1
service_provider 1 1
default 1 1 1 1 1 1

Therapeutic Developer × the 6 personas is the densest (since it's CARR's primary ICP and has CGT-modality-specific rows). Gaps in CDMO × Research/Clinical and Service Provider × OPS/QA/RESEARCH/CLINICAL fall through to the default row and then to icp_groups lead-ins.


The 3-tier resolution chain

When a message is generated, the system tries three tiers in order:

Tier 1 — Matrix lookup (resolve_messaging_strategy RPC)
   Looks up (icp_segment, marketing_persona, optional CGT match)
   If found → uses pain points, value props, angle from the row
   Reports: metadata.messagingSource = "db_matrix" or "db_matrix_cgt"

Tier 2 — icp_groups lead-in (fallback)
   When matrix has no row → looks up positioning.icp_groups[carr_icp_group]
   e.g., td_allogeneic → injects allogeneic-specific lead-in phrasing
   Reports: metadata.messagingSource = "icp_groups_fallback"

Tier 3 — Role fallback (last resort)
   When neither matrix nor icp_groups match → DEFAULT_ROLE_MESSAGING
   Each persona has hardcoded baseline pain/value props
   Reports: metadata.messagingSource = "role_fallback"

This is the difference between personalized and just-LLM-generated. Without the matrix, every message is whatever the LLM hallucinates about CGT + the recipient's role. With it, every message has CARR-vetted pain points and value props as the spine.


5 message types, 2 variants

Types

Type Channel Char limit Use
linkedin_connection LinkedIn 300 Initial connection request
linkedin_connection_followup LinkedIn 900 (hard cap) After connection accepted
linkedin_inmail LinkedIn 1,900 InMail to non-connections
email_cold Email 600 First cold email
email_followup Email 400 Follow-up sequence step

Variants (A/B)

Variant Approach When to use
traditional Direct value proposition — CARR's equipment solves your manufacturing challenge Default. Most cold contexts.
path_to_patients Mission-aligned — accelerating your path to getting therapies to patients When connecting to a research- or mission-driven audience. Aligns with CARR's P2P program (rentals, buyback, partnership framing).

Status: path_to_patients is wired in v55 of the EF but has no UX control yet in the CARR app to toggle per-send. It can be invoked via the batch generator or API call; not yet exposed in the modal. This is one of the few wired-but-not-surfaced items.


What flows into the prompt (the 11 sections)

From docs/SSO_MATRIX_DEEP_DIVE_2026-05-11.md §4, order matters:

  1. Sender identity — from team_profiles (display name, headline, about, writing_rules, persona_summary voice)
  2. Target contact — name, title, seniority, department, persona, location, Clay summary/headline/experience, L2 segment_data, engagement history
  3. Account positioning context — keyed off carr_icp_groupicp_groups[mapped_key] + product fit line
  4. Their company — name, modality, dev stage, country/state, description (truncated 600 char), CARR account enrichment (centrifugation fit, scale, separation tech), competitive line if separation tech matches a known competitor
  5. Messaging Strategy (3-tier) — matrix angle + pain points + value props + suggested hook
  6. Messaging Variant — P2P block when applicable
  7. Relevant Value Pillars (VPC) — 1–2 pillars matched to the role angle
  8. Recent Account Signals (v55) — funding summary + ≤2 news + ≤2 trials + ≤1 grant, capped 1,200 chars, "use AT MOST ONE" instruction
  9. Custom Context — operator free-text
  10. Message Instructions — type, max chars, tone, goal, length rules
  11. Products / Tone rules / Banned phrases / Preferred vocabulary

This 11-section assembly is why the messages don't read like generic LLM output — every section is CARR-specific and CARR-supplied.


The 3 generation surfaces (all use identical logic)

Surface Trigger What runs
generate-outreach-message EF v55 Single message from UI / batch caller Full 11-section prompt → Claude Sonnet 4 (→ gpt-4o-mini fallback) → drafts persisted
batch-generate-outreach EF v51 Bulk from v_campaign_contact_segments Same prompt, batched up to 50 contacts per run, per-batch cache for shared company data
run_batch_outreach_generation.py (VPS) Drains v_evergreen_outreach_generation_queue Calls the single EF per row — inherits all features

All three share the same buildPrompt, loadAccountSignals, formatAccountSignalsBlock, resolveMessagingStrategy, deriveMarketingPersona. There is no prompt drift across surfaces.


The writing-rules guardrail (Nico-specific, generalizable)

Added in Track 0 of the May buildout. Per-rep, persistable:

team_profiles
  ├── writing_guidelines (TEXT)      — soft style preferences
  ├── required_phrases (TEXT[])      — must include
  └── banned_phrases (TEXT[])        — must NOT include

At generation time the EF:
1. Pulls the sender's writing rules from team_profiles
2. Injects them into the prompt
3. After generation, runs checkWritingRuleViolations() against the output
4. Logs violations to generation_metadata.writingRulesApplied = true and the specific failing phrases

This is how Nico's feedback gets enforced at scale (per his templates parsed in Inputs/nico_templates_parsed.txt). Currently only Nico's row is populated; the column exists for all 9 senders so the pattern is uniform.


DNC compliance

Three checks happen before any message is generated or sent:

Check Where What
do_not_contact_list lookup At message-generation time (both EFs) 15-row table — sourced from CARR's DoNotContactList.xlsx plus team additions
Tier suppression At fetch time (3 EFs: batch-generate-outreach, push-to-emailbison, send-linkedin-messages) SUPPRESSED_TIERS = ['warm_target', 'active_prospect', 'customer'] — accounts at these tiers never get cold-touched
Account-level skip At campaign-build time UX-driven, rep can mark "don't contact this account"

Account signals (new in v55, May 11)

The major May 11 addition — outreach messages now have access to CARR's live intelligence data (news, trials, grants, funding) as supplementary context:

Source Limit Recency filter
news_intelligence 2 items last 120 days, sorted priority × recency
account_clinical_trials 2 items start date ≤ 3 yrs old, active statuses preferred
account_grants 1 item fiscal year ≤ 2 yrs, active
companies.enrichment_data (funding) inline suppressed if unknown/public/nonprofit/private

Block is capped at 1,200 chars with explicit instruction "use AT MOST ONE." The matrix remains primary; signals are background.

Every message persists the full signals snapshot to outreach_messages.account_signals_snapshot for audit. Metadata gains accountSignalsUsed and enrichmentSources.


Live performance (proof of life)

Smoke test, May 11 — Harish Santhanam (Juno Therapeutics, VP Cell Therapy Tech Ops):

Metric Result
messagingSource db_matrix_cgt (Tier 1, CGT-specific) ✅
marketingPersona TECHNICAL
accountSignalsUsed true ✅
accountSignalsSnapshot.trials 2 entries (NCT07335562, NCT07115745) ✅
accountSignalsSnapshot.funding null (correctly suppressed — stage=public) ✅
Generated InMail 910 chars, subject "CAR-T processing challenges from bench to commercial scale"
Opening "Juno's CAR-T programs moving through clinical development likely face the classic challenge of maintaining cell viability and recovery when scaling separation protocols…"

Matrix dominated; trials provided conceptual support without quoting NCT IDs.


Counts (May 6 snapshot)

Metric Value
Total messages generated 1,635
Sent 16
Draft (awaiting review) 699
Archived 402
Email cold type drafted 748

The 699 drafts awaiting review is the current biggest manual lever: rep approval throughput. Once a rep marks ready_to_send, the cron picks it up and delivers within 2 hours.


What this layer looks like elsewhere

Component Typical alternative Notes
AI message generator (general) Lavender, Regie.ai, Twain, Smartwriter Lavender Pro $29/user/mo published; Regie.ai is quote-only at team plans. None carry CARR's positioning or matrix — they generate generic best-practice email.
Tone-controlled generation Claude / OpenAI API + custom prompt Same engine we use; the value-add is the 11-section prompt assembly.
Pain × persona × value matrix Sales enablement (Highspot, Seismic) + manual maintenance Highspot quote-only, third-party listings reference roughly $30K–$75K/yr. The matrix itself is data + process, not a SaaS thing — it lives in any system that can store the rows.
Writing-rules enforcement Custom code or Lavender's Coach Mode Coach Mode scores live as you type; we enforce on generation.
Account-signals injection None off-the-shelf This is the unique part — most ABM tools surface signals to humans, not to message generation.

Cross-references

  • Canonical audit (most current): docs/SSO_MATRIX_DEEP_DIVE_2026-05-11.md
  • Outreach messaging skill: skills/outreach_messaging.md
  • Messaging matrix data: context/icp/messaging_matrix.md
  • Message generation contract: context/icp/messaging_generation.md
  • EF source: supabase/functions/generate-outreach-message/index.ts (v55 banner)
  • Batch EF source: supabase/functions/batch-generate-outreach/index.ts (v51 banner)
  • Live intelligence data feeding signals: 09_live_intelligence_apis.md

Live Intelligence APIs

Download .docx

09 — Live Intelligence APIs (The Moat)

Parent: 00_INDEX.md · Reading time: 6 min

This is the part that doesn't show up in an SDR's morning routine but quietly makes everything more accurate every single day. CARR's account data isn't a snapshot — it's a continuously-refreshed picture, fed by 4 separate data sources running on different cadences. As of v55 of the message generator, this data flows directly into the outreach prompt.

Not in scope: social listening (LinkedIn post/engagement monitoring) and the ELG team-activity feed were never fully built out and are excluded from the platform going forward. They are not part of the migration and are not a deliverable.


The four live data feeds

Source What it provides Refresh cadence Coverage in CARR
BioCreative Hub (cgt_accounts) New CGT companies discovered universe-wide Weekly (Sun 2am) 3,964 companies live
News intelligence Industry news matched to CARR target accounts Every 4 hours 704 articles
ClinicalTrials.gov New + updated trials matched to account sponsors Weekly (Sun 3am) 1,862 trials matched
NIH RePORTER New + ongoing grants matched to academic institutions Weekly (Sun 4am) 5,000 grants matched

Plus references read live from Hub when needed:
- SEC EDGAR — filings for public CGT companies (viewed live, not synced)
- PatentsView — patent activity for CGT companies (viewed live, not synced)


The news pipeline (most active feed)

This is the most visible auto-refreshed source. Architecture from _shared/reference/NEWS_INTELLIGENCE_PIPELINE.md:

BioCreative Hub news pipeline (runs on Ops VPS, 2x/day 05:00 + 17:30 UTC Mon-Sat)
   │
   ├── Source scrapes (industry news outlets, PR wires, company blogs)
   ├── Article classifier (Claude Sonnet 4) — categorizes by priority, topic, company match
   ├── AI analyzer — extracts company mentions, modality tags, deal types
   └── AI enricher — links to matched accounts, scores relevance
        │
        └─→ Hub.client_news_intelligence (master table, all clients)
              │
              ▼  every 4 hours via pg_cron
              sync_news_from_life_science_with_logging()
              │
              └─→ CARR.news_intelligence (CARR-specific filtered subset)

Pipeline cost: ~$1.35/run, ~$2.70/day in Claude API costs at the Hub. CARR pays $0 for sync (just PostgreSQL pg_net HTTP calls).

Where it surfaces

  • News page (/news) — chronological feed
  • Account Detail → News tab — per-account news history
  • High-priority news appears in Task Center as alerts
  • As of v55 — top 2 news items inject into outreach prompts as account signals

Clinical trials (CARR's strongest signal source)

For a centrifuge-equipment company, clinical trials are the leading indicator of buying activity:
- New Phase 2/3 trial start → manufacturing scale-up imminent → equipment decision window
- Phase transition (1→2, 2→3) → process re-validation → upgrade opportunity
- Site activation → CMO/CDMO selection → competitive equipment decision

The pipeline:

  1. sync_clinical_trials_from_hub() runs Sunday 3am
  2. Pulls all trials where sponsor name matches a CARR account
  3. Writes to account_clinical_trials with start_date, phase, status, modality
  4. Account signals loader (v55 EF) pulls top 2 active trials per account into outreach prompts
  5. Trials page (/account-detail/:id/trials) shows the full per-account picture

Coverage: 1,862 trials matched to CARR accounts. 341 distinct companies have at least one tracked trial — meaning the account-signals layer can use real trial data for nearly every late-stage CGT therapeutic developer in CARR's universe.


NIH grants (academic-side intelligence)

For academic institutions (570+ in CARR's universe), NIH grants are the funding leading indicator. The pipeline:

  1. sync_grants_from_hub() runs Sunday 4am
  2. Matches grant recipient organization name to CARR academic accounts
  3. Writes to account_grants with PI name, fiscal year, award amount, project description
  4. Account signals loader picks up the most recent active grant per academic account

Coverage: 5,000 grants matched across 90 distinct institutions. Deep coverage on the institutions that get most CGT NIH funding (Stanford, Harvard, Penn, Duke, etc.).


SEC EDGAR + Patents (read-live, not synced)

These don't need their own CARR-side tables because they're querable from the Hub on demand:

  • SEC filings — 10-K, 10-Q, 8-K filings for publicly-traded CGT companies. Surfaces material events: facility expansions, manufacturing partnerships, capital raises, M&A.
  • Patents — granted + applications mapped to CGT companies. Forward-looking signal of technology direction.

Both available at Hub mjsgtszehjltxmbxtctz — 2,800+ filings, 2,900+ patents universe-wide. Read live when needed; not pre-synced because volume is large and use-case is more episodic.


What "match a trial to a CARR account" actually means

This is the part that's harder than it sounds. Trial sponsors are recorded as free-text — "Juno Therapeutics" vs "Juno Therapeutics, Inc." vs "Juno Therapeutics, Inc., a Bristol-Myers Squibb company" — all the same company. The matching pipeline:

  1. Tokenize sponsor name + lemma + lowercasing
  2. Compare against companies.company_name, aka_names[], and parsed alias variants
  3. PostgreSQL pg_trgm similarity scoring + threshold
  4. Manual review queue for low-confidence matches

Plus organization-restructuring awareness — when Juno was acquired by BMS, both names should match. This is handled in the Hub-side matching, not CARR-side.

Same logic applies to NIH grants (recipient organization names), patents (assignee names), and news (company mentions extracted by AI).


How it all converges in the outreach prompt

For a Tier 1 therapeutic developer contact, the "Recent Account Signals" block in the prompt might look like:

RECENT ACCOUNT SIGNALS (background context — use AT MOST ONE):

Funding: Series C, $180M raised Q4 2025. Lead investors: ARCH Venture Partners,
Casdin Capital.

Trials: NCT07335562 — Phase 3, NOT_YET_RECRUITING, "Allogeneic CAR-T for r/r DLBCL"
(start 2026-08-12). NCT07115745 — Phase 1, RECRUITING (start 2026-03-04).

News: 2026-04-22, "Juno announces $80M GMP manufacturing expansion in Seattle"
(priority: high, deal_type: facility_expansion).

Grants: (no active NIH grants — company is for-profit, public stage).

This block adds maybe 800 characters to the prompt. It's hard-capped at 1,200. The instruction explicitly tells the LLM to reference at most one of these signals, conceptually — not to list them.

The result: messages reference real, current, account-specific context without sounding like a database dump.


What this layer looks like elsewhere

Component Typical alternative Notes
Company news monitoring Owler, Crunchbase Pro, Google Alerts + Slack Owler Pro published ~$420/yr per user; Crunchbase Pro published $49/user/mo. Neither is structured for AI consumption.
Clinical trial tracking Citeline Trialtrove, GlobalData, ClinicalTrials.gov direct + manual matching Citeline Trialtrove and GlobalData are enterprise pharma intelligence subscriptions — typically five-figure annual minimum, quote-only.
NIH grants NIH RePORTER (free, but raw) + manual matching Free at the source, but match-to-account at scale is a data-engineering project.
Patents PatSnap, Questel Orbit, Derwent Innovation All enterprise IP databases — multi-five-figure annual subscriptions.
Intent data (third-party) Bombora, 6sense, Demandbase All quote-only ABM platforms. Bombora data feeds into many of them.
Unified feed into AI prompts None The "all these sources, AI-matched per account, injected into outreach generation" pattern isn't an off-the-shelf product.

Most teams use 2–3 of these sources separately, surface them in dashboards, and rely on humans to synthesize. The CARR system collapses the synthesis into the message-generation step.


Honest limitations

  1. News with company_id direct link is sparse — 38 rows / 26 distinct companies. Most news is matched via matched_accounts[] array; future enhancement could pull array-matched into the signals loader too (see SSO deep-dive §8 "Open gaps").
  2. Patents + SEC filings not synced into CARR yet — they exist on the Hub, can be queried live, but aren't in CARR's account_signals loader. Low-hanging future addition.

Cross-references

  • News pipeline reference: biocreativeaihub/_shared/reference/NEWS_INTELLIGENCE_PIPELINE.md
  • News pipeline runbook: biocreativeaihub/departments/internal-ops/context/operations/NEWS_PIPELINE_RUNBOOK.md
  • Data flows: context/database/data_flows.md
  • Hub-to-CARR sync map: context/database/hub_to_carr_sync_map.md
  • SSO matrix account signals integration: docs/SSO_MATRIX_DEEP_DIVE_2026-05-11.md §4

Outreach Infrastructure

Download .docx

10 — Outreach Infrastructure (Domains, Inboxes, Seats, Warming)

Parent: 00_INDEX.md · Reading time: 6 min · Cross-ref: docs/CARR_LINKEDIN_EMAIL_PIPELINE_STATE_2026-05.md, EMAILBISON_MODULE.md, docs/runbooks/heyreach.md

The most invisible but most expensive-to-redo layer. Buying domains, configuring DNS, warming inboxes for 10 weeks, connecting LinkedIn seats, registering webhooks, building send pipelines — none of this shows up in the UX but all of it is the difference between messages landing in inbox vs. spam folder. This is where the engagement has the deepest sunk cost that compounds for whoever operates the system.


Email infrastructure

Domains purchased + DNS-configured

3 dedicated sending domains for CARR outreach (not CARR's primary carrbiosystems.com, which would risk that domain's reputation):

Domain Purpose
carrbiosystemsconnect.com Sender pool 1
carrbiosystemsoutreach.com Sender pool 2
explorecarr.com Sender pool 3

Each domain has:
- SPF record published
- DKIM keys configured
- DMARC policy set
- MX records routed
- 10+ weeks of warming completed

Warming = sending small volumes of low-priority/internal emails over time, letting reputation build with ISP filters. Premature high-volume sends from a cold domain land in spam. The 10-week warming runway is the single most time-locked piece of the infrastructure.

Mailboxes / sender personas

5 mailboxes warmed and active across the 3 domains, mapped 1:1 to sending personas in team_profiles:

Mailbox persona Real person
jacob.andrews@... Jacob Andrews
jeff.plambeck@... Jeff Plambeck
andrew.hallet@... Andrew Hallet
bethanne.deuel@... Bethanne Deuel
nico.summaria@... Nico Summaria

Note from CARR_LAUNCH_READINESS_2026-05.md: SOW originally referenced 16 mailboxes. 5 are warmed and active in DB. The 11 difference is either a target that wasn't reached, lives in a separate workspace, or a stale plan number — flagged for confirmation with Bethanne/Nico before sizing the first email sequence.

EmailBison instance

Self-hosted EmailBison instance running on BioCreative VPS:
- Base URL: https://send.biocreativestrategies.com/api
- Workspace dedicated to CARR
- Vault secret emailbison_api_key in CARR Supabase

Why self-hosted: shared SaaS sending infrastructure (Smartlead, Instantly cloud, etc.) means your reputation is averaged with whoever else is on the shared pool. Self-hosted = full control of IP reputation. Also = no per-seat licensing.

EmailBison campaigns staged

4 evergreen campaigns built, contacts loaded, ready to activate:

Rep Contacts loaded Status
Bethanne Deuel 173 Draft, ready to activate
Andrew Hallet 123 Draft, ready to activate
Jeff Plambeck 103 Draft, ready to activate
Nico Summaria 101 Draft, ready to activate

Total: 500 contacts loaded, 0 sent. Activation gated on:
- Final vault-secret confirmation (EMAILBISON_API_URL, EMAILBISON_API_KEY, EMAILBISON_WORKSPACE_ID)
- Rep final-sequence sign-off
- Mailbox-count confirmation (the 5 vs 16 question)

This is the #1 carryover from Month 3 → Month 4.


LinkedIn infrastructure (HeyReach)

Seats

5 HeyReach seats, one per active rep, all authenticated:

Rep HeyReach seat
Andrew Hallet ✅ auth valid
Bethanne Deuel ✅ auth valid
Jacob Andrews ✅ auth valid
Jeff Plambeck ✅ auth valid
Nico Summaria ✅ auth valid

auth_is_valid = true for all 5 (verified via HeyReach API May 5). is_active = false on all 5 — this is the open issue, likely upstream seat-state quirk; sends still work via resumeFinishedCampaign:true. On the bug list.

Campaigns

30 total campaigns across the seats:
- 5 DRAFT — new "[Rep] — LinkedIn — Evergreen" stage-1 connection-request campaigns (407475–407490). Brian launches these in HR UI when ready.
- 25 FINISHED — older "CARR Followup-2 — [Rep]" follow-up message campaigns (377xxx). Auto-resumed on each accepted-connection event via resumeFinishedCampaign:true.

This 2-stage pattern (connection-request campaign + follow-up message campaign) is necessary because HeyReach's API doesn't support CreateCampaign, and connection-only campaigns can't send follow-up DMs from inside themselves. So CARR's setup is by design, not by accident.

Send + reply pipelines

Pipeline EF Cadence
LinkedIn message delivery send-linkedin-messages v39 Every 2h via pg_cron
Reply capture heyreach-webhook v35 Real-time
Campaign + lead sync sync_all_from_heyreach() Every 6h
Connection cache refresh refresh_heyreach_connections Every 6h
Lead matching to contacts match_heyreach_leads() Every 12h

The send pipeline is 3-path:

For each ready_to_send LinkedIn message:
   1. Existing conversation? (inbox/GetConversationsV2)
      YES → inbox/SendMessage → status='sent'

   2. Connected? (local cache → MyNetwork/IsConnection)
      YES → AddLeadsToCampaignV2 with customUserFields[followup_message]
            + resumeFinishedCampaign:true + resumePausedCampaign:true
            → status='sent'

   3. Not connected
      → status='waiting_for_connection' (next cron retries)

This 3-path approach is what makes the system work despite HeyReach's API limitations.

Webhooks (11 event types registered)

All 11 HeyReach event types are registered, active, and routing to heyreach-webhook v35:

CONNECTION_REQUEST_SENT/ACCEPTED · MESSAGE_SENT/REPLY_RECEIVED · INMAIL_SENT/REPLY_RECEIVED · FOLLOW_SENT · LIKED_POST · VIEWED_PROFILE · CAMPAIGN_COMPLETED · LEAD_TAG_UPDATED.

When a connection is accepted: webhook fires → lead_connection_status = 'connected'match_heyreach_leads() runs → contact appears in v_rep_linkedin_followup_queue (currently 165 rows) → rep generates a follow-up.

Live results to date

Metric Value
Total connection requests sent ~800
Connection requests accepted 157 (~16% acceptance rate — above industry baseline)
Conversations opened 2
LinkedIn messages sent ~62
Replies 8
Best campaign acceptance rate 36% (Jake Top Accounts)

The 16% blended acceptance is solid for cold connection requests in a niche B2B segment — industry-wide LinkedIn outreach benchmarks commonly land in the 10–25% range depending on personalization and targeting tightness.


Webhook + reply infrastructure (the other half)

Email replies need to flow back into the system so reps can respond, conversations get tracked, and accounts auto-promote to warm_target.

Webhook EF Handles
emailbison-webhook v6 LEAD_REPLIED, LEAD_INTERESTED, EMAIL_BOUNCED, LEAD_UNSUBSCRIBED, TAG_ATTACHED/REMOVED
emailbison-reply v4 Proxy a reply back to EmailBison API (lets reps reply from inside the CARR app)
emailbison-forward v4 Proxy a forward (escalate-to-pipeline flow)
heyreach-webhook v35 All 11 HeyReach event types
carr-bison-reconcile v5 Match EmailBison contacts back to CARR contact records

Auto-promotion logic: when a webhook fires with a real reply (not bounce/OOO/unsub), the account moves from cold_targetwarm_target automatically, and the 3 SUPPRESSED_TIERS filters in the send pipelines prevent any further cold touches. Documented in skills/target_universe_tiers.md.


What this layer looks like elsewhere

Component Typical alternative Notes
Sending domains Mailforge, Mailreef, Premiumto, manual setup with registrar + DNS Mailforge starts ~$0.50/mailbox/mo public pricing; setup of 3 domains with DNS + warming workflow is normally a multi-week setup project.
Domain warming Warmup Inbox, Mailwarm, Smartlead (built-in), Instantly (built-in) $7–$25/mailbox/mo. 8–12 week warming is industry standard regardless of tool.
Email-sending platform Smartlead, Instantly, Apollo Sequences, Outreach, Salesloft, EmailBison (used, self-hosted) Smartlead $39+/mo published, Instantly $37+/mo published. Outreach + Salesloft are enterprise SaaS, quote-only, commonly in the four-figure annual per seat range.
LinkedIn automation HeyReach (used), Expandi, Dripify, Linked Helper, Skylead HeyReach $79+/seat/mo published; Expandi $99/seat/mo. The 5-seat setup is meaningful sunk-cost in seat licensing.
Webhook + reply infrastructure Built into Outreach / Salesloft / Apollo Sequences Same EFs we built; the alternative is bundled in higher-tier sales engagement platforms.
Reply intent classification Custom logic, or Lavender / Drift / native Our classifier distinguishes replies / bounces / OOO / unsubscribe and routes accordingly.

Where the sunk cost compounds:
- 10 weeks of warming doesn't transfer easily. New domains = restart from zero.
- 5 HeyReach seats carry the connection-history reputation of those LinkedIn accounts.
- Reply data captured populates feedback loops that make the next round of messaging smarter (writing rules, banned phrases, conceptual agreement signals).

If CARR ever runs this on its own, the domains + inboxes + seat licenses are the parts that don't need to be rebuilt — just transferred. The Edge Functions, schemas, and integration logic are open-source-style portable (Deno + standard PostgreSQL).


Cross-references

  • LinkedIn + email pipeline state (canonical): docs/CARR_LINKEDIN_EMAIL_PIPELINE_STATE_2026-05.md
  • Launch readiness audit: docs/CARR_LAUNCH_READINESS_2026-05.md
  • EmailBison module: EMAILBISON_MODULE.md
  • HeyReach runbook: docs/runbooks/heyreach.md
  • EmailBison runbook: docs/runbooks/emailbison.md
  • Campaign operations skill: skills/campaign_operations.md
  • Hub-level pipeline reference: biocreativeaihub/_shared/reference/HEYREACH_EMAILBISON_PIPELINE_REFERENCE.md

Supporting Assets & Custom Code

Download .docx

11 — Supporting Assets, Custom Code, Docs

Parent: 00_INDEX.md · Reading time: 5 min

Beyond the data + automation layers, a comparable assembly of supporting assets sits in the CARR + BioCreative repos. None of it shows up in the live UX but all of it is the durable knowledge base the system can be picked up, debugged, extended, or handed off with.


Landing pages

3 dedicated landing pages deployed (HTML + custom branding):

Page Audience Purpose
accelerate.html Therapeutic developers in scale-up "Accelerate your path to clinic" framing — Path-to-Patients program intro
autologous.html Autologous CAR-T / TCR developers Modality-specific landing with autologous workflow benefits
(third landing) Allogeneic / iPSC developers Allogeneic-specific framing

Source: biocreativeaihub/projects/carr-landing-pages/ (deployed to dedicated VPS).
Tech stack: static HTML + custom CSS, CARR brand colors, deployed via Hostinger VPS with Traefik for SSL.

Pattern is replicable — same framework can serve additional landing pages for stainless-steel product line, EMEA-specific framing, conference event pages, etc. Cost per new landing page is hours, not days.


Branded assets

Generated through the BioCreative image-gen pipeline using CARR's design system:

  • Social cards — LinkedIn post imagery aligned to brand
  • Carousel slides — for multi-slide LinkedIn posts (Content Studio output)
  • Email headers / banners — for sequence emails
  • Article header imagery — for newsletter pieces
  • Diagram exports — Excalidraw diagrams of the system (~10+ in public/diagrams/)

All driven by Research/CARR_MASTER_DESIGN.md (colors, typography, design tokens). Replicable for each new piece — the design system is a JSON/markdown contract, not a single PSD.


Custom scripts (the code we wrote)

In scripts/ of the CARR repo:

Category Count Examples
Colab notebooks 5+ Account enrichment, contact import, contact classifier v4, batch email generator, account matcher
SQL scripts 40+ Migrations, RPC bodies, view definitions, backfills, audits
Python scripts 40+ Enrichment runner, classifier runners, sync scripts, audit scripts, validation runners
PowerShell 3–5 Build / smoke test orchestration

In biocreativeaihub/scripts/ (Hub-side, supports CARR):

  • News pipeline orchestrator (news_pipeline/)
  • Hub→CARR sync scripts
  • Bulk message generation via Claude CLI on VPS (bc_bulk_generate_vps.py)
  • Persona classifier templates
  • Stakeholder registry matching

Total custom Python/SQL: ~80+ files of CARR-specific or CARR-supporting code. Most are <300 lines each — small, focused, debuggable.

The enrichment runner (high-value example)

scripts/enrichment_runner/ — a Flask-based local web app for running enrichment workflows interactively:
- Tabs for account enrichment, persona classification, validation, ICP review
- Direct DB connection (no auth friction)
- Used internally by BioCreative when running enrichment at higher volumes than the Colab notebooks support


Edge Functions (the runtime backbone)

18 EFs deployed in CARR's Supabase. Each is custom-built for CARR's data model:

Category EFs
Message generation generate-outreach-message v55, batch-generate-outreach v51
LinkedIn pipeline send-linkedin-messages v39, heyreach-webhook v35, create-heyreach-lead-lists v28
Email pipeline push-to-emailbison v18, sync-emailbison v9, emailbison-webhook v6, emailbison-reply v4, emailbison-forward v4, carr-bison-reconcile v5, bison-lead-inspect, bison-camp-bump-limits
Validation validate-data-flag v2
Content generate-carr-newsletter v1, generate-content v45
Other transcribe-audio v84

Each EF is in Deno (Supabase's runtime). Source is in supabase/functions/ in the repo. Banner comments in every EF declare version + change log.


Documentation

The repo is documentation-first. Bulleted summary of what exists:

Skills (canonical task patterns)

carr-biosystems-hub/skills/ — 14 files covering account enrichment, campaign operations, contact management, database query, deck generation, diagram generation, HeyReach setup, HeyReach API, market intel, note validation, outreach messaging, target universe tiers, client digest email.

Context (deep reference)

carr-biosystems-hub/context/ — 10 files in 4 sub-folders:
- brand/ — design, voice, products
- database/ — schema reference, data flows, hub-to-CARR sync map
- icp/ — account classification, contact classification, scoring model, messaging matrix, messaging generation
- ux/ — modal patterns, contact modal map, SSO visibility map

Runbooks (operational playbooks)

carr-biosystems-hub/docs/runbooks/ — 7 files: campaigns_modal_routing, carr_newsletter_send_playbook, emailbison, heyreach, linkedin_export_guide, outreach_suppression, validate_data_flag.

Monthly reviews + audits

  • docs/CARR_MONTH_ONE_REVIEW.md / _TWO_REVIEW.md / _THREE_REVIEW.md
  • docs/CARR_LAUNCH_READINESS_2026-05.md
  • docs/CARR_LINKEDIN_EMAIL_PIPELINE_STATE_2026-05.md
  • docs/SSO_MATRIX_DEEP_DIVE_2026-05-11.md
  • docs/NICO_FEEDBACK_SYNTHESIS.md
  • docs/CARR_PIPELINE_SMOKE_2026-05.md

Top-level reference

  • CARR_SYSTEM_OVERVIEW.md — the platform user guide written for CARR leadership (v3.5)
  • CARR_PROJECT_STATUS.md — current state
  • CARR_PLATFORM_USER_GUIDE.md — end-user guide
  • EMAILBISON_MODULE.md — email infrastructure complete reference
  • README.md, CONTRIBUTING.md

Hub-side BC repo

biocreativeaihub/clients/CARR_Biosystems/ — additional CARR-specific:
- CLIENT_CONTEXT.md
- OPPORTUNITY_SUMMARY.md
- CARR_PROJECT_TRACKER.md (master 683-line tracker, v3.0)
- 25+ Markdown research and strategy docs
- 5 Python utility scripts
- 4 CSV data exports

Generated for Jake

  • docs/JAKE_CLAUDE_DESKTOP_MCP_SETUP.md
  • docs/JAKE_CLAUDE_DESKTOP_POWER_USER_GUIDE.md

CI / quality

  • .github/workflows/ci.yml — GitHub Actions CI runs typecheck + lint + tests on push
  • vitest.config.ts — unit test setup
  • tsconfig.app.json / tsconfig.json — TypeScript strict mode
  • ESLint configured with eslint.config.js
  • Tailwind + shadcn/ui design system

What this all amounts to

The 22-page CARR app is the visible layer. Behind it:

  • ~80+ custom Python / SQL scripts
  • 18 Edge Functions
  • 446 schema migrations
  • 95 database views, 111 functions
  • 17 cron jobs
  • 3 landing pages
  • 30+ research documents
  • 14 skills + 10 context docs + 7 runbooks
  • Auto-generated AI content, branded assets, diagrams

The repo is portable and reproducible. Anyone with PostgreSQL + Deno + Node access can stand up an equivalent system from these artifacts. The data + infrastructure investment (domains, warming, LinkedIn seats, Clay credits) is the part that takes time more than money to recreate.


What this layer looks like elsewhere

Component Typical alternative Notes
Landing pages Webflow, Unbounce, custom dev shop Webflow team plans $35+/mo published; dev shop bespoke landing pages typically $3–15K each.
Custom Python/SQL scripts Engineering retainer or in-house data engineer A loaded full-time data engineer is well into the six figures annually.
Edge Functions / serverless API AWS Lambda, Azure Functions, Cloud Run Compute cost is pennies; engineering cost to build the equivalent integrations is the real number.
Documentation discipline Confluence + Notion + dedicated tech writer Tools are inexpensive; the ongoing discipline of keeping docs in sync with the code (e.g., updating SSO_MATRIX_DEEP_DIVE_2026-05-11 when the EF version bumps) is the value.

Cross-references

  • Skills index: skills/README.md
  • Context index: context/README.md
  • Runbooks index: docs/runbooks/
  • Top-level overview: CARR_SYSTEM_OVERVIEW.md
  • Hub-side BC tracking: biocreativeaihub/clients/CARR_Biosystems/CARR_PROJECT_TRACKER.md

Market Alternative Cost Reference

Download .docx

12 — Market Alternative Cost Reference

Parent: 00_INDEX.md · Reading time: 6 min · Purpose: Make the stack choices visible. Not a sales pitch — a reference for whenever the CARR team is choosing where to invest going forward.

The CARR + BioCreative engagement is one of many ways to assemble the layers covered in this package. This file lays out what the comparable commercial stacks look like — for each of the 11 prior layers, what a CARR-equivalent could be built/bought from, and what those tools cost.

Every dollar figure here is either (a) published on the vendor's pricing page, or (b) widely reported in industry research / third-party tracker sites. Quote-only enterprise SaaS prices are clearly marked as such. See _appendix_citations.md for source links.


Reading this table

  • Layer — one of the 11 from this package
  • What CARR has today — the current system component
  • Common commercial alternative(s) — what most B2B companies would buy
  • Published / typical cost — best-available reference cost, with caveats
  • Trade-off note — what's different between the choices

The reference

Layer 02 — Brand + positioning + voice + messaging matrix

What CARR has today Common alternative(s) Published / typical cost Trade-off
4 master docs + 30 research docs + 17K-char positioning JSON injected into every AI generation Brand strategy firm engagement (1-time) + sales enablement platform (ongoing) Brand strategy engagements range from $10K–$120K depending on firm tier (Branding Compass, Lithium, Pentagram — public references). Highspot / Seismic enablement: quote-only, third-party trackers reference roughly $30K–$75K/yr. Off-the-shelf brand work is usually delivered as a slide deck. CARR's positioning is machine-readable and runs at every message generation.

Layer 03 — Hub-spoke database architecture

What CARR has today Common alternative(s) Published / typical cost Trade-off
PostgreSQL hub + per-client spoke, 446 migrations, RLS + vault Snowflake / Databricks + reverse-ETL (Hightouch, Census) + custom sync Snowflake credits start at ~$2/credit for Standard edition (public pricing); small-team usage commonly $1K–$5K/mo. Hightouch Pro starts $1,250/mo (public). Equivalent stack: ~$30K+/yr before engineering. The Supabase choice means lower marginal cost but less mature governance tooling vs Snowflake. Trade is intentional.

Layer 04 — Account universe + ICP scoring

What CARR has today Common alternative(s) Published / typical cost Trade-off
17K Hub TAM filtered to 3,964 CGT, ICP v2 scoring across 4 dimensions, 7-status lifecycle ZoomInfo / Apollo for TAM + 6sense or Demandbase for ABM scoring Apollo public plans up to $99/user/mo (with usage caps); ZoomInfo Advanced is quote-only and routinely cited in five-figure annual ranges per third-party trackers. 6sense / Demandbase are quote-only ABM platforms, commonly placed in high-five-to-six-figure annual range by Forrester / Gartner evaluations. Off-the-shelf TAM data is broad but doesn't carry CGT-specific filters (modality, clinical phase, separation tech). CARR's universe is narrower but tagged for purpose.

Layer 05 — Account enrichment pipeline (CARR-specific)

What CARR has today Common alternative(s) Published / typical cost Trade-off
Hub L2 (22-key) + CARR deep enrichment (centrifuge fit, scale, separation tech) via Firecrawl + Brave + Claude Apollo / ZoomInfo enrichment (universe-wide) + GlobalData or Citeline (pharma intelligence) Apollo/ZoomInfo enrichment is part of their seat licenses. GlobalData / Citeline Trialtrove are enterprise pharma intelligence subscriptions, typically five-to-six-figure annual minimums. The CGT-specific signals (separation tech, manufacturing scale, equipment readiness) aren't in any off-the-shelf data product.

Layer 06 — Contact discovery

What CARR has today Common alternative(s) Published / typical cost Trade-off
104K contacts from PhantomBuster + Sales Nav + Clay Find-People Apollo / ZoomInfo (built-in contact database) Apollo published up to $99/user/mo; ZoomInfo quote-only. Sales Navigator: $99/user/mo (LinkedIn published). PhantomBuster Pro: $129–$899/mo (public plans). Off-the-shelf databases are broader but less tunable. CARR's universe is built around CARR's account list and refreshes from PhantomBuster on-demand.

Layer 07 — Contact enrichment + persona classification

What CARR has today Common alternative(s) Published / typical cost Trade-off
Clay waterfall enrichment + Claude L2 persona classifier (6 personas, CARR-specific) Clay alone, Apollo, ZoomInfo, RocketReach + manual segmentation Clay Pro published $349/mo+; Clay enterprise quote-only; per-contact-credit pricing scales with volume. RocketReach team plans $83+/user/mo published. We use Clay (best email + Linkedin data) for enrichment, then layer CARR-specific persona classification on top. Off-the-shelf Clay is universe-agnostic.

Layer 08 — Message generation (SSO matrix engine)

What CARR has today Common alternative(s) Published / typical cost Trade-off
11-section prompt assembly + 38-row SSO matrix + writing-rules guardrail + account-signals injection + Claude Sonnet 4 Lavender, Regie.ai, Twain (general LLM email assistants) Lavender Pro: $29/user/mo published. Regie.ai: quote-only team plans. Off-the-shelf tools produce generic best-practice email. CARR's outputs reference real products, pain points, account signals, and respect tone rules per sender.

Layer 09 — Live intelligence APIs

What CARR has today Common alternative(s) Published / typical cost Trade-off
News (every 4h) + clinical trials + NIH grants + SEC + patents — all matched to CARR accounts and injected into outreach Owler + Crunchbase Pro + Citeline + manual matching Owler Pro: ~$420/yr per user (public). Crunchbase Pro: $49/user/mo (public). Citeline Trialtrove: enterprise, quote-only. Assembled stack: easily $10K+/yr in tool licenses before integration. Most teams use these as dashboards humans read. CARR's stack injects directly into AI message generation.

Layer 10 — Outreach infrastructure

What CARR has today Common alternative(s) Published / typical cost Trade-off
3 warmed domains, 5 mailboxes warmed 10+ wks, EmailBison self-hosted, 5 HeyReach seats, full webhook + reply pipelines Mailforge + Smartlead + HeyReach/Expandi + custom dev Mailforge: ~$0.50/mailbox/mo public. Smartlead: $39+/mo (public). HeyReach: $79+/seat/mo (public). Expandi: $99/seat/mo (public). Combined for CARR-equivalent setup: ~$400–$900/mo in software alone, plus 8–12 weeks of warming. The 10+ weeks of warmed reputation is the largest sunk cost — it doesn't transfer to new domains.

Layer 11 — Supporting assets + custom code

What CARR has today Common alternative(s) Published / typical cost Trade-off
80+ Python/SQL scripts, 18 EFs, 446 migrations, 14 skills, 10 context docs, 7 runbooks, 3 landing pages Engineering retainer or in-house data engineer + Webflow / dev shop for landing pages Loaded full-time data engineer: well into six figures annually at fully-burdened cost. Dev-shop landing page: $3K–$15K each. Webflow team: $35+/mo (public). Custom code is portable and reproducible from the repo; the alternative is per-feature engineering cost.

Stacked together — directional reference

This is not a like-for-like comparison or a quote. It's a directional reference for what assembling the equivalent stack at retail prices would look like if a B2B team built it themselves with off-the-shelf tools:

Bucket Likely commercial stack Directional annual range
Brand + positioning + messaging Strategy firm engagement + sales enablement platform $30K–$100K+ (1-time strategy) + $30K–$75K/yr ongoing
TAM + ABM scoring ZoomInfo Advanced + 6sense or Demandbase Quote-only, commonly cited five-to-six-figure annual
Account / contact enrichment Apollo Pro + Clay Pro + RocketReach (or replacement) Apollo per seat + Clay $349+/mo + RocketReach $83+/user/mo
Intelligence (news / trials / social) Owler + Crunchbase Pro + Sprout Social + Citeline Owler $420/user/yr + Crunchbase $49/user/mo + Sprout $399/user/mo + Citeline (quote-only)
Outreach platform Smartlead + HeyReach + Mailforge $400–$900/mo software (3 domains, 5 LinkedIn seats) + 10+ wk warming
AI message generation Lavender Pro + Anthropic / OpenAI usage $29/user/mo + per-token API
Engineering / integration Full-time data engineer or retainer Loaded six figures annually
Custom landing pages Dev shop or Webflow + designer $3K–$15K/page or $35+/mo platform

The point of this list is not to say this is cheaper than that. The point is the equivalent stack is real, the components are nameable, the costs are knowable, and the tradeoffs are visible. CARR's investment in this engagement has produced an assembled stack with:

  • Data + logic that lives in CARR's own database
  • No per-seat or per-credit lock-in to external platforms beyond the explicit ones (Clay, HeyReach, EmailBison)
  • A documented, reproducible system that the CARR team can pick up and extend

When CARR (or BW IT, or anyone) chooses what to do with this going forward — keep operating it as-is, migrate to Azure as discussed with John Katsapis, layer in additional commercial tools, or transition pieces to internal teams — knowing what each layer costs to replace at retail is the reference for that decision.


What's not in this comparison (intentionally)

  • Hours spent — both BioCreative's and CARR's team's. This isn't a value-of-time argument.
  • Per-meeting / per-deliverable retainer breakdowns. The SOW already documents that.
  • Future-state pricing for any continuation tier. That's a separate conversation.
  • Subjective quality comparisons. The point of this layer is to show that what was built has off-the-shelf analogs, and what those analogs cost — not to argue one is "better."

Cross-references

  • All citation sources: _appendix_citations.md
  • Forward options: docs/CARR_MONTH_FOUR_PLUS_ROADMAP.md (3 options at end of initial term)
  • Continuation analysis: clients/CARR_Biosystems/CARR_SOW_CONTINUATION_ANALYSIS.md (in Hub repo)

Appendix - Citations & Sources

Download .docx

Appendix — Citations & Sources

Parent: 00_INDEX.md
Purpose: Source links for every external pricing or industry claim made in this package. Internal data (DB counts, deployed versions) cites the in-repo audit docs that produced them.

This is a living reference. When numbers change (vendor pricing pages get updated frequently), update here and re-link from the section docs.


A. Internal sources (in-repo)

These are the canonical audit/state docs that the per-section numbers came from. All in carr-biosystems-hub/:

Reference What it documents
CARR_SYSTEM_OVERVIEW.md v3.5 (May 11, 2026) Master platform overview written for CARR leadership
docs/CARR_MONTH_THREE_REVIEW.md (May 6, 2026) Month 3 honest assessment, SOW scorecard, counts at end of Month 3
docs/CARR_MONTH_FOUR_PLUS_ROADMAP.md (April 14, 2026) Forward-looking 3-option roadmap (VPS / scale current / Azure)
docs/CARR_LAUNCH_READINESS_2026-05.md (May 5, 2026) Pre-launch readiness audit — channels, EFs, crons, search-path, queues
docs/CARR_LINKEDIN_EMAIL_PIPELINE_STATE_2026-05.md (May 5, 2026) End-to-end LinkedIn + email pipeline state
docs/SSO_MATRIX_DEEP_DIVE_2026-05-11.md (May 11, 2026) Canonical SSO matrix + message generation audit
docs/NICO_FEEDBACK_SYNTHESIS.md (April 22, 2026) Nico's 222 notes audit, HITL loop v1
docs/CARR_PIPELINE_SMOKE_2026-05.md Post-fix smoke test results
EMAILBISON_MODULE.md EmailBison architecture + deployment reference
skills/outreach_messaging.md v1.3 (May 11) Outreach skill canonical
skills/contact_management.md v1.2 (May 11) Contact pipeline canonical
skills/target_universe_tiers.md (May 11) Engagement-status taxonomy canonical
skills/account_enrichment.md Account enrichment pipeline canonical
Research/CARR_BRAND_BIBLE.md + Research/CARR_MASTER_BRAND_VOICE.md + Research/CARR_MASTER_DESIGN.md + Research/CARR_LANDING_PAGES.md Brand reference foundation

And in biocreativeaihub/:

Reference What it documents
_shared/reference/NEWS_INTELLIGENCE_PIPELINE.md News pipeline architecture
_shared/reference/HEYREACH_EMAILBISON_PIPELINE_REFERENCE.md Cross-client outreach pipeline pattern
_shared/reference/HEYREACH_API_REFERENCE.md v2.1 HeyReach API reference
_shared/reference/EMAILBISON_API_REFERENCE.md v1.2 EmailBison API reference
departments/client-mgmt/launch/SPOKE_ENRICHMENT_PATTERN.md Hub-spoke enrichment rules
departments/internal-ops/context/operations/NEWS_PIPELINE_RUNBOOK.md News pipeline operational runbook
clients/CARR_Biosystems/CARR_PROJECT_TRACKER.md v3.0 (683 lines) Master CARR project tracker

B. External vendor pricing (linked, last verified May 13 2026)

Note on pricing: Most B2B sales-tech vendors update their pricing pages frequently and use quote-only enterprise tiers. Where a public price is cited, it's the entry/professional tier. Where quote-only, third-party tracker references (G2, Vendr, public RFP databases) are noted.

Sales engagement / messaging

  • Lavender — Pro tier $29/user/mo (public): https://www.lavender.ai/pricing
  • Regie.ai — quote-only: https://www.regie.ai/pricing
  • Outreach / Salesloft — both quote-only enterprise: https://www.outreach.io/pricing , https://salesloft.com/pricing
  • Smartlead — public plans from $39/mo: https://smartlead.ai/pricing
  • Instantly — public plans from $37/mo: https://instantly.ai/pricing
  • EmailBison — self-hosted (no per-seat fees on the BioCreative-hosted instance)

LinkedIn automation

  • HeyReach — public plans from $79/seat/mo: https://heyreach.io/pricing
  • Expandi — public plans from $99/seat/mo: https://expandi.io/pricing
  • Dripify — public plans from $59/user/mo: https://dripify.io/pricing
  • LinkedIn Sales Navigator — $99/user/mo Core, $149+/user/mo Advanced: https://business.linkedin.com/sales-solutions/sales-navigator
  • PhantomBuster — public plans $69–$899/mo: https://phantombuster.com/pricing

Contact / company data

  • Apollo.io — public plans up to $99/user/mo with usage caps; enterprise quote-only: https://www.apollo.io/pricing
  • ZoomInfo — quote-only; third-party trackers (Vendr, G2 reviews) cite four-to-five-figure annual minimums commonly: https://www.zoominfo.com
  • Cognism — quote-only: https://www.cognism.com
  • LeadIQ — public plans from $0 → $89/user/mo Pro: https://leadiq.com/pricing
  • RocketReach — public plans from $83+/user/mo for team tier: https://rocketreach.co/pricing
  • Hunter — public plans from $49+/mo: https://hunter.io/pricing
  • Anymailfinder — public plans from $14+/mo: https://anymailfinder.com/pricing

Enrichment + waterfall

  • Clay — Pro tier $349/mo published, enterprise quote-only: https://www.clay.com/pricing

ABM / account scoring

  • 6sense — quote-only; Forrester/Gartner ABM evaluations and Vendr listings commonly place enterprise ABM platforms in the high-five-to-six-figure annual range: https://6sense.com
  • Demandbase — quote-only: https://www.demandbase.com
  • MadKudu — quote-only: https://www.madkudu.com
  • RollWorks — quote-only: https://www.rollworks.com

Intelligence / market data

  • Owler — Owler Pro ~$420/year per user (public): https://www.owler.com/pricing
  • Crunchbase Pro — $49/user/mo (public, billed annually): https://about.crunchbase.com/pricing
  • PitchBook — quote-only; widely-reported as five-figure annual: https://pitchbook.com
  • CB Insights — quote-only: https://www.cbinsights.com
  • Citeline Trialtrove — quote-only pharma intelligence subscription: https://www.citeline.com
  • GlobalData — quote-only: https://www.globaldata.com
  • PatSnap — quote-only IP intelligence: https://www.patsnap.com

Sales enablement / content

  • Highspot — quote-only; Vendr listings commonly reference ~$30K–$75K/yr ranges: https://www.highspot.com
  • Seismic — quote-only: https://seismic.com
  • Showpad — quote-only: https://www.showpad.com

Email infrastructure

  • Mailforge — public pricing from ~$0.50/mailbox/mo: https://mailforge.ai
  • Mailreef — public pricing varies: https://mailreef.com
  • Warmup Inbox — $7+/mailbox/mo (public): https://warmupinbox.com/pricing

Data warehouse + reverse-ETL

  • Snowflake — public pricing ~$2+/credit Standard edition; usage-based: https://www.snowflake.com/pricing
  • Databricks — usage-based: https://www.databricks.com/product/pricing
  • Hightouch — Pro starts $1,250/mo (public): https://hightouch.com/pricing
  • Census — public plans from ~$300/mo: https://www.getcensus.com/pricing

Landing pages / web

  • Webflow — team plans from $35/mo (public): https://webflow.com/pricing
  • Unbounce — public plans from $99/mo: https://unbounce.com/pricing

Hosting

  • Hostinger VPS — public KVM2 from ~$5–$8/mo: https://www.hostinger.com/vps-hosting

Call / conversation intelligence (referenced indirectly)

  • Gong — quote-only; third-party trackers reference ~$1,500/user/yr+: https://www.gong.io
  • Klue (win-loss + competitive intel) — quote-only: https://klue.com

C. Industry research references

These are publicly-available analyst / publication sources cited indirectly:

  • Forrester Wave: ABM Platforms — sets the framing for enterprise ABM tier sizing (Forrester subscriber reports)
  • Gartner Magic Quadrant: B2B Marketing Automation — same: https://www.gartner.com
  • G2 reviews + pricing transparency — used as third-party tracker for quote-only enterprise tools: https://www.g2.com
  • Vendr (vendor pricing transparency) — public RFP price benchmarks: https://www.vendr.com
  • LinkedIn outreach acceptance-rate benchmarks — industry baseline (10–25% for cold connection requests in niche B2B) commonly cited across LinkedIn sales blog, HeyReach + Expandi published benchmark reports
  • Miller Heiman Strategic Selling framework — now owned by Korn Ferry; framework reference materials: https://www.kornferry.com
  • B2B email deliverability — best practices on domain warming and IP reputation widely published by ISP filter docs (Google Postmaster Tools, Outlook SNDS), Smartlead/Instantly blogs, EmailBison docs

D. AI / LLM API pricing (used internally)

  • Anthropic (Claude) — public per-token pricing: https://www.anthropic.com/pricing#api
  • Claude Sonnet 4 used by generate-outreach-message, news classifier, persona classifier
  • OpenAI — public per-token pricing: https://openai.com/api/pricing
  • gpt-4o-mini used as fallback in generate-outreach-message
  • Brave Search API — public per-query pricing: https://api.search.brave.com/app/subscriptions/static
  • Firecrawl — public credit-based pricing: https://www.firecrawl.dev/pricing

E. How to update this file

When numbers change (vendor pricing page changes, etc.):
1. Update the specific vendor row in §B
2. Update any per-section costs in 12_market_alternative_costs.md that reference it
3. Note the "last verified" date at top of §B

Volatility: B2B SaaS pricing changes commonly mid-quarter. Consider this list a Q2 2026 snapshot.