moonlight-lupin/agent-skills

people-enrichment

Enrich and search People Data Labs (PDL) Person and Company data, writing results to .xlsx.

Vedi sorgente
Documento Skill originale

Contenuto dal repository con titoli, esempi, codice, tabelle, link e immagini preservati.

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.

SubcommandInputOutputBilling
person-enrichlist of named peopleprofile + work history1 credit / match
person-identifylist of people (ambiguous)several scored candidates eachper PDL identify terms
person-searchcriteria flagsa list of matching people1 credit / record returned
company-enrichlist of companiesfirmographics1 credit / match
company-searchcriteria flagsa list of matching companies1 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.
dallo stesso repository

Altri Skills

Tutti gli Skills
moonlight-lupin
Community

claude-plugin-converter

Convert Claude Code plugins into self-contained Hermes plugins — discovery analysis then full conversion

installazioni
1
GitHub Stars
62
Aggiornato
7 set
moonlight-lupin
Community

clips-studio

Use when the user wants to "make a video/clip", "generate a video from text", "animate this image/photo", "create a marketing reel / social video / teaser", "do a 3D / parallax move", "pan/zoom/orbit a shot", or mentions fal.ai, Kling, Veo or Seedance for video. Staged fal.ai workflow — brainstorm, draft cheaply, produce the final at quality. Three modes: text-to-video, animate (still to motion), camera-move (push-in/pan/orbit). Not for still images (image-studio), slide decks, or charts. Honesty discipline: never depict real identifiable subjects via text-to-video.

installazioni
1
GitHub Stars
62
Aggiornato
7 set
moonlight-lupin
Community

decision-log

ADR-style decision journal for agents and teams. Create numbered decision records, track superseding chains, schedule periodic reviews, and search past decisions to avoid re-litigating settled questions.

installazioni
1
GitHub Stars
62
Aggiornato
7 set
moonlight-lupin
Community

deep-research

Autonomous multi-step deep research engine implementing an iterative Think → Search → Extract → Synthesize → Stop loop. The LLM drives every decision: what to search, what's relevant, what's missing, and when to stop. Produces a cited, magazine-quality report with inline citations, category- specific formatting, and research stats. Trigger when the user asks for "deep research", "research report on", "comprehensive analysis of", "look into X in depth", "write a report on X", or any question needing multi-source synthesis beyond a single search. For entity vetting/dossiers use entity-research; for news digests use news-monitoring; for source-grounded Q&A use notebooklm-mode.

installazioni
1
GitHub Stars
62
Aggiornato
7 set