---
name: moltsets-company-employee-scout
description: Use this skill when the user wants to find people who work at a specific company. Scope the search by company name or exact domain.
---

# Company Employee Scout

Find employees at a target company - scoped by company name or exact domain. Returns ranked contacts with title, seniority, department, and contact data included.

## Triggers

"find people at Stripe", "show me contacts at HubSpot", "show me the team at [Company]", "find contacts at [Company]", "who works at [Company]". Chains company lookup + people search, with optional contact enrichment.

## Chain

```
company name/domain
  to search_companies   (resolve name to domain + firmographics)
  to search_people  (find people, scoped by company_domain or company name)
  to linkedin_to_business_email     (optional - per-URL parallel calls to fill missing business emails)
```

## 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:
- Search only: 2–3 calls (company lookup + people search), ~10–15 seconds
- With enrichment: search + batch email enrichment for N people, ~20–40 seconds total

## Risk scores - confirm before enriching

Every email MoltSets returns carries a deliverability risk score - a grade from A to F. Ask which grades to keep before running anything:

> "MoltSets grades email deliverability risk from A (best) to F (no data). Which grades should I keep? I'd recommend **A, B, C and F** - and dropping **D**, since D is a confirmed bounce, complaint or spam trap."

| Grade | Meaning | Best practice |
| --- | --- | --- |
| A | Strongest engagement signal available | Safe to send immediately |
| B | Solid | Fine in regular sends; on a new or warming domain, send a smaller batch before scaling |
| C | Deliverability can't be confirmed | Segment separately from A/B, warm at low volume, watch engagement, suppress non-responders after 1-2 attempts |
| D | Confirmed bounce, complaint or spam trap | Never send - fastest way to trip spam traps and damage sender reputation for the whole list |
| F | No data - unknown risk, not "safe" | Re-verify before sending, or treat like C |

Use whatever set the user confirms. Treat the grade as a filter, not a guarantee - it lowers risk, it doesn't remove it. Pair it with the user's own sending domain reputation and list hygiene.

## Step 0 - Input Quality Gate

### Company is required - hard stop
If no company name or domain is provided, **stop and ask before running**:

> "Which company do you want to search? I need a company name or domain to scope the results."

Do not attempt a search without a company - results will be meaningless.

For large companies (recognisable enterprises), expect a broad employee mix; paginate with `offset` to pull more pages.

## `search_people` filters and best practice

Full request parameter set:

| Purpose | Param | Notes |
|---|---|---|
| Free text | `query` | Searches `full_name`, `first_name`, `last_name`, company name, `title` (~85% filled), `headline` (~65% filled). Names and role keywords only |
| Company name | `company` | Analysed match - every word you pass must appear in the stored name |
| Company domain | `company_domain` | Exact; full URLs are normalised automatically |
| Country | `country` | ~99% filled - the most reliable filter available |
| State / region | `state` | The person's location. Full names - "Texas", not "TX" |
| City | `city` | The exact stored city, **not** its suburbs. Pair with `state`/`country` to disambiguate repeated names |
| Seniority | `seniority` | ~60% filled. Intern, Entry, Senior, Manager, Director, VP, Head, C Suite, Owner, Partner |
| Department | `department` | ~60% filled. Shares its data with `functional_area` - use one |
| Functional area | `functional_area` | Same underlying data as `department` - never send both |
| Industry (broad) | `industry` | ~60% filled. 21 broad buckets |
| Industry (niche) | `linkedin_industry` | ~50% filled. LinkedIn's own ~150 labels - "Staffing and Recruiting", "Wellness and Fitness Services" |
| Industry (code) | `naics_code` | ~50% filled. Any hierarchy level - "54" is broad, "541120" is surgical |
| Employer size | `employee_range` | Filters the person's **current employer** - no company lookup needed first |
| Employer revenue | `revenue_range` | Same - applied to the person's current employer |
| Paging | `limit` / `offset` | 10 default, 25 max (5 on the Free plan) |

**Filters are free precision.** Execution cost is driven by the free-text `query`, not by the filters attached to it.

| Query shape | Relative cost to execute |
|---|---|
| `query` alone | baseline |
| `query` + any number of filters | the same - filters add nothing |
| filters only, no `query` | **~40x cheaper** |

- **Never send a bare `query`.** Attaching `country` costs nothing and removes every other market. A query-only call is the least precise shape available and no cheaper than a filtered one.
- **Drop `query` entirely when filters carry the whole intent.** "VPs of sales at US software companies" is fully expressible as `seniority` + `department` + `industry` + `country`, and runs ~40x cheaper as a pure filter search.
- Billing doesn't change either way - tokens are charged per record returned. This is about speed and search load.
- If all you have is free text, add `country`: highest fill rate of any filter, so it discards almost no legitimate match.

**Don't over-stack sparse filters.** Every non-`query` filter is an exact match and silently discards records where that field is empty. Three ~60%-filled filters can cut a viable audience to nothing. When a search comes back thin, drop the sparsest filter first (`naics_code`, `linkedin_industry`) or shorten the NAICS code - not `country`.

**Exact strings matter.** `"C Suite"` has a space, not a hyphen. `"Marketing & Advertising"` and `"Medical & Health"` use ampersands. `"5001+"` and `"$500k - $1M"` must match character for character. `"UK"` and `"HK"` exist as dirty values - prefer `"United Kingdom"` and `"Hong Kong"`.

**Target by company size without naming a company.** `employee_range` and `revenue_range` apply to the person's current employer, so a `search_companies` pass first is usually unnecessary:

