Platform Value & System Overview
What the CARR platform is and does today - the context beneath the migration.
CARR System Overview
Download .docxCARR 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 databasecarr_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_v2RPC. 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.gov → 1,778 clinical trials matched to CARR accounts by sponsor name
- NIH RePORTER → 1,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_statusnormalized from 21 dirty variants → 6 clean values, then mapped 1:1 intoaccount_tier(now labeled "Account Status" in the UI). Thecarr_statuscolumn is retired from the UI.funding_statusnormalized from ~85 free-text values → 13 clean enums (seed, series_a, public, private, etc.)modalities[]backfilled from classification for 1,268 accountsis_icp_relevantflag 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_tiercolumn): 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-listsedge function creates HeyReach lists from campaign contacts - Automated send pipeline:
send-linkedin-messagesedge function deliversready_to_sendoutreach 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_sendoutreach every 2h, Webhook captures real-time events (opens, replies, bounces) - See
EMAILBISON_MODULE.mdfor 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_positioningdatabase 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 Detail → Contacts 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 .docxCARR × 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 |
| HeyReach (5 seats) | 37 campaigns · 765 leads loaded · 800 CRs sent · 157 accepted · 11 webhook events live | |
| 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.mdv3.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
traditionaltopath_to_patientsper 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 viaresumeFinishedCampaign: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
- Today's meeting (May 14): Walk top-to-bottom, file by file, ~10 min per layer. Pause where it's most useful.
- 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.
- 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.mdv3.5 — the platform overview written for CARR leadership; this package goes deeper on the layers underneathdocs/CARR_MONTH_THREE_REVIEW.md— honest Month 1–3 assessment, SOW vs delivereddocs/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 runbooksdocs/SSO_MATRIX_DEEP_DIVE_2026-05-11.md— canonical messaging system audit
What CARR Gave Us
Download .docx01 — 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:
- 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.
- Paul + Kelvin onboarding (full names, business emails, LinkedIn URLs, sender-domain preference). Unlocks ~1,200 EMEA + APAC accounts.
- 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 .docx02 — 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):
- Sender identity block (from
team_profiles) - Target contact block (Clay summary + L2 segment data)
- Account positioning context keyed off the account's ICP group → injected lead-in
- Account-specific block (modality, dev stage, scale, separation tech) + competitive line if applicable
- Messaging Strategy (3-tier: matrix → icp_groups → role fallback)
- Messaging Variant (Path-to-Patients block if selected)
- Value Pillars (1–2 matched to the role angle)
- Recent Account Signals (news/trials/grants — see
09_live_intelligence_apis.md) - Custom context (operator free-text)
- Message instructions (type, length, tone, goal)
- 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.mdfor 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(seedocs/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 .docx03 — 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 DEFINERfunctions inpublicschema have explicit safesearch_path(verified May 5 audit —CARR_LAUNCH_READINESS_2026-05.md§"Search-Path Regression Check") - Webhook idempotency enforced by unique constraints (HeyReach
eventId, EmailBisonevent_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 .docx04 — 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_REPLIED → emailbison-webhook |
promoteToWarm() → cold_target → warm_target |
| Email "interested" tag | EmailBison LEAD_INTERESTED → emailbison-webhook |
Same |
| LinkedIn connection accepted | HeyReach CONNECTION_REQUEST_ACCEPTED → heyreach-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:
unreviewedat 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:
- A pipeline-opportunity list — even informal. Right now
pipeline_opportunitiesis empty. With a list of active deals, the system can:
- Promote those companies toactive_prospectautomatically
- Backfillbuying_mode,budget_confirmed,fit_confirmedfrom 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) - 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 .docx05 — 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 .docx06 — 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:
- 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.
- 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.
- 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 .docx07 — 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:
- Clay enrichment — pulls headline + summary + experience
- v4 classifier runs →
marketing_persona = technical_leadership, segment_data filled with technical-buyer angle, pain points around scale-up - 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 - 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 .docx08 — 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 |
300 | Initial connection request | |
linkedin_connection_followup |
900 (hard cap) | After connection accepted | |
linkedin_inmail |
1,900 | InMail to non-connections | |
email_cold |
600 | First cold email | |
email_followup |
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_patientsis 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:
- Sender identity — from
team_profiles(display name, headline, about, writing_rules, persona_summary voice) - Target contact — name, title, seniority, department, persona, location, Clay summary/headline/experience, L2 segment_data, engagement history
- Account positioning context — keyed off
carr_icp_group→icp_groups[mapped_key]+ product fit line - 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
- Messaging Strategy (3-tier) — matrix angle + pain points + value props + suggested hook
- Messaging Variant — P2P block when applicable
- Relevant Value Pillars (VPC) — 1–2 pillars matched to the role angle
- Recent Account Signals (v55) — funding summary + ≤2 news + ≤2 trials + ≤1 grant, capped 1,200 chars, "use AT MOST ONE" instruction
- Custom Context — operator free-text
- Message Instructions — type, max chars, tone, goal, length rules
- 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 .docx09 — 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:
sync_clinical_trials_from_hub()runs Sunday 3am- Pulls all trials where sponsor name matches a CARR account
- Writes to
account_clinical_trialswith start_date, phase, status, modality - Account signals loader (v55 EF) pulls top 2 active trials per account into outreach prompts
- 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:
sync_grants_from_hub()runs Sunday 4am- Matches grant recipient organization name to CARR academic accounts
- Writes to
account_grantswith PI name, fiscal year, award amount, project description - 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:
- Tokenize sponsor name + lemma + lowercasing
- Compare against
companies.company_name,aka_names[], and parsed alias variants - PostgreSQL
pg_trgmsimilarity scoring + threshold - 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
- News with
company_iddirect link is sparse — 38 rows / 26 distinct companies. Most news is matched viamatched_accounts[]array; future enhancement could pull array-matched into the signals loader too (see SSO deep-dive §8 "Open gaps"). - Patents + SEC filings not synced into CARR yet — they exist on the Hub, can be queried live, but aren't in CARR's
account_signalsloader. 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 .docx10 — 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_target → warm_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 .docx11 — 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.mddocs/CARR_LAUNCH_READINESS_2026-05.mddocs/CARR_LINKEDIN_EMAIL_PIPELINE_STATE_2026-05.mddocs/SSO_MATRIX_DEEP_DIVE_2026-05-11.mddocs/NICO_FEEDBACK_SYNTHESIS.mddocs/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 stateCARR_PLATFORM_USER_GUIDE.md— end-user guideEMAILBISON_MODULE.md— email infrastructure complete referenceREADME.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.mddocs/JAKE_CLAUDE_DESKTOP_POWER_USER_GUIDE.md
CI / quality
.github/workflows/ci.yml— GitHub Actions CI runs typecheck + lint + tests on pushvitest.config.ts— unit test setuptsconfig.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 .docx12 — 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 .docxAppendix — 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.