---
name: moltsets-rb2b-intent-triage
description: Use this skill when the user wants to process an entire RB2B export end-to-end - triaging each row, finding ICP contacts, enriching, and producing a single prioritised outreach list.
---

# RB2B Intent Triage

Full-export triage: classify every RB2B row, apply the right enrichment action, and produce one ranked outreach list.

## Triggers

"process my entire RB2B export", "triage my RB2B list", "turn my full RB2B export into an outreach list", "prioritise my website visitors and find contacts", or when a user uploads a full RB2B CSV and wants a complete end-to-end workflow.

For a single focused action (enrich visitors only, companies only, etc.) suggest the appropriate focused skill instead.

## CSV parsing

Read the uploaded or pasted CSV. For every row, extract:
- `ProfileType` - "Person" or "Company"
- `LinkedInUrl` - person or company LinkedIn
- `FirstName`, `LastName`, `Title`, `CompanyName`, `Website`
- `AllTimePageViews`, `RecentPageCount`, `NewProfile`, `Tags`
- `WorkEmail` - RB2B-supplied email for Person rows
- `Industry`, `EstimatedEmployeeCount` - for company fit filtering

Report:
```
Total rows: X  (X Person, X Company)
New profiles (first visit): X
Tagged rows: X  (e.g. "Hot page": X)
```

## Step 0 - Define ICP + company fit

Need before triaging:

**1. ICP visitor definition** (which RB2B visitor rows count as a direct target):
> "Which visitor titles/roles are your ICP? For example: 'VP of Marketing', 'Head of RevOps, Director+'.
> I'll use this to classify which visitor rows in your export to enrich directly vs. which companies to prospect into."

**2. Company fit** (optional filter for which companies to pursue at all):
> "Any company filters? For example: industry (SaaS, eCommerce), size (50–500 employees), revenue ($5M+).
> Rows where the company doesn't fit will be skipped entirely."

## Step 1 - Triage rows

Classify each row into one of three buckets:

**Bucket A - ICP Person (enrich directly)**
- `ProfileType = Person` AND `Title` matches ICP definition AND company fits (if filter set)

**Bucket B - Non-ICP Person, company fits (find ICP contacts)**
- `ProfileType = Person` AND `Title` does NOT match ICP AND company fits
- Extract company, deduplicate

**Bucket C - Company row (find ICP contacts)**
- `ProfileType = Company` AND company fits (if filter set)

**Skip - company doesn't fit:**
- Any row where `Industry`, `EstimatedEmployeeCount`, or `EstimateRevenue` fails the company fit filter

Report triage results:
```
Bucket A (direct enrich):        X Person rows
Bucket B (company pivot):        X non-ICP visitors to X unique companies
Bucket C (company rows):         X company rows
Merged B+C companies:            X unique companies
Skipped (company fit miss):      X rows
```

## Step 2 - Prioritise by intent

Before processing, rank everything by intent signals:

For Bucket A (persons): sort by `AllTimePageViews` + weight `NewProfile = true` and any `Tags` entries.

For Buckets B+C (companies): aggregate page views per company across all visitors from that company. Sort by aggregated `AllTimePageViews` desc. Flag `NewProfile = true` companies.

## Step 3 - Credit check

Call `MoltSets:get_billing` and `MoltSets:get_usage` with `period: billing_cycle` in parallel (free).

Estimate:
```
Bucket A: X people × enrich cost per tool       = ~XXX cr
Buckets B+C: X companies × ~3 contacts × enrich = ~XXX cr
Total estimated:                                 = ~XXX cr
Current balance:                                 = XXX cr
```

If estimated cost > balance: stop. Report shortfall, ask whether to process top-N by intent or wait for top-up.

## Step 4 - Ask output preference

Ask how they want the results delivered (table, CSV, Google Sheets, etc.) before processing. If file/integration: get filename/destination now.

## Step 5 - Process Bucket A (ICP visitors - direct enrich)

Collect LinkedIn URLs from Bucket A rows.

Run in parallel:
- `MoltSets:linkedin_to_business_email` - SINGLE `linkedin_url`; fire one call per URL in parallel
- `MoltSets:linkedin_to_personal_email` - SINGLE `linkedin_url`; one call per URL in parallel (if user wants personal too)
- `MoltSets:linkedin_to_mobile_phone` with `linkedin_urls: [array]` (the only batch-array endpoint; if requested)

Preserve `WorkEmail` from original CSV as `RB2B Email` column.

## Step 6 - Process Buckets B+C (company-level - find contacts)

Merge unique companies from Bucket B and Bucket C. Process in intent order.

For each company:
1. `search_people` scoped by `company_domain` (the company's `Website`, preferred) or `company`/`query` (company name), optionally narrowed to your ICP role with `seniority`, `department`/`functional_area`, `country` (use enum values), limit target per company (default 3). Filtering to the ICP role here means fewer non-target results to enrich. Title also returns as a response field for ranking.
2. Tag each result with source (B or C) and total company `AllTimePageViews`

Deduplicate LinkedIn URLs across all results.

Business email is often already on the search records - check first and only enrich the gaps. Credit confirm before enrichment: "Found X ICP contacts. Enriching = ~XXX credits. Proceed?"

Run enrichment in parallel:
- `MoltSets:linkedin_to_business_email` - SINGLE `linkedin_url`; one call per URL in parallel (the email gaps)
- `MoltSets:linkedin_to_mobile_phone` with `linkedin_urls: [array]` (the only batch-array endpoint; if requested)

Fire the per-URL email calls in parallel; chunk the phone array at 100 if needed.

## Step 7 - Merge + rank output

Combine all results into one list. Sort by:
1. Intent score (higher `AllTimePageViews` = higher rank)
2. `NewProfile = true` rows boosted
3. Tagged rows (e.g. "Hot page") boosted

**Output format:**

| Priority | Name | Company | Signal | Source | Title | Business Email | Mobile |
|---|---|---|---|---|---|---|---|

- `Priority` = rank (1 = highest intent)
- `Signal` = `AllTimePageViews` value or aggregated views for company
- `Source` = "ICP visitor" / "Non-ICP visitor's company" / "Company row"

**Summary:**
```
Rows processed:         X  (X Person, X Company)
ICP visitors enriched:  X
Non-ICP companies:      X  to X contacts found
Company rows:           X  to X contacts found
Skipped:                X  (company fit miss)
Total outreach list:    X contacts
Business emails:        X/N (XX%)
Mobile numbers:         X/N (XX%)  - if enriched
Credits used:           ~XXX
```

## Edge cases

- Visitor `Title` is empty to treat as non-ICP (Bucket B); note in output
- Same company appears in Bucket B and Bucket C to merge, don't double-process
- ICP visitor already in company search results to deduplicate; keep the directly-enriched record
- Credits run out mid-processing to stop, output all completed rows, report exact resume point
- Large exports (100+ rows) to set expectation it will take a while, report progress after each bucket