```json
{ "seniority": "VP", "employee_range": "51-200", "country": "United States" }
```

Prefer the numeric bands over the legacy `"Small"` / `"Mid-Market"` / `"Enterprise"` / `"Unknown"` values, which carry far thinner coverage.

**Size the search before you walk it.** `search_linkedin_profile` accepts `count_only: true`, which returns the match count without fetching data or charging tokens. Every search response also carries `results.total` - read it before paginating, then increment `offset` by `limit`. Results are `_score`-ranked, so the first page is the best page.

**Emails come back in the search.** Records already include `business_email` and `business_email_risk_score` - for those rows, no follow-up enrichment call is needed.

## `search_companies` filter notes

- **Use `domain` when you have one.** Exact match, always beats a free-text `query`, and full URLs are normalised automatically ("https://www.acme.com/about" → "acme.com") - no need to strip the protocol or path first. `query` searches the company **name only**.
- **Filters are free precision.** Execution cost comes from `query`, not the filters attached to it - a filters-only call runs **~40x cheaper**, and most firmographic lookups need no free text at all. Billing is unchanged: tokens are charged per record returned.
- **Full filter set:** `query`, `domain`, `industry`, `linkedin_industry`, `naics_code`, `employee_range`, `revenue_range`, `country`, `state`, plus `limit`/`offset`.
- **Industry vocabularies overlap.** `industry` carries broad buckets *and* long-tail values (`"Computer Software"`, `"Insurance"`, `"Banks"`, `"Aerospace and Defense"`), so the same company may be filed under either - if a lookup comes back thin, try the neighbouring value. `linkedin_industry` (~150 niche labels) and `naics_code` (any hierarchy level) cover finer granularity.
- **Location is derived from where the team is based.** Accurate for small companies, but **large multinationals resolve to a single one of their offices** - don't lean on `country`/`state` alone for enterprise or international targeting.
- **Range values are exact and skewed.** `"1-10"` dominates `employee_range`; `"$500k - $1M"` dominates `revenue_range`. Prefer numeric bands over legacy `"Small"`/`"Mid-Market"`/`"Enterprise"`/`"Unknown"`, and always use `"$500k - $1M"` over the legacy `"$1 - $1M"` (same range, far fewer records).
- **Read `results.total` before paginating.** Results are `_score`-ranked; 25 max per call, increment `offset` by `limit`.

## Step 1 - Resolve company

**Known domain** (e.g. `stripe.com`): skip to Step 2.

**Company name only**: call `MoltSets:search_companies` with `query: "[name]"` - `query` searches the company **name** only, which is exactly the job here. Narrow with `country`/`state` or `industry` if the name is generic and comes back with collisions. Confirm the correct match with the user before proceeding.

**A URL, not a bare domain**: pass it straight to `domain` - full URLs are normalised automatically (`https://www.acme.com/about` → `acme.com`), so there's no need to strip the protocol or path first.

## Step 2 - Search employees

Call `search_people` scoped to the company:
- `company_domain`: the exact company domain (e.g. `"stripe.com"`) - the most precise scope; use this whenever you have it
- `company`: the company name (e.g. `"Stripe"`, `"HubSpot"`) - use when you only have a name
- `limit`: default 10, max 25 per page
- `offset`: 0, 25, 50, … to paginate across a large employee base

You can also narrow within the company using people filters: `seniority` (Intern, Entry, Senior, Manager, Director, VP, Head, C Suite, Owner, Partner), `department` or `functional_area` (Operations, Sales, Information Technology, Education, Engineering, Finance, Medical & Health, Marketing, Human Resources, Design, Consulting, Legal - use one), and `country`/`state`/`city` for a specific office. Add these when the user wants a specific slice (e.g. "VPs at Stripe", "sales team at HubSpot", "the Dublin office"). Filters cost nothing on top of the call, so narrow server-side rather than pulling a full roster and filtering it yourself. `query` can also free-text a person's name or role - but don't send it bare when a `company_domain` scope is available.

Read `results.total` on the first response: it's the count across all pages and tells you how big the employee base actually is before you start paginating.

## Step 3 - Present results

Each record returns `full_name`, `title`, `seniority`, `country`, `headline`, `linkedin_url`, `business_email`, company data, and `_score`. Present:

| Name | Title | Seniority | LinkedIn | Business email | Risk |
|---|---|---|---|---|---|

Show the risk score on every row that has an email, including grades outside the accepted set - flag those rather than dropping them silently, so the user can see what was filtered and why.

Close with the risk-score spread: "Risk scores: A X, B X, C X, D X, F X - X kept, X outside your accepted set."

Default 10 per page. For large companies, paginate with `offset` to gather more records. Ask if user wants more pages or wants to enrich with contact data.

## Step 4 - Optional enrichment

`business_email` is often already present in the results, with its own risk score - call both out. If user wants the gaps filled or phone numbers: collect LinkedIn URLs for the rows that need it and call `linkedin_to_business_email` once per URL (single `linkedin_url` each), fired in parallel. Phone uses `linkedin_to_mobile_phone` with a `linkedin_urls` array.

Always do a credit check first: "Found X people, Y missing a business email. Enriching = Y × [cost] = ~XXX credits. Proceed?"

## Edge cases

- Company name in `company`/`query` is a soft signal - results may include people with that company mentioned in their headline/title, not just employees. Prefer `company_domain` for precision
- Seniority, department, and country are accepted as request filters - use them to narrow to a role slice within the company. Title also returns as a response field for ranking
- For large companies, paginate with `offset` to pull more pages
