# People Enrichment

> >

- **Type:** Skill
- **Install:** `agentstack add skill-moonlight-lupin-agent-skills-people-enrichment`
- **Verified:** Yes — security-reviewed for prompt injection and unsafe behavior
- **Seller:** [moonlight-lupin](https://agentstack.voostack.com/s/moonlight-lupin)
- **Installs:** 0
- **Category:** [AI & ML](https://agentstack.voostack.com/c/ai-and-ml)
- **Latest version:** 0.1.0
- **License:** MIT
- **Upstream author:** [moonlight-lupin](https://github.com/moonlight-lupin)
- **Source:** https://github.com/moonlight-lupin/agent-skills/tree/main/research/people-enrichment
- **Website:** https://hermes-agent.nousresearch.com

## Install

```sh
agentstack add skill-moonlight-lupin-agent-skills-people-enrichment
```

Requires the [AgentStack CLI](https://agentstack.voostack.com/docs/cli). Works with Claude Code, Cursor, and any MCP-compatible agent.

## About

# People Enrichment & Search (People Data Labs)

One script, `scripts/enrich.py`, with five subcommands over PDL's Person and Company datasets. All share the same API-key handling, the boolean-PII contact logic, status flags, `.xlsx` styling, and a `--dry-run` preflight mode.

| Subcommand | Input | Output | Billing |
| --- | --- | --- | --- |
| `person-enrich` | list of named people | profile + work history | 1 credit / match |
| `person-identify` | list of people (ambiguous) | several scored candidates each | per PDL identify terms |
| `person-search` | criteria flags | a list of matching people | 1 credit / record returned |
| `company-enrich` | list of companies | firmographics | 1 credit / match |
| `company-search` | criteria flags | a list of matching companies | 1 credit / record returned |

The two *search* commands return data per *result*, so cost scales with `--size`. Always state the rough cost before a large search and keep `--size` modest unless the user asks for more (max 100 per request).

## Scope and routing

Use this skill when the user wants PDL person/company enrichment or search for a legitimate, proportionate purpose. Do **not** use it to scrape LinkedIn directly, to compile an intrusive profile, or where a host environment mandates a different data provider.

## Why People Data Labs, not a LinkedIn scraper

Scraping LinkedIn is fragile and legally risky. This skill uses PDL as a licensed aggregator rather than live LinkedIn scraping. If the user insists on live scraping, explain the trade-off rather than building a scraper.

## The API key

`scripts/enrich.py` needs a PDL key, resolved at runtime in this order: `PDL_API_KEY` env var → `.env` in the cwd → `.env` next to the script. **The key must never be written into this skill or any script.** If absent, live commands exit with instructions. `--dry-run` and `--self-test` do not require a key.

Create the `.env` only locally:

```bash
echo 'PDL_API_KEY=their_key_here' > .env
```

Treat `.env` as a secret: don't print, commit, or upload it. `--self-test` runs offline (canned data, no key) and writes sample people + company sheets so the user can see the output format before spending credits.

## Dry-run preflight

Before spending credits, especially on larger files or searches, run the same command with `--dry-run`:

```bash
python scripts/enrich.py person-enrich --input people.csv --output out.xlsx --dry-run
python scripts/enrich.py person-search --company "Northwind Capital" --title director --size 25 --dry-run
python scripts/enrich.py company-search --industry "real estate" --country singapore --size 50 --dry-run
```

Dry-run validates the input/search, prints the planned output, and estimates maximum credits without requiring `PDL_API_KEY`, calling PDL, or writing `.xlsx` output.

## Contact fields and the free plan

On the free plan, PDL returns PII fields (`emails`, `phone_numbers`) as a boolean, not the value: `true` = a contact exists but is paywalled, `false` = none on file. The people sheets surface this in **Email status** / **Phone status** columns: `included` (real value present, Pro plans), `exists - upgrade to view` (paywalled but present), `none on file`, or `unknown`.

## The five commands

**person-enrich** — one-to-one match named people.

```bash
python scripts/enrich.py person-enrich --input people.csv --output out.xlsx
```

Recognised input columns (case/space-insensitive): name/full name, first name, last name, company/employer, title, location, email, linkedin/profile. More context per row = higher match rate.

**person-identify** — when a single enrich is ambiguous, get the candidate set.

```bash
python scripts/enrich.py person-identify --input people.csv --max-candidates 5
```

Same input as enrich. Output has multiple rows per input person, each a scored candidate (Match score column), so the user can pick the right one.

**person-search** — find people by criteria, no name list needed.

```bash
python scripts/enrich.py person-search --company "Northwind Capital" --title director --size 25
```

Flags: `--company --title --location --country --industry --name`, plus `--size` (1–100), `--dataset` (default all), and `--sql` to pass a raw PDL SQL query for full control. Flags are combined with AND.

**company-enrich** — match a list of companies to firmographics.

```bash
python scripts/enrich.py company-enrich --input companies.csv --output firms.xlsx
```

Recognised input columns: name/company, website/domain, ticker, linkedin/profile, location/country/region/locality. Needs at least one of name/website/ticker/profile per row.

**company-search** — find companies by criteria.

```bash
python scripts/enrich.py company-search --industry "real estate" --country singapore --min-employees 50 --size 50
```

Flags: `--name --industry --country --locality --tag --min-employees`, plus `--size` and `--sql`.

## Reviewing output with the user

People sheets have two tabs: **People** (one row per person, status colour-coded) and **Employment history** (one row per past role). Company sheets have a single **Companies** tab. The **Status** column is the first thing to check: `matched` (green), `needs_review` (amber), `no_match` (red), `error` (orange). Call out the amber/red rows explicitly so the user knows what to double-check.

## Tuning matches

`--min-likelihood N` (1–10) is the confidence floor for the enrich/identify commands. Raise it (6–8) when names/companies are common and you'd rather miss than mis-match; lower it when you have rich context and want coverage. Company enrichment is most reliable with a website/domain; person enrichment with a company or email alongside the name.

## Swapping providers later

The PDL-specific pieces are the `*_params` builders, `pdl_request`, and the `parse_person` / `parse_company` mappers. To support another provider, implement those against its API and keep the same record dict shape; input parsing, status logic, SQL/flag handling, dry-run summaries, and `.xlsx` writing stay as is.

## Principles

- **Drafts, not advice** — output is a research aid for a person to review, not a determination.
- **Never invent** — surface only what PDL returns; mark `no_match`/`needs_review` honestly rather than guessing an identity.
- **Deterministic where it counts** — input parsing, status logic, dry-run estimates and `.xlsx` writing are deterministic.
- **Honesty and calibration** — flag low-confidence matches and show the rough credit cost up front.
- **Workspace hygiene** — write outputs where the user expects; never write the API key to disk in the skill.

## Data handling

**PDL is a third party and enrichment sends the real name/company to it** — it cannot be tokenised, because the name *is* the lookup. Treat the `.env` / `PDL_API_KEY` as a secret: never print, commit or upload it. For people, confirm a legitimate and proportionate purpose and collect only fields relevant to that purpose.

## Pitfalls

1. **Free plan hides contact values** — emails/phones come back as booleans; read the status columns.
2. **Search cost scales with `--size`** — quote the rough credit cost and keep `--size` modest.
3. **Common names mis-match** — raise `--min-likelihood` or add context columns (company/email).
4. **Never commit `.env`** — the key is a secret; `--self-test` and `--dry-run` need no key.
5. **Dry-run is an estimate** — actual billing follows PDL's endpoint terms and returned records/matches.

## Verification checklist

- [ ] Legitimate, proportionate purpose confirmed for any person enrichment/search.
- [ ] `--dry-run` used for large files or searches to validate scope and estimate credits.
- [ ] `PDL_API_KEY` available via env or `.env` for live runs (never written into the skill).
- [ ] Rough credit cost stated before any large search.
- [ ] Amber/red status rows flagged to the user.
- [ ] `.env` not printed/committed.

## Requirements

- Python 3.8+
- `pip install openpyxl` (HTTP uses the stdlib `urllib` — no `requests` needed)
- `PDL_API_KEY` (env var or `.env`) for live API calls; get one at https://www.peopledatalabs.com
- Network access to the PDL API. `--self-test` and `--dry-run` run fully offline.

## Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

- **Author:** [moonlight-lupin](https://github.com/moonlight-lupin)
- **Source:** [moonlight-lupin/agent-skills](https://github.com/moonlight-lupin/agent-skills)
- **License:** MIT
- **Homepage:** https://hermes-agent.nousresearch.com

Install and usage instructions live in the source repository linked above.

## Pricing

- **Free** — Free

## Security capabilities

Automated source analysis of v0.1.0 — what this tool can access:

- **Network access:** yes
- **Filesystem access:** no
- **Shell / process execution:** no
- **Environment & secrets:** yes
- **Dynamic code execution:** no

*"Yes" means the capability is present in the source — more access means more to trust, not that it is unsafe.*


## Versions

- **0.1.0** — security scan: passed — Imported from the upstream source.

## Links

- Listing page: https://agentstack.voostack.com/l/skill-moonlight-lupin-agent-skills-people-enrichment
- Seller: https://agentstack.voostack.com/s/moonlight-lupin
- Browse the marketplace: https://agentstack.voostack.com/browse

---
Listed on AgentStack — the marketplace for AI agent skills and MCP servers. Every listing is security-reviewed. Creators keep 70%.
