---
name: moltsets-accounts-to-contacts
description: Use this skill when the user has a list of target companies and wants to find contacts at those companies.
---

# Accounts to Contacts

Given a list of companies, return ranked contacts at each one - with title, seniority, department, and contact data included - and optionally enrich.

## Triggers

"find contacts at these companies", "I have a list of accounts, find me contacts", "turn this company list into a contact list", "prospect into these accounts", "who works at these companies". Input is a list of companies; output is a unified people list ready for enrichment or outreach.

## Chain

```
company list
  to search_people  (per company, looped)
  to deduplicate
  to linkedin_to_business_email     (optional)
  to linkedin_to_mobile_phone              (optional)
```

## 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 × ~2–4 seconds = search phase estimate
- Enrichment (if requested) adds one batch call after all searches complete
- For 10+ companies, flag that this takes a while and you'll report progress

## Step 0 - Input Quality Gate

**Company list** - at least 1 company with a name (domain optional but helps precision). If missing, stop:
> "Paste or upload your company list. I need at least company names - domains help precision."

### Notes
- `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 already scoping to specific companies, so industry is usually unnecessary - but you CAN add `seniority`/`department`/`country` to pull only a role slice at each account (use enum values)

## Step 1 - Parse company list

Accept:
- Line-separated paste (name only, or name + domain)
- CSV (extract company name and domain columns)
- Typed list

Normalise into rows: `Company Name | Domain (if provided)`

Flag any rows with unresolvable names (very ambiguous, no domain). Report: "Parsed X companies."

## Step 2 - Confirm target count

Confirm with user before running:

> "I'll pull contacts at each of X companies. How many contacts per company? (Default: 3, max 25 per call)"

Default to 3 per company unless specified. Wait for confirmation.

## Step 3 - Credit check (required)

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

Estimate (conservative - actual results vary):
```
X companies × ~3 results      = ~X prospects
X prospects × linkedin_to_business_email = email cost  (if requested)
X prospects × linkedin_to_mobile_phone    = phone cost  (if requested)
Total:                         = ~XXX credits
Current balance:               = XXX credits
```

If estimated cost > balance: stop. Report shortfall, how many companies the balance covers, ask to proceed partially or top up.

## Step 4 - Probe (first company)

Before looping all companies, run `search_people` with `limit: 1` for the first company:

- `company_domain`: the company's domain if known (most precise), or `company`/`query`: the company name as free text
- Optionally narrow with `seniority`, `department`/`functional_area`, `country` to target a role slice (use enum values)
- Title also comes back as a response field (`title`, `seniority`, `department`, `country`, etc.) for ranking

Check result quality:
- Good match to proceed with full loop
- Poor match (wrong company) to adjust `company_domain`/`company`/`query` before scaling

## Step 5 - Loop all companies

For each company:
1. Run `search_people`:
   - `company_domain` (if known) or `company`/`query`: the company name
   - optionally `seniority`, `department`/`functional_area`, `country` for a role slice
   - `limit`: target per company (default 10, max 25)
2. If results < target and user wants more: paginate with `offset`
3. Tag each result with source company for traceability

Process sequentially - one search call per company, no batch search API. Do not pause per company - flag any zero-result companies in final output.

**Note:** `company_domain` is the most precise scope; `company`/`query` (company name) is a softer signal and results may include people who only mention the company in their headline.

## Step 6 - Deduplicate

Remove duplicate LinkedIn URLs across all companies. If a person appears at multiple companies (e.g. consulting multiple clients), keep the entry with the stronger company match and note the duplicate.

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

## Step 7 - Optional enrichment

Business email is often already present on the search records - check first and only enrich the gaps. If user wants emails (for the gaps) or phones: collect the LinkedIn URLs that still need data to run enrichment in batch.

Credit confirm first: "Found X contacts. Enriching [email/phone/both] = ~XXX credits. Proceed?"

- `linkedin_to_business_email` - SINGLE `linkedin_url` per call; fire one per URL in parallel (no email batch array)
- `linkedin_to_mobile_phone` - `linkedin_urls` array (batch, max 100)

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

## Step 8 - Output

| Company | Name | Title | Seniority | Department | Country | LinkedIn | Business Email | Mobile |
|---|---|---|---|---|---|---|---|---|

Omit email/mobile columns if enrichment not requested.

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

List zero-result companies separately so user can investigate.

Offer to export as CSV-style table.

## Edge cases

- Zero results for a company to mark "No results" in summary, do not stop loop
- Company name ambiguous (e.g. "Apple" could be many things) to note in output, results may include false matches
- Large list (20+ companies) to set expectation it will take time; report progress periodically
- Credits run out mid-loop to stop, output completed rows, report exact resume point (which company index)
- Max 25 results per `search_people` call - loop with `offset` if user wants more per company
