---
name: moltsets-attio-event-badge-list-enrichment
description: Expand a raw event or badge-scan export of just names and companies into full person records with MoltSets, before it lands in Attio for post-event outreach.
---

# Attio Event and Badge List Enrichment

## Triggers

- "Enrich this event attendee list before I import it into Attio"
- "Expand these badge-scan names and companies into full contacts with email and title"

## What this skill does

Takes a raw event or trade show attendee export, usually just a name and a company, and expands each row into a full person record before it goes anywhere near Attio. It resolves title, business email, LinkedIn, and firmographics through MoltSets, flags rows it cannot resolve, and hands back an import-ready file so post-event outreach starts with real data rather than a name and a booth number.

## Chain

```
Raw attendee export (CSV or sheet: name + company, sometimes title)
  to normalise company name to domain  (best-effort, or ask for domain if ambiguous)
  to MoltSets:
      search_business_profile_by_name  (name + domain -> title, LinkedIn, seniority)
      linkedin_to_best_email           (LinkedIn URL -> business email)
      search_companies                 (domain -> firmographics)
  to flag unresolved rows              (ambiguous company name, no match found)
  to attio/query-records                (check for existing records, avoid duplicate import)
  to attio/create-record                (import new, enriched person records)
```

## Inputs

- **Attendee file** - the raw export (CSV or sheet) with at minimum name and company
- **Event context** - event name and date, to tag the imported records
- **Company resolution** - whether to guess domains from company name automatically or confirm ambiguous ones with you first
- **Import scope** - all resolved rows, or only rows above a confidence threshold
- **Acceptable risk scores** - which A-F deliverability grades to keep (recommended: A, B, C and F; D excluded)

## 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.

## `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`.

## How it works

1. Reads the raw export and identifies what is present per row (name, company, sometimes a title)
2. Normalises the company name to a domain, flagging ambiguous names (common names, multiple possible matches) for confirmation
3. Runs `search_business_profile_by_name` with name plus domain to return title, seniority, and LinkedIn URL
4. Runs `linkedin_to_best_email` where a LinkedIn URL was returned, to get a business email
5. Runs `search_companies` on the domain to attach firmographics to each row
6. Checks resolved records against existing Attio person records to avoid duplicate import, then creates the new, enriched records tagged with the event name and date

Before any write-back, every found address is checked against the accepted grade set. Out-of-range grades are reported in the table with their true score and skipped - never written to the CRM.

## Output

| Name (as scanned) | Company | Resolved Domain | Title | Email | Risk | LinkedIn | Confidence | Action |
| --- | --- | --- | --- | --- | --- | --- | --- | --- |

Show the risk score on every row that has an email, including grades outside the accepted set - flag those in `Action` (e.g. "held - grade D") rather than dropping them silently. Only emails inside the accepted set are written back to the CRM.

```
Rows in export:              X
Rows resolved:                X/N (XX%)
Ambiguous / flagged:          X
Already in Attio:             X
New records imported:         X
MoltSets tokens used:         X

Email risk scores:
  A: X   B: X   C: X   D: X   F: X
  kept (accepted grades):  X
  filtered (excluded):     X
```

## Tips

- Requires the Attio MCP (mcp.attio.com) and the MoltSets MCP connected in the same client
- Badge scans and business card OCR are frequently misspelled, so check flagged rows manually rather than force-matching them
- Tag every imported record with the event name and date so lifecycle and attribution reporting can isolate this cohort later
- Run a coverage check on the first 20 to 50 rows before processing a large export, to catch a systematic domain-guessing problem early
- Add the imported records straight to an event-named Attio list in the same pass, so the cohort is ready for outreach without a second step
