people-sourcer — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited people-sourcer (Agent Skill) and scored it 96/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 1 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 1 flagged
The text {match} tells the agent to skip the normal "ask the user first" gate. Used adversarially it removes the human-in-the-loop check before destructive or sensitive actions, turning a normally-gated agent into a fire-and-forget executor.
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
A real recruiter, BD person, or research lead doesn't open a CRM first. They start with a question: who specifically am I trying to reach, and why? Then they hunt — across whichever platform that tribe actually lives on — and they keep notes. This skill makes Claude work that way, end-to-end, into a spreadsheet the user can act on.
Spam happens when you compile names without context. A list with 200 anonymous LinkedIn URLs is worse than 30 rows where each one has a real signal — this person posted last week about exactly your problem, here's how to enter their world.
So the rule is: never source from zero. Always source from signal. Find the place where the right people are already self-identifying, scrape that signal, then enrich and personalize. The personalization is what makes the difference between a useful list and noise.
Use this skill when the deliverable is a list of named individuals with structured fields. Don't use it for:
If in doubt: if the user wants rows in a spreadsheet with names and an outreach angle, this is the skill.
Six phases. Each writes to a scratchpad so context survives long runs.
1. Intake → pin down WHO and WHY
2. Source strategy → pick platforms + queries
3. Discovery → iterative BrightData scraping
4. Enrichment → per-person profile + contact pull
5. Personalization → worldbuilder commentary per row
6. Output → multi-sheet xlsxSkip phases that are already done. If the user hands you a list of profile URLs and just wants enrichment + commentary, jump to Phase 4.
Before scraping anything, create a scratchpad so you don't lose the thread mid-run.
mkdir -p /home/claude/sourcing-work/<project-slug>/raw
touch /home/claude/sourcing-work/<project-slug>/brief.md
touch /home/claude/sourcing-work/<project-slug>/candidates.jsonlbrief.md — the persona, query plan, and audience model. See references/scratchpad-template.md.candidates.jsonl — one JSON line per candidate, appended as you find them. JSONL because you'll be writing as you scrape, and a corruption in one line doesn't kill the whole file.raw/ — raw scrapes by source URL, named like linkedin-search-1.json, reddit-r-netsec-1.md, etc.Why JSONL for candidates: you'll likely process 30–500 people across multiple rounds. Mid-run failures shouldn't lose progress. Append-only is the right shape.
Pin down the brief in brief.md before doing anything else. The single most expensive mistake in sourcing is scraping the wrong audience well.
Required:
If the brief is vague ("find me ML people"), ask 1–2 sharp questions before scraping. Don't ask a wall — ask the ones that actually change the search:
If the user is decisive ("just find me 50 senior MLEs in Bangalore who post about RAG"), skip the questions and go.
Pick platforms based on where the persona actually lives. See references/source-matrix.md for the full decision table; the short version:
| Persona | Primary platform | Why |
|---|---|---|
| B2B/SaaS buyers, execs, recruiters' candidates | Self-identified work history, public posts | |
| Devs / technical talent | GitHub + Reddit + X (formerly Twitter) + LinkedIn | Code is the signal; posts are the noise |
| Indie hackers / founders | X, IndieHackers forum, ProductHunt, LinkedIn | Where they ship and gripe |
| Security / pentesting | Reddit (r/netsec, r/AskNetsec, r/oscp), X infosec, ctftime, conference speaker pages | Tribe is small, vocal, identifiable |
| Researchers / academics | Google Scholar, arXiv, ResearchGate, university pages, Twitter/X | Citations + author pages |
| Creators / influencers | YouTube, TikTok, Instagram, Twitter/X | Platform IS the work |
| Local community / event attendees | Facebook events, Meetup, local subreddits, Eventbrite | Hyperlocal |
| Journalists / writers | Twitter/X, Muck Rack, bylines on outlet sites | Bylines = identity |
Plan your queries in brief.md before firing them. Write them out as a numbered list so you can reuse and iterate.
These are the BrightData tools you'll lean on — they're deferred, so call tool_search first to load them.
| Goal | Tool |
|---|---|
| Find LinkedIn profiles by query | bd:web_data_linkedin_people_search |
| Pull a single LinkedIn profile (full data) | bd:web_data_linkedin_person_profile |
| Pull LinkedIn posts | bd:web_data_linkedin_posts |
| Reddit post + comments | bd:web_data_reddit_posts |
| X (Twitter) posts | bd:web_data_x_posts |
| Instagram profile / posts / reels | bd:web_data_instagram_profiles / _posts / _reels |
| TikTok profile / posts | bd:web_data_tiktok_profiles / _posts |
| YouTube profile / videos / comments | bd:web_data_youtube_profiles / _videos / _comments |
| Facebook posts / events | bd:web_data_facebook_posts / _events |
| Discovery (which subs, which writers, etc.) | bd:search_engine, bd:search_engine_batch, bd:discover |
| GitHub profiles, personal sites, niche forums, anything else | bd:scrape_as_markdown (or bd:scrape_batch for ≤10 URLs) |
See references/bd-tool-cheatsheet.md for parameter examples.
Sourcing is not "one search and done." It's a loop where each round narrows from where-they-are to who-specifically-they-are.
For each platform you picked, run a discovery query to find the places the persona congregates. Use bd:search_engine_batch to fire several at once.
Example for "senior Rust backend engineers in EU":
"senior rust" engineer site:linkedin.com europerust backend site:github.com followers:>200site:reddit.com/r/rust experience hiringrusty-days OR rustconf speakerDon't scrape candidates yet. Just identify where they cluster — the active subreddits, the LinkedIn groups, the conference speaker pages, the GitHub orgs.
Write findings under "Round 1 — Discovery" in brief.md.
Now actually pull people. Choose the right tool per source:
bd:web_data_linkedin_people_search with structured filters (role, location, current company keywords).bd:web_data_reddit_posts to get post + commenter usernames + their text.bd:scrape_as_markdown on the speaker URL, then for each speaker name, search their LinkedIn / X.bd:scrape_as_markdown on /graphs/contributors.Append each candidate as a JSONL line to candidates.jsonl immediately:
{"name":"…","handle":"…","platform":"linkedin","profile_url":"…","raw_signal":"posted about RAG eval pipelines on Apr 4","source_query":"senior MLE site:linkedin.com bangalore RAG","seen_at":"2026-04-29"}Don't bother with full enrichment yet — just capture name, primary URL, and the one-line signal that landed them on the list. Enrichment is Phase 4.
Look at your candidates file. Are you skewed all-LinkedIn? All one country? All male names (a real bias risk)? All from one company? Run targeted rounds to fill gaps.
Stop when you have roughly 1.5–2× the target N (you'll lose some to dedup, dead profiles, and bad fits in the next phase).
For each candidate in candidates.jsonl, enrich with whatever's publicly available. Don't enrich all 100 in parallel — batch in groups of 10–20 to keep the run debuggable.
For each person, fill the default schema (see references/output-schema.md):
Read references/ethics-and-rails.md before this phase. Short version:
✅ Use emails that the person has publicly published on their own profile, GitHub, personal site, or signature. ✅ Use contact form URLs. ✅ Use platform DM as the channel ("reach out via X DM" is a valid row value). ❌ Don't guess emails ([email protected] patterns are a guess; treat them as unverified at best). ❌ Don't pull from data brokers, leaked dumps, or paid email-finders dressed as "verification." ❌ Don't extract emails from content that's behind a login the person didn't intend you to see.
If you can't find a public contact, that's fine — record Public contact: not found; reach via [LinkedIn/X DM/contact form URL]. The user can handle their own outreach platform.
For each person, after pulling their primary profile, run one quick search to find their other handles. Patterns that work:
"<full name>" site:github.com (devs)"<full name>" site:twitter.com OR site:x.comThis dramatically lifts the quality of the personalization step — you can pull their X bangers in addition to their LinkedIn corporate-speak.
This is the phase that separates a real list from a CSV-with-extra-steps. Read `/mnt/skills/user/worldbuilder-writing/SKILL.md` Phase 0 before this phase. The principle there is the principle here: writing/commenting is applied psychology, not self-expression.
For each person, write three short fields. None of them generic. Each must reference a specific signal from that person's actual scraped data.
The reason they're on the list, anchored in a fact. Not "experienced ML engineer" — that's a description. Try: "Led RAG eval at Phonepe; posted a teardown of LangChain's evaluators on Apr 4 — directly relevant to your eval-tooling pitch."
How to enter THEIR world, not pitch from outside it. Apply worldbuilder Phase 0:
Examples:
Public signals that should change how the user approaches this person:
If there's no risk, leave the field empty. Don't invent risks for symmetry.
Use the xlsx skill: read `/mnt/skills/public/xlsx/SKILL.md` before writing the file. It tells you which library and pattern to use in this environment.
Three sheets in one workbook:
references/output-schema.md plus user's custom fields. Format the header row, freeze it, autosize columns, hyperlink all profile URLs.people-<purpose-slug>-<YYYYMMDD>.xlsx — e.g., people-rust-engineers-eu-20260429.xlsx. Save to /mnt/user-data/outputs/ and present via present_files.
If the user explicitly asked for a Google Sheet AND the Google Drive connector is loaded:
create_file tool to upload it. Drive will let them open as a Sheet.Don't promise Drive integration if the connector isn't connected. Check first.
When you present the file, give them three things in your message:
Don't dump all 47 names into chat. The file IS the deliverable; the chat is the briefing.
[email protected] is not a contact; it's a guess that lands you in spam folders and can violate anti-spam law in some jurisdictions. Leave the field empty if there's no public email.User: "Find me 30 indie hackers who built B2B SaaS in fintech in the last 18 months. I want to interview them for a podcast."
Rough flow:
bd:search_engine_batch for "B2B fintech" launched site:indiehackers.com 2024..2026, ProductHunt fintech launches in date window, X advanced search for "just hit $5k MRR" fintech.bd:scrape_as_markdown), the PH product pages (founder names + handles), the X threads. Append candidates to JSONL.people-fintech-indie-hackers-20260429.xlsx, three sheets, custom column "MRR (public)" added per user request. Hand-off message: 28 delivered (2 dropped — one stealth, one sold the company), here's the audience insight, here's how to start.That's the full flow. Most real runs are messier — the point is the discipline of (a) scraping signal not noise, (b) personalizing per row, (c) being honest about what you couldn't find.
worldbuilder-writing — authoritative on audience modeling and per-person commentary. This skill depends on it.xlsx — authoritative on spreadsheet generation in this environment. Read before Phase 6.pro-graphic-designer — the architectural sibling. Same scratchpad-driven, iterative-scraping shape.Don't reinvent what those skills cover. Read them and dispatch.
~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.