Source people in bulk from Anysite's LinkedIn profile database (search_sql_users) with ~60 filters - derived seniority/function, company domain/id incl. past employers (alumni), career-shape (new in role, tenure, promotions), education, skills, deterministic territory buckets. Use when the user wants to find people in bulk - persona lists, buyers/candidates by role and company traits, competitor alumni, "new VP hires", recruiting searches - "найди людей", "собери список персон", "кто недавно сменил работу". For company lists first use anysite-company-sourcing; for one known person use linkedin/user; for CRM push use anysite-crm-prospect.
Installer avec Codex ou Claude Copiez ce prompt, collez-le dans Codex, Claude ou un autre assistant, puis laissez-le vérifier la page du skill et l'installer pour vous.
Une commande directe contourne le prompt de vérification. Examinez la source avant de l'exécuter.
La commande reste sur une seule ligne. Faites défiler horizontalement pour la vérifier avant de la copier.
Vous préférez une copie locale ? Téléchargez les fichiers actuellement disponibles dans SkillsMP.
Affichage de SKILL.md
SKILL.md
Instructions source · Aperçu en lecture seule
name
anysite-people-sourcing
description
Source people in bulk from Anysite's LinkedIn profile database (search_sql_users) with ~60 filters - derived seniority/function, company domain/id incl. past employers (alumni), career-shape (new in role, tenure, promotions), education, skills, deterministic territory buckets. Use when the user wants to find people in bulk - persona lists, buyers/candidates by role and company traits, competitor alumni, "new VP hires", recruiting searches - "найди людей", "собери список персон", "кто недавно сменил работу". For company lists first use anysite-company-sourcing; for one known person use linkedin/user; for CRM push use anysite-crm-prospect.
People Sourcing
linkedin/search/sql/users (endpoint search_sql_users) searches a very large
profile database with filters no live LinkedIn search has: derived seniority and
function, career-shape maths (tenure, promotions, months in role), past-employer
alumni, company domains and deterministic bucketing. It is the bulk people
workhorse; live search_users stays the tool for one-off lookups and namesake
disambiguation.
Verified live: filters compose correctly (seniority_min=head + function=sales +
US + 51–500 headcount + new-in-role returned exactly that, role histories fresh
to the current quarter; alumni via past_company_id returns people whose role at
that company has an end date, never current staff).
Two semantics that change how you work
An over-count result is an unbiased SAMPLE, and repeating the request
returns the SAME people (verified: two identical calls → identical 5
aliases; and raising count only appends — the list is prefix-stable, not
reshuffled). Calling again is not pagination.
Buckets are disjoint and stable (verified: bucket_total:2, index 0 vs 1
→ zero overlap across 40). Walk them for volume: bucket_total:N, bucket_index:0..N-1, also the built-in territory splitter. Ceiling:bucket_total max is 100, so the reachable population is ~100×1000 = 100k;
size bucket_total so each bucket is < 1000, otherwise a bucket is itself a
sample and you silently lose the tail.
What filters but does NOT come back (read before you "validate")
The derived fields you filter on are not in the response: no seniority,
function, profile_score, months_in_role, promotion_count, industry,
employee_count (verified on a live record). Consequences:
"Validate against intent" = read experience[] by hand: take roles with
end_date == null (the current ones) and check .position / .company.name.
You cannot re-sort or re-segment the result by seniority/function via
query_cache — those columns aren't there.
The only size field carried per role is experience[].company.employee_range,
and that string is unreliable (see Company filters). There is no trustworthy
company-size value in a people result to write to a CRM.
Filter map (grouped; full contract via discover(linkedin, search))
Text DSL (whitespace=AND, |=OR no spaces around it, "phrase", -not):
name, headline, summary, current_title, any_title (past roles
included), skills, languages, location, keywords, edu_*.
IRON RULE — quote every multi-word alternative in an OR chain. Whitespace
binds tighter than |, so an unquoted phrase SHATTERS the chain into
impossible AND groups: current_company_name: "Tencent|Tencent Games|Level Infinite|Proxima Beta" parses as (Tencent|Tencent) AND (Games|Level) AND (Infinite|Proxima) AND Beta → 0 results on Tencent-scale companies
(verified live — this exact failure burned a real user session). Correct:
"Tencent"|"Tencent Games"|"Level Infinite"|"Proxima Beta"|Krafton.
Lint before EVERY send: any token containing a space inside an OR chain
without quotes → do not send, fix first.
Derived seniority/function — start here for recall.seniority /
seniority_min (entry→ic→senior_ic→manager→head→vp→founder→cxo), function /
any_function (sales, marketing, engineering, product, data, finance, hr, ops,
legal, support, exec, …). Catch titles a text search can't (CRO, CCO, "VP
Business Development" all matched a function:sales+seniority_min:vp query —
none would survive a "vp of sales" DSL). Two traps, both measured:
seniority_min:"head" includes founder → pulls solo owners of 2-person
shops. For enterprise buyers list the levels explicitly:
seniority:["head","vp","cxo"], and always add employee_count_min.
Token false-positives: "CEO Office" (staff, not the CEO) scored ≥head;
"…President's Club 2020…" (an award on a rank-and-file AE) scored ≥vp.
Precision on a vp+sales slice was 9/10 — good, not perfect; verify the
shortlist against .
Coverage honesty
Not every profile states a current employer, industry, company size or dated
roles — those filters answer only for people who do. Set the matching has_*
flag deliberately and tell the user the trade-off ("filtering by company size
skips people whose company doesn't state one"). open_to_work: false = "no badge
observed", not "not looking". Follower/connection counts exist on a small share —
gate with has_engagement.
Two data-shape facts to expect: some profiles carry multiple concurrent open
roles (measured: 4/10 in one slice; one person had ~19 — advisory boards,
visiting posts). "Current company" is then ambiguous, and a
current_company_domain/employee_count filter may match on a quarter-time
advisory role, not the day job — so verify the target company is an operational
current role before anchoring an opener on it. And urn is occasionally null
even when alias is present — the vanity URL still enables user_find_email_by_url,
but URN-keyed handoffs (user/posts) need the live linkedin/user step first.
The loop
Start from the most selective structural filters (seniority/function/
company/country) — never bare keywords (it only helps for distinctive words
and must ride a selective filter).
Probe count:10, validate against INTENT via experience[] (structural
filters aren't semantic: "Director of Sales, 51–200, US" returned a coffee
wholesaler). Precision comes from current_company_domain[] (a list from
anysite-company-sourcing), taxonomy industry[], or headline/skills DSL.
Tighten/widen, re-probe, fetch; >1000 → size bucket_total so each bucket
< 1000 and walk it.
Free re-cuts with query_cache (only on returned fields); export with
export_data.
Zero results — debug in this order, don't flail:
Re-read your own DSL for unquoted multi-word phrases in OR chains (the #1
cause by far — see the IRON RULE).
Loosen ONE filter per step (drop profile_score_min, widen seniority,
drop industry) — never jump straight to a bare keywords full-text.
Sanity check: 0 results for a Tencent-scale employer is almost certainly a
query bug, not missing data — go back to step 1, don't report "not found".
500/408 on a broad query: don't retry as-is — narrow it (add a selective
filter) or raise timeout (≤1500). An unselective query is a scan; retrying a
scan just times out again.
Recipes
"VPs of Sales at US SaaS 50–500": seniority:["vp","cxo"], function:["sales"], country:["US"], employee_count_min:50, employee_count_max:500, industry:["Software Development"]. (SaaS ≠ a taxonomy label — narrow via the
company-side list or headline DSL. profile_score_min only if asked.)
"BD/partnerships across a brand family" (verified live, 99 profiles):
current_company_name: "\"Tencent\"|\"Tencent Games\"|\"Level Infinite\"| \"Proxima Beta\"|Krafton", current_title: "\"business development\"|bizdev| partnership|partnerships|licensing|monetization|payments|commercial", seniority:["manager","head","vp","cxo"], has_current_role:true — every
multi-word alternative quoted; regional focus goes in headline, not
country (see Geo).
"New decision-makers" (best-converting timing): add months_in_role_max:6.
"Grew up inside the company" (internal champion / stable ABM contact):
promotion_count_min:2 + avg_tenure_months_min:24.
"Competitor alumni": past_company_id:[<ids>] (+ function/seniority) — people
who LEFT. Note: this is ex-employees, NOT the competitor's customers; for
customers use anysite-crm-competitor-intel (wappalyzer + reviews).
School alumni warm-intro: edu_slug:[...] + edu_ended_year_min/max.
Recruiting: skills/edu_field DSL + avg_tenure_months_min (stability) +
n_companies_max (not a hopper) + open_to_work:true as a bonus tier only.
Territory split: same query, bucket_total:<reps>, bucket_index:<rep #>.
Handoffs and hygiene
Company lists IN (current_company_id/domain) come from
anysite-company-sourcing; people OUT go to anysite-crm-prospect
(dedup + CRM push).
For "up to N contacts across a few companies", 2–3 focused queries (base +
regional + function-specific) deduped by alias beat one mega-query — each
stays selective and each angle surfaces people the others rank low.
Emails have a real cost and yield — don't hand-wave it. The result's
alias is the vanity URL, ready for the email cascade (anysite-mcp →
Email finding): user_email first (cheap, ~half personal addresses, low
yield), then user_find_email_by_url (~75% yield but 50cr each — estimate
50cr × N and confirm before a big run) with its valid_email/email_status
as the deliverability gate. Personal/unverified addresses never go into a work
sequence. There is no built-in email verifier — for bounce-critical sends, gate
externally.
Live-verify the outreach shortlist via linkedin/user — the DB is fresh
but not realtime; it also yields the vanity URL. Job-change detection on CRM
contacts belongs to anysite-crm-champions (this DB's months_since_change_max
is its cheap pre-filter, not its evidence).
Sourcing individuals is personal-data processing: search to the stated business
need, don't hoard.
experience[]
Company — a ladder, pick the rung deliberately:
current_company_name DSL with QUOTED brand variants — the default. A bare
token like Tencent also matches subsidiaries ("Tencent Korea", "Fintech at
Tencent") — a feature for brand families, a bug if you need one legal entity.
current_company_id[] (numeric LinkedIn page ids, resolve via company
search first) — when strictness matters: separating Level Infinite from the
rest of Tencent, excluding brand-name lookalikes.
current_company_domain[] (bare domains) — when domains are what you have
(e.g. a CRM list).
keywords — LAST resort, only WITH ≥1 selective filter (company/title/
seniority/country) and never as the employer filter itself: it's full-text
across all fields, and an unselective keywords query is a DB scan
(measured: 140s → HTTP 500).
Also: any_company_id/domain (ever worked);
past_company_id[] (worked and LEFT — alumni); employee_count_min/max of
the current company. Do NOT use employee_range[] — the band string
contradicts the true headcount often (measured ~35%: a 104-person company
banded "11-50", a 58-person one "501-1000"); filter size only with the numeric
employee_count_min/max.
Industry:industry[] / any_industry[] take exact LinkedIn-taxonomy
labels (e.g. "Software Development" works), NOT market words — ["fintech"]
returns 0 (measured). Resolve labels via search_industries; for "fintech",
"SaaS" and the like, filter on the company side (anysite-company-sourcing
specialities) or on headline/skills DSL instead.
Geo:country[] ISO2 (reliable); location DSL for cities/metros.
"Responsible for a market" ≠ "located in it." When the user wants people
FOCUSED on a region (CIS/MENA/emerging markets), do NOT filter country by
that region — BD/publishing teams of global companies sit in HQ (KR/CN/US/NL/
SG). Search the market mention in the profile instead:
headline/summary: CIS|Russia|Kazakhstan|MENA|"emerging markets"|"Middle East". Measured on a live case: country:[RU,KZ,UZ,AE,SA,…] → 2 profiles;
the headline variant → 84. Use country only when the person must physically
BE in the region — and warn the user the pool will be narrow.
Education:edu_slug[], edu_institution, edu_field,
edu_ended_year_min/max (graduation cohort ≈ age proxy).
Career shape:months_in_role_max (new in role), months_in_role_min,
months_since_change_max (started OR ended a role recently — job-change
radar), experience_years_min, n_roles_*, n_companies_* (stability vs
hopping), promotion_count_min (promoted without changing employer),
avg_tenure_months_*.
Quality & coverage:profile_score_min (0–8) — do NOT set it by default:
it silently drops sparse-but-on-target profiles (a real user's default of 5
cut exactly the people they were hunting). Add it only when the user asks for
"complete/outreach-grade profiles" (then 5+), or as a tie-breaker on an
over-1000 pool. Plus the has_* family (has_current_role, has_role_dates,
has_education, has_company_size, has_engagement…).
Badges/engagement:open_to_work, hiring, verified, is_premium,
is_top_voice, follower_count_min, connection_count_min. (is_creator /
is_influencer filter but are NOT returned — you can't confirm them.)
Lookalike (EXPERIMENTAL — verify every time):similar_to / also_viewed
by alias. Measured unreliable: two seeds returned namesakes (same name,
different people) or nothing — NOT semantic lookalikes. Do not use it as a
"people like our champion" shortcut; if you try it, probe count:5 and confirm
the surnames differ from the seed's before trusting a single row. For real
lookalikes, replicate the champion's attributes as explicit filters instead.
Freshness:fetched_after (unix ts) — only recently refreshed profiles.