---
name: moltsets-rb2b-companies-to-contacts
description: Use this skill when the user has an RB2B export and wants to find contacts at the companies that visited their website.
---

# RB2B Companies to Contacts

Extract visiting companies from an RB2B export, return ranked contacts at each (with title, seniority, and contact data included), and enrich.

## Triggers

"find contacts at companies who visited my site", "turn my RB2B company list into contacts", "who works at these visiting companies", "prospect into companies from RB2B", or when a user uploads an RB2B CSV and wants contacts at visiting companies.

## CSV parsing

Read the uploaded or pasted CSV. Extract companies from both row types:
- `ProfileType = Company` rows: use `CompanyName` + `Website`
- `ProfileType = Person` rows: use `CompanyName` + `Website` (ignore the individual - they may not be ICP)

Deduplicate by `Website` (domain). Sort companies descending by `AllTimePageViews` - highest intent first.

Report: "Found X unique companies. Top accounts by page views: [top 3 names + view count]."

Highlight any companies where `NewProfile = true` - first-time visitors worth flagging.

## Set Expectations

Before firing any calls, give the user a brief, dry heads-up. Deadpan over enthusiastic - no filler, no corporate speak.

Facts to work with:
- One search call per company, sequential - no batch search API
- N companies × ~3–5 seconds = search phase
- Enrichment adds one batch call after all searches complete
- For 10+ companies, flag it will take a while and report progress

## Step 0 - Note on search scope

`search_people` accepts both company and people filters: `company` (name), `company_domain` (exact), `industry`, `seniority`, `department`/`functional_area`, `country`, `query` (free-text name/role/company), plus `limit`/`offset`. You're scoping to specific companies here, so add `seniority`/`department`/`country` (enum values) only if the user wants a specific role slice. Title also comes back as a response field for ranking.

## Step 1 - Confirm scope

Tell the user: "I have X companies from the RB2B export. How many contacts per company? (Default: 3, max 25 per call)"

## Step 2 - Credit check

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

Estimate:
```
X companies × ~3 results    = ~X prospects
X prospects × linkedin_to_business_email cost = email cost
X prospects × linkedin_to_mobile_phone cost          = phone cost (if requested)
Total:                                   = ~XXX credits
```

## Step 3 - Probe (first company)

Run `search_people` with `limit: 1` for the highest-intent company:
- `company_domain`: the company's `Website` domain if available (most precise), else `company`/`query`: the company name
- optionally `seniority`, `department`/`functional_area`, `country` for a role slice (use enum values)
- title also returns as a response field for ranking

Check result quality before looping all companies.

## Step 4 - Loop all companies

For each company (ordered by `AllTimePageViews` desc):
1. `search_people` scoped by `company_domain` (preferred) or `company`/`query` (company name), optionally narrowed with `seniority`/`department`/`functional_area`/`country`, `limit`: target per company
2. Tag each result with source company and RB2B page view count for traceability
3. Flag zero-result companies - do not stop loop

Report progress periodically for 10+ company lists.

## Step 5 - Deduplicate

Remove duplicate LinkedIn URLs across all companies.

Report: "Found X unique contacts across Y companies."

## Step 6 - Enrich

Business email is often already on the search records - check first and only enrich the gaps. Credit confirm: "Found X contacts. Enriching [email/phone/both] = ~XXX credits. Proceed?"

Run 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 - Output

| Company | Name | Title | Seniority | LinkedIn | Business Email | Mobile | RB2B Visits |
|---|---|---|---|---|---|---|---|

Include `RB2B Visits` (AllTimePageViews) so the user can see which accounts had highest intent.

Summary:
```
Companies processed:  X
Contacts found:       X  (avg X per company)
Zero-result accounts: X
Business emails:      X/N (XX%)
Mobile numbers:       X/N (XX%)  - if enriched
Credits used:         ~XXX
```

List zero-result companies separately.

## Edge cases

- Company name ambiguous to note in output, results may include false matches
- Large list (20+ companies) to set expectation it will take time
- Credits run out mid-loop to stop, output completed rows, report exact resume point
- `Website` domain preferred over company name for search scoping - pass it as the `company_domain` param (more precise than `company`/`query`)
