Eine Claude Skill, die ein Jobbeschreibungsprofil sowie ein ICP-Rubrik entgegennimmt, eine KI-Sourcing-Abfrage gegen Juicebox, hireEZ oder LinkedIn Recruiter aufbaut, bis zu 200 Kandidaten abruft, jeden gegen das Rubrik mit zitierten Belegen bewertet und personalisierten Outreach für die Top-N entwirft – dann an einem menschlichen Review-Gate stoppt. Der Recruiter liest die Shortlist, bearbeitet die Nachrichten und sendet. Ersetzt die 3-Stunden-Boolean-plus-Scoring-plus-Outreach-Schleife durch eine 30-Minuten-Review-Schleife.
Wann einsetzen
Sie sourcen für eine Stelle, die öfter als einmal pro Quartal besetzt wird, und das ICP-Rubrik ist stabil genug, um es zu verschriftlichen.
Sie haben ein ICP-Rubrik mit Verhaltensankern pro Dimension (nicht nur vage Bezeichnungen). Die Rubrik-Vorlage in references/1-icp-rubric-template.md des Bundles zeigt die Form; wenn Sie sie nicht ausfüllen können, haben Sie noch kein Rubrik, gegen das diese Skill bewerten kann.
Sie haben API-Zugang zu Juicebox PeopleGPT, hireEZ oder LinkedIn Recruiter. Die Skill lehnt es ab, auf das Scrapen öffentlicher LinkedIn-URLs zurückzufallen.
Ein menschlicher Recruiter oder Sourcer überprüft jede Shortlist, bevor Outreach versandt wird. Die Skill schreibt Entwürfe auf die Festplatte und stoppt.
Wann NICHT einsetzen
Auto-Ablehnung in der Schleife. Die Skill rankt; sie lehnt nicht ab. Die „übersprungenen” Kandidaten werden mit Begründungen für den Recruiter zum Überstimmen aufgezeigt. Das Verdrahten einer reject-Aktion an einen Score-Schwellenwert verwandelt dies in automatisierte Entscheidungsfindung und löst EU-KI-Gesetz-Anhang-III-Hochrisiko-Pflichten plus NYC LL 144 Bias-Audit-Pflichten innerhalb eines Jahres vor der Nutzung aus. Wenn Sie das benötigen, lassen Sie ein Bias-Audit durchführen, nicht diese Skill.
Scoring auf Protected-Class-Proxies. Schul-Tier als eigenständige Dimension, Namensherkunft, Foto-Präsenz, Employment-Gap-Strafen, aus dem Abschlussjahr abgeleitetes Alter, „Culture Fit” ohne Verhaltensanker. Die Fairness-Checkliste der Skill lehnt die Ausführung ab, wenn eines davon im Rubrik erscheint. Bearbeiten Sie die Checkliste nicht, um ein voreingenommenes Rubrik passieren zu lassen.
Gehalts-Band-Empfehlungen. NYC LL 32-A, Colorado, Kalifornien und Washington erfordern veröffentlichte Bänder und Bias-Audit-Pflichten bei automatisierten Vergütungsentscheidungen. Verwenden Sie ein Comp-Benchmarking-Tool, keine Sourcing-Skill.
Einmalige C-Suite-Suchen. Eine Retained Search für eine spezifische namentlich genannte Person oder eine eng definierte Führungskraft ist von einem Menschen mit Netzwerk schneller erledigt. Die Skill ist für wiederholbares IC- und Manager-Level-Sourcing gebaut, wo Rubrik-Kalibrierung ihre Setup-Kosten zurückverdient.
Referenz-Checks oder Hintergrundrecherche. Andere Einwilligungsposition. Anderer Workflow.
Setup
Bundle einspielen. Platzieren Sie apps/web/public/artifacts/candidate-sourcing-claude-skill/SKILL.md in Ihrem Claude Code Skills-Verzeichnis (oder Claude.ai Custom Skills).
Rubrik ausfüllen. Kopieren Sie references/1-icp-rubric-template.md in eine Datei pro Rolle in Ihrem eigenen Repository. Ersetzen Sie jeden {Platzhalter}. Die Skill erfasst den SHA-256 des Rubriks in ihrem Audit-Log pro Durchlauf, sodass nachfolgende Bearbeitungen im Retro sichtbar sind.
Quellkanal konfigurieren. Fügen Sie Ihren Juicebox- oder hireEZ-API-Schlüssel zur Konfiguration der Skill hinzu. Für LinkedIn konfigurieren Sie Recruiter-API-Zugangsdaten – die Skill lehnt das Scrapen öffentlicher Profil-URLs ab.
Do-Not-Poach- und Ausschlusslisten erstellen. Eine CSV der Kunden-Domains (Do-Not-Poach) und eine CSV der exclude_list-URLs (kürzlich abgelehnte, in stiller Periode, abgemeldet). Der deterministische Pre-Filter in Schritt 3 der Skill wendet diese an, bevor das LLM einen Kandidaten sieht.
Probelauf auf einer abgeschlossenen Stelle. Führen Sie auf einer Stelle aus, die Sie letztes Quartal manuell besetzt haben. Vergleichen Sie die Top-25 der Skill mit Ihren manuellen Top-25. Stimmen Sie die Rubrik-Anker ab, wenn die Skill anders kalibriert – die Anker, nicht die Suchabfrage, sind üblicherweise falsch.
Was die Skill tatsächlich tut
Sechs Schritte der Reihe nach. Die Reihenfolge ist wichtig: deterministische Filter und Fairness-Pre-Flight kommen vor dem LLM-Ranking, weil ein LLM losgelassen auf einen kontaminierten Pool schnelle, sichere, unbrauchbare Ausgabe produziert.
Rubrik validieren gegen references/2-fairness-checklist.md. Halten, wenn das Rubrik Protected-Class-Proxies enthält. Die Entscheidung, vor dem Abruf statt danach zu scheitern, ist bewusst – ein voreingenommenes Rubrik, das in eine Sourcing-Tool-API geladen wird, hinterlässt einen Logeintrag, der bereits als automatisierte Verarbeitung unter DSGVO Art. 22 gilt.
Suchabfrage aufbauen im nativen Format des Kanals. Synonyme auf 5 pro Dimension begrenzen; abgerufener Pool auf 200 begrenzen. Größere Pools verschlechtern das Ranking, weil der Modellkontext mit wenig relevanten Kandidaten gefüllt wird.
Deterministischer Pre-Filter.exclude_list-Übereinstimmungen, Do-Not-Poach-Unternehmen, Standortfehler und Profile >18 Monate veraltet entfernen. Dies sind überprüfbare Filter; das LLM erlegt ihnen keine erneute Beurteilung auf.
Rubrik-basiertes Ranking. Bewertung 1–5 für Skill, Level, Unternehmens-Muster, Response-Likelihood. Jede Bewertung über 1 zitiert einen verbatim Profilstring. Kein Zitat → Bewertung 1. Die Zitat-Anforderung hält das Modell im Profiltext verankert statt aus Name, Foto oder Schule zu schließen.
Menschliches Review-Gate.shortlist.md und pro-Kandidaten outreach/<id>.md-Dateien schreiben. Stopp. Die Skill definiert keine send-Aktion.
Audit-Log. Eine JSONL-Zeile pro Durchlauf anhängen mit run_id, rubric_sha256, Pool-Größen, Kanal, Modell. Keine PII. Das macht den Durchlauf unter NYC LL 144 oder EU-KI-Gesetz-Befragung verteidigbar.
Das Shortlist-Format und das Pro-Kandidaten-Beleglayout befinden sich in references/3-shortlist-format.md im Bundle. Das Format ist fest, weil nachgelagerte Konsumenten – Recruiter, Hiring Manager, Audit-Reviewer – vorhersehbare Spalten brauchen.
Kostenrealität
Pro Shortlist von 25 aus einem 200-Kandidaten-Pool auf Claude Sonnet 4.5:
Abrufkosten — hängt vom Kanal ab. Juicebox PeopleGPT zählt gegen Ihr monatliches Abfragekontingent (Starter-Pläne mit 200 Suchen sind schnell erschöpft, wenn Sie mehrere Rollen pro Woche ausführen). hireEZs Unlocks-per-Month ist dort die bindende Einschränkung. LinkedIn Recruiter API hat eigene Per-Seat-InMail- und Suchkontingente. Nichts davon ändert sich mit der Skill in der Schleife; Sie geben dasselbe Kanalquotient aus, das Sie bei manueller Boolean-Suche ausgegeben hätten.
LLM-Tokens — typischerweise 80–120k Input-Tokens (Rubrik + 200 Kandidatenprofil-Auszüge + Skill-Anweisungen) und 8–15k Output-Tokens (Shortlist + 25 Outreach-Entwürfe). Auf Sonnet 4.5 sind das rund $0,50–0,80 pro Shortlist. Der volle Monat für einen Sourcer, der ~80 Shortlists ausführt, landet bei $40–65 in Modellkosten.
Recruiter-Zeit — der Gewinn liegt hier, nicht in den Modellkosten. Manuelles Boolean + Scoring + Outreach für 25 Kandidaten sind 2–3 Stunden. Die Shortlist der Skill zu überprüfen und die Entwürfe zu bearbeiten sind 25–40 Minuten, was den Workflow lohnenswert macht.
Setup-Zeit — 45 Minuten für Rubrik und Ausschlusslisten, wenn das Rubrik bereits in irgendeiner Form existiert; länger, wenn das Rubrik grundlegend neu ist (wobei Structured Interviewing die Voraussetzung ist, nicht diese Skill).
Erfolgsmetrik
Verfolgen Sie drei Zahlen pro Stelle pro Monat im ATS:
Antwortrate auf Outreach — sollte der manuellen Baseline des Recruiters entsprechen oder sie übertreffen. Wenn sie sinkt, sind die Outreach-Entwürfe generisch – üblicherweise ist das Rubrik zu grob, nicht das Modell.
Shortlist-zu-Screen-Durchlaufquote — der Anteil der auf der Shortlist stehenden Kandidaten, die der Hiring Manager als screen-würdig erachtet. Sollte ≥70 % bei einer stabilen Stelle betragen. Darunter ist das ICP-Rubrik fehlkalibriert; führen Sie es auf einer abgeschlossenen Stelle aus und stimmen Sie es ab.
Zeit von Stellenöffnung bis zum ersten qualifizierten Screen — die Durchsatz-Metrik, die die Skill bewegen soll. Die 3-Stunden-zu-30-Minuten-Reduktion zeigt sich hier, nicht in den Modellausgaben.
Vergleich mit Alternativen
vs. Gem AI Sourcing — Gem besitzt den Recruiter-Workflow von Ende zu Ende (Sourcing-UI, Sequenzen, Analysen, ATS-Integration via Ashby und andere). Wählen Sie Gem, wenn Sie ein verwaltetes Produkt möchten und Ihr Team in seiner UI leben wird. Wählen Sie diese Skill, wenn Sie das Rubrik, die Pre-Filter-Logik und das Audit-Log in Ihrem eigenen Repository versioniert haben möchten, mit auswechselbarem Modell.
vs. hireEZs eingebautem AI-Ranking — hireEZ AI Match ist gutes Retrieval; die Lücke liegt auf der Rubrik-Ebene. Mit dieser Skill behalten Sie hireEZ als Retrieval-Kanal und bringen Ihr eigenes Rubrik + evidenz-zitiertes Scoring darüber. Wenn hireEZs Defaults Ihrem ICP entsprechen, brauchen Sie diese Skill nicht.
vs. manueller Boolean + Tabellen-Scoring — manuell ist richtig für einmalige oder Executive-Suchen, bei denen das Rubrik im Kopf des Recruiters liegt und das Aufschreiben Overhead ist, der sich nicht amortisiert. Die Skill verdient ihre Setup-Kosten bei sich wiederholenden Stellen.
vs. selbst gebautem Python-Skript gegen die LinkedIn / Juicebox APIs — gleiche Ranking-Qualität, wenn Sie den Prompt sorgfältig aufbauen, aber Sie bauen auch die Fairness-Checkliste, das Audit-Log und das menschliche Review-Gate selbst. Das Bundle liefert sie.
Wichtige Hinweise
Bias-Verstärkung — durch die Fairness-Checkliste in references/2-fairness-checklist.md abgesichert, die den Durchlauf anhält, wenn das Rubrik Protected-Class-Proxies enthält. Das Audit-Log erfasst rubric_sha256 pro Durchlauf, sodass das an einem bestimmten Datum verwendete Rubrik unter EU-KI-Gesetz oder NYC LL 144 reproduzierbar ist.
Veraltete LinkedIn / Juicebox-Daten — durch den deterministischen Filter in Schritt 3 abgesichert (Profile >18 Monate veraltet entfernen) und durch die Response-Likelihood-Dimension im Scoring (die Aktualität gewichtet). Cold-Storage-Kandidaten verdrängen keine aktiv suchenden.
LinkedIn-ToS-Exponierung — durch die Weigerung gesichert, öffentliche Profil-URLs zu scrapen. Die Skill verwendet die Recruiter API, Juicebox oder hireEZ, die ihre eigene Datenlizenzierung tragen. Wenn linkedin_recruiter ausgewählt ist und die API nicht konfiguriert ist, bricht die Skill mit einem Setup-Fehler ab, statt zurückzufallen.
Auto-Send-Drift — durch das menschliche Review-Gate (Schritt 5) und das Fehlen einer send-Aktion in der Skill gesichert. Entwürfe werden in outreach/<id>.md-Dateien für den Recruiter geschrieben, um sie in den ATS / Sourcing-Tool-Outbox einzufügen. KI-verfasst-und-gesendet ohne Review produziert Volumen ohne Qualität und schadet der Candidate Experience.
Comp-Transparenz — Outreach-Entwürfe nennen nie eine Zahl; sie referenzieren die Band als „wettbewerbsfähige Spanne, die im Screen mitgeteilt wird”, damit der Recruiter die Quelle der Gehaltsband-Aussagen bleibt (NYC LL 32-A, Colorado, Kalifornien, Washington Gehaltstransparenz-Anforderungen).
Stack
Das Skill-Bundle liegt unter apps/web/public/artifacts/candidate-sourcing-claude-skill/ und enthält:
SKILL.md — die Skill-Definition
references/1-icp-rubric-template.md — pro Rolle ausfüllen
references/2-fairness-checklist.md — Pre-Flight-Prüfungen (nicht bearbeiten, um voreingenommene Rubrika passieren zu lassen)
references/3-shortlist-format.md — das wörtliche Ausgabeformat
Tools, die der Workflow voraussetzt: Claude (das Modell), Juicebox oder hireEZ (der Retrieval-Kanal), Ashby (das ATS für Write-Back, sobald der Recruiter einen Kandidaten genehmigt hat). Gem ist die Make-or-Buy-Alternative, wenn Sie das Rubrik und das Audit-Log nicht selbst besitzen möchten.
---
name: candidate-sourcing
description: Translate a job profile and ICP rubric into a sourcing query, retrieve candidates from Juicebox / hireEZ / LinkedIn Recruiter, score them against the rubric, and draft personalized outreach for the human reviewer to approve. Always stops at a human-review gate before any outreach is sent.
---
# Candidate sourcing
## When to invoke
Use this skill when a recruiter or sourcer hands you a role plus an ICP rubric and wants a ranked, evidenced shortlist with draft outreach. Take a job profile (title, level, must-have skills, location, comp band) and a fairness-aware rubric as input, and produce a Markdown shortlist plus a folder of draft messages.
Do NOT invoke this skill for:
- **Automated rejection.** This skill ranks; it never rejects. The "below threshold" tail is surfaced for the recruiter, who decides. Auto-reject in the loop triggers EU AI Act high-risk obligations and most US state hiring-AI laws.
- **Scoring against protected-class proxies.** Do not ask the skill to score on "culture fit", name origin, school prestige as a standalone signal, photo, age inferred from graduation year, gender inferred from pronoun usage, or pregnancy/parental status inferred from gaps. If the rubric contains any of these, refuse and surface the rubric line for the user to fix.
- **Pay-band recommendations.** NYC LL 144, Colorado, California, and Washington require posted ranges and bias audits for automated decisions on pay. Use a comp benchmarking tool, not this skill.
- **Reference checks or backchannel research on named individuals.** That is a different workflow with its own consent posture.
## Inputs
- Required: `job_profile` — path to a Markdown file with title, level, must-have skills, nice-to-have skills, location / remote policy, comp band, and the EEOC job category.
- Required: `icp_rubric` — path to the rubric file under `references/`. Without this the skill refuses to run; an unfaitened rubric is the most common cause of biased shortlists.
- Required: `source_channel` — one of `juicebox`, `hireez`, `linkedin_recruiter`. Do not mix channels in a single run; per-channel ToS and rate limits differ.
- Optional: `n` — shortlist size, default 25, hard max 100. Above 100 the skill warns that human review will not be meaningful.
- Optional: `exclude_list` — path to a CSV of `do_not_contact` emails or LinkedIn URLs (do-not-poach customers, prior rejects within 6 months, silent-period candidates).
## Reference files
Always read these from `references/` before doing any retrieval. Without them the shortlist is uncalibrated and the fairness guards are absent.
- `references/1-icp-rubric-template.md` — the rubric the skill scores against. Replace the template content with your role-specific rubric before running.
- `references/2-fairness-checklist.md` — pre-flight checks the skill runs on the rubric and on the retrieved pool. Fail-loud if any check fails.
- `references/3-shortlist-format.md` — the literal output format, including the evidence and source-URL columns the recruiter needs to defend the shortlist downstream.
## Method
Run these six steps in order. Steps 1-3 are deterministic filters and fairness pre-flight; only step 4 uses the LLM for ranking. The order is deliberate — running the LLM over an unfiltered, ToS-violating, or rubric-contaminated pool produces output that is fast, confident, and unusable.
### 1. Validate the rubric
Open `icp_rubric` and run every check in `references/2-fairness-checklist.md`. If any line in the rubric matches a protected-class proxy pattern (school-tier scoring, name-based filtering, employment-gap penalties, photo presence, "culture fit" without behavioral anchors), stop and return the offending lines to the user. Do not proceed with retrieval.
The choice to fail before retrieval rather than after is intentional: a biased rubric loaded into a sourcing tool's API leaves a log entry that counts as automated processing under GDPR Art. 22 and the EU AI Act, regardless of whether the skill ever shows the user the result.
### 2. Build the search query
Translate the job-profile must-haves into the channel's native query format:
- `juicebox` → natural-language PeopleGPT prompt, with location and level filters set as structured parameters not free text.
- `hireez` → Boolean string with explicit AND/OR/NOT grouping. Cap synonyms at 5 per dimension; longer Boolean degrades hireEZ's relevance ranking.
- `linkedin_recruiter` → use the Recruiter API with structured filters only. **Do not scrape `linkedin.com/in/` URLs** — that violates LinkedIn ToS and the *hiQ v. LinkedIn* settlement does not change ToS exposure for production sourcing.
Cap the retrieved pool at 200. Larger pools degrade rubric scoring because the LLM context fills with low-relevance candidates and the ranking flattens.
### 3. Deterministic pre-filter
Before the LLM sees any candidate, apply hard filters:
- Drop anyone in `exclude_list`.
- Drop anyone whose current company is on the do-not-poach list.
- Drop anyone whose profile was last updated more than 18 months ago (LinkedIn / Juicebox staleness signal).
- Keep only candidates whose stated location matches the role's location policy (with a configurable radius for hybrid roles).
These filters are deterministic so they can be audited. The LLM does not re-litigate them in step 4.
### 4. Rubric-based ranking
For each remaining candidate, score 1-5 on each rubric dimension (skill-match, level-fit, company-pattern-fit, response-likelihood). For every score above 1, cite the specific evidence string from the candidate's profile. No evidence string → score 1 by default.
Why a citation requirement: it forces the model to ground each score in profile text rather than infer from a name, photo, or school. Scores without evidence are the mechanism by which bias enters AI-augmented sourcing pipelines.
### 5. Human-review gate
Stop. Write the shortlist to `shortlist.md` per the format in `references/3-shortlist-format.md`. Write the draft outreach to `outreach/<candidate-id>.md`, one file per candidate. Do not call any "send" endpoint. Do not mark candidates as contacted in the ATS. Surface the path to both directories and exit.
The recruiter's job from here: read the shortlist, edit the messages, and send through the ATS or sourcing tool's outbox. The skill does not re-enter the loop until the next role.
### 6. Audit log
Append a single line to `audit/<YYYY-MM>.jsonl` containing: `run_id`, `role`, `rubric_sha256`, `pool_size_pre_filter`, `pool_size_post_filter`, `shortlist_size`, `channel`, `model_id`, `timestamp`. Do not log candidate PII to this file. The audit log exists so that under NYC LL 144 or EU AI Act questioning, the recruiter can demonstrate which rubric was used on which date.
## Output format
```markdown
# Sourcing shortlist — {Role title}
Generated: {ISO timestamp} · Channel: {channel} · Pool: {pre} → {post} · Rubric SHA: {short}
| # | Name | Current role | Current company | Skill | Level | Pattern | Response | Aggregate | Source |
|---|---|---|---|---|---|---|---|---|---|
| 1 | Jamie L. | Senior Backend Engineer | Acme Fintech | 5 | 5 | 4 | 4 | 18 | {URL} |
| 2 | ... | ... | ... | ... | ... | ... | ... | ... | ... |
## Evidence — top 5
### 1. Jamie L. (aggregate 18)
- **Skill (5)**: "5y Go, 2y Rust, led migration from monolith to event-driven services" — profile, role 2.
- **Level (5)**: "Senior IC, scope across two teams, mentors three engineers" — profile, current role.
- **Pattern (4)**: "Stripe → Plaid → Acme Fintech" — three fintech roles in sequence.
- **Response likelihood (4)**: profile updated 11 days ago, "open to opportunities" tag set.
### 2. ...
## Skipped — surfaced for review (not auto-rejected)
| Name | Reason |
|---|---|
| ... | "current company on do-not-poach list (Acme Customer)" |
| ... | "profile last updated 2023-11, staleness > 18mo" |
## Draft outreach
Drafts written to `outreach/`. Recruiter reviews and sends; this skill
does not contact candidates.
- `outreach/jamie-l.md`
- `outreach/...`
```
## Watch-outs
- **Bias amplification (NYC LL 144, EU AI Act, EEOC).** *Guard:* the fairness checklist in `references/2-fairness-checklist.md` runs in step 1 and refuses retrieval if rubric contains protected-class proxies. Audit log in step 6 stores `rubric_sha256` so the rubric used on a given run is reproducible.
- **LinkedIn ToS exposure.** *Guard:* skill uses the Recruiter API (or Juicebox / hireEZ which carry their own data licensing), never scrapes public LinkedIn pages. If the channel is `linkedin_recruiter` and the Recruiter API is not configured, the skill aborts with a setup-error rather than falling back to scraping.
- **Stale profile data.** *Guard:* deterministic filter in step 3 drops candidates with `profile_updated > 18mo`. Response-likelihood scoring in step 4 weights profile freshness explicitly so cold-storage candidates do not crowd out actively looking ones.
- **Auto-send drift.** *Guard:* skill stops at the human-review gate in step 5 and writes to `outreach/` files. There is no `send` action defined anywhere in this skill. To send, the recruiter pastes into the ATS / sourcing tool outbox.
- **Rubric drift mid-search.** *Guard:* `rubric_sha256` is captured per run; if the rubric changes between two runs for the same role, the audit log shows both hashes, making it visible in retro.
- **Compensation discussion in draft outreach.** *Guard:* outreach templates in this skill never quote a number; they reference the comp band as "competitive range disclosed on screen" so the recruiter remains the source of pay-band statements (NYC LL 32-A, CO, CA, WA pay-transparency posting).
# ICP rubric — TEMPLATE (per role)
> Replace this template's contents with the rubric for the specific role.
> The candidate-sourcing skill scores against the four dimensions below.
> Each dimension MUST have behavioral anchors — vague labels ("senior")
> without anchors produce noisy and biased scoring.
## Role identity
- **Title**: {e.g. Senior Backend Engineer, Platform}
- **Level**: {IC4 / IC5 / EM1 — your internal scale}
- **Location policy**: {remote-US / hybrid-NYC-2dpw / onsite-Berlin}
- **EEOC job category**: {2 — Professionals (most engineers); see EEO-1}
- **Comp band (recruiter-internal, never sent to skill output)**: {range}
## Dimension 1 — Skill match (1-5)
The candidate's profile shows direct experience with the must-have technologies and the specific problem-shape of the role.
| Score | Anchor |
|---|---|
| 5 | Held a role doing exactly this work for ≥2 years; cites artifacts (talks, OSS, posts). |
| 4 | Held a role doing exactly this work for ≥1 year; no artifacts. |
| 3 | Adjacent work (e.g. Java backend role for a Go role); transferable. |
| 2 | Tangential work; would require ramp. |
| 1 | No evidence in profile. |
## Dimension 2 — Level fit (1-5)
The candidate's stated scope and tenure pattern match the level the role is hiring at. Do NOT use school prestige, employer prestige, or title inflation as a level signal — anchor on scope description.
| Score | Anchor |
|---|---|
| 5 | Profile shows scope at or above target level (multi-team, mentoring, technical strategy). |
| 4 | Scope at target level for ≥1 year. |
| 3 | One level below target; growth trajectory plausible. |
| 2 | Two levels below; reach. |
| 1 | More than two levels off, in either direction. |
## Dimension 3 — Company-pattern fit (1-5)
The shape of the candidate's prior employers matches the shape of yours (stage, scale, regulated/unregulated, B2B/B2C). Anchor on *characteristics*, not brand names — brand-name scoring is the most common bias vector in AI-augmented sourcing.
| Score | Anchor |
|---|---|
| 5 | ≥2 prior employers match {stage/scale/domain pattern}. |
| 4 | 1 prior employer matches; others adjacent. |
| 3 | All adjacent (different domain, similar stage). |
| 2 | Mostly mismatched; one transferable role. |
| 1 | No pattern match. |
## Dimension 4 — Response likelihood (1-5)
How likely the candidate is to respond to outreach right now.
| Score | Anchor |
|---|---|
| 5 | Profile updated <30 days; "open to opportunities" set; recently posted about job search. |
| 4 | Profile updated <90 days. |
| 3 | Profile updated <180 days. |
| 2 | Profile updated <12 months. |
| 1 | Stale profile (>12 months) — *also flagged in pre-filter for drop at >18mo*. |
## Disqualifiers (deterministic, applied in step 3 of the skill)
These cause the candidate to be surfaced in the "skipped" table, not auto-rejected. The recruiter decides.
- Current company is on do-not-poach list (`{path-to-list}`).
- Email or LinkedIn URL appears in `exclude_list`.
- Stated location does not match role's location policy + radius.
- Profile last updated >18 months ago.
## Bias guards (refusal triggers — skill aborts in step 1 if present)
If any of the following appear in this rubric, the skill refuses to run:
- School-tier scoring as a standalone dimension.
- Name-based filtering or scoring.
- Photo-based scoring.
- Employment-gap penalties without a job-related justification.
- Age inferred from graduation year used in any dimension.
- Gender, ethnicity, religion, sexual orientation, parental status, or disability status as a scored or filtered dimension.
- "Culture fit" without behavioral anchors.
## Last edited
{YYYY-MM-DD} — bump on every material change. The skill captures the SHA-256 of this file in its audit log per run.
# Fairness pre-flight checklist
> The candidate-sourcing skill runs every check below in step 1 (rubric
> validation) and step 3 (post-filter pool review). Any failed check
> halts the run with a message naming the failure. Do not edit this file
> to make checks pass — fix the rubric or the search instead.
## A. Rubric checks (run before retrieval)
A1. **No protected-class proxies.** Scan the rubric for any of the following terms or patterns. Any hit halts the run:
- `school`, `university`, `Ivy`, `tier-1`, `top-N` (when used as a scoring dimension, not as one signal among many)
- `name origin`, `surname`, `first name`
- `photo`, `headshot`, `appearance`
- `age`, `years since graduation`, `birth year`
- `gender`, `pronoun`, `she/her`, `he/him` (as filter terms)
- `ethnicity`, `race`, `nationality` (except where required for immigration-status filtering with documented legal basis)
- `pregnant`, `parental`, `maternity`, `paternity`
- `disability`, `accommodation`
- `religion`, `political`, `marital`
- `culture fit` without a behavioral-anchor table immediately following
A2. **Anchors present on every dimension.** Each rubric dimension must have a 1-5 anchor table. Anchors prevent the LLM from scoring on vibes. Halt if any dimension has free-text anchors only.
A3. **Disqualifier list is short and mechanical.** Disqualifiers must be deterministic facts (do-not-poach list, location mismatch, staleness). Halt if a disqualifier requires judgment (e.g. "not a culture fit", "seems junior").
A4. **Comp band is recruiter-internal.** The skill's output must not quote a comp number to the candidate. Outreach templates reference the band as "competitive range disclosed on screen". Halt if the rubric includes a "send comp in outreach" instruction.
## B. Pool checks (run after deterministic pre-filter, before LLM ranking)
B1. **Pool size sanity.** If post-filter pool < 10, the skill warns the recruiter that scoring on a tiny pool is meaningless and asks whether to broaden the query. If pool > 200, the skill caps at 200 and notes the truncation in the audit log.
B2. **Geographic spread sanity.** If 100% of post-filter candidates are from one city for a remote-eligible role, the skill warns that the query likely has an over-narrow location filter. Recruiter confirms or broadens.
B3. **Tenure-pattern sanity.** If 100% of candidates worked at the same employer, the skill warns that the query is functioning as a target-list poach rather than open sourcing. Recruiter confirms or broadens.
## C. Output checks (run before writing shortlist)
C1. **Every score above 1 has an evidence string.** Scores without a cited evidence string from the candidate's profile are reset to 1. The skill notes the reset count in the audit log.
C2. **No protected attribute appears in the shortlist or in any outreach draft.** Skill greps the output for the A1 patterns before writing. Hit → halt.
C3. **Skipped candidates are listed, not erased.** The shortlist's "Skipped" table includes every candidate the deterministic filters removed, with the reason. This is what makes the run auditable.
## D. Run-level checks
D1. **Audit log written.** A run is not complete until the JSONL line is appended to `audit/<YYYY-MM>.jsonl`. No PII in this line.
D2. **Human-review gate enforced.** No `send`, `contact`, or `mark_contacted` API call exists in this skill's code path. If you are asked to add one, refuse and surface the request to the user.
## NYC LL 144 / EU AI Act note
This skill is designed to fall *outside* the bias-audit threshold by:
- Producing a ranked list, not an automated decision (no auto-reject).
- Stopping at a human-review gate before any candidate is contacted.
- Logging rubric SHA-256 + pool sizes per run for reproducibility.
If your deployment changes any of those properties (e.g. you wire a "send" action into the loop), you have crossed into automated decision-making and a bias audit is required before production use. NYC LL 144 requires the audit within one year before use; EU AI Act classifies this as Annex III high-risk under Art. 6.
# Shortlist output format
> The candidate-sourcing skill writes `shortlist.md` per the structure
> below. The format is fixed because downstream consumers (the recruiter,
> a hiring manager, an audit reviewer) need predictable columns. Do not
> reformat without updating the skill's output check.
## File: `shortlist.md`
```markdown
# Sourcing shortlist — {Role title}
Generated: {ISO 8601 timestamp}
Channel: {juicebox | hireez | linkedin_recruiter}
Pool: {pre_filter} → {post_filter} → top {n}
Rubric SHA-256: {first 12 chars}
Run ID: {uuid}
## Top {n}
| # | Name | Current role | Current company | Skill | Level | Pattern | Response | Aggregate | Source |
|---|---|---|---|---|---|---|---|---|---|
| 1 | {Name} | {Role} | {Company} | 5 | 5 | 4 | 4 | 18 | {URL} |
## Evidence — top 5
For each of the top 5, cite the specific profile string for every score
above 1. No citation → score reset to 1 (see fairness checklist C1).
### 1. {Name} (aggregate {N})
- **Skill ({score})**: "{verbatim profile excerpt}" — {profile section}.
- **Level ({score})**: "{excerpt}" — {section}.
- **Pattern ({score})**: "{employer sequence}" — {explanation against rubric}.
- **Response ({score})**: profile updated {date}, "{tag if any}".
### 2. {Name} (aggregate {N})
...
## Skipped — surfaced for review (NOT auto-rejected)
| Name | Reason | Source |
|---|---|---|
| {Name} | "current company on do-not-poach list ({customer})" | {URL} |
| {Name} | "stated location {city} outside role policy {policy}" | {URL} |
| {Name} | "profile last updated {date}, staleness > 18mo" | {URL} |
## Suggested talk-track per top candidate
The recruiter uses these as talk-track scaffolding for the first
screening call. They are NOT scripts.
### 1. {Name}
- **Open with**: their {recent role / talk / OSS contribution} — specific
reference, not a generic compliment.
- **Likely motivation hypothesis**: {evidence-based, e.g. "third fintech
role in a row, may be looking for a non-fintech reset; ask"}.
- **Hesitation to surface**: {e.g. "current company is well-funded; ask
what would have to be true for them to consider a move"}.
### 2. {Name}
...
## Outreach drafts
Drafts written to `outreach/{candidate-id}.md`, one file per candidate.
The recruiter reviews, edits, and sends through the ATS or sourcing
tool's outbox. The skill does not contact candidates.
- `outreach/{id-1}.md`
- `outreach/{id-2}.md`
- ...
```
## File: `outreach/<candidate-id>.md`
```markdown
# Outreach draft — {Name}
Channel: {LinkedIn InMail | email | Juicebox sequence}
Subject: {≤60 chars, references a specific signal from the profile}
---
Hi {first name},
{One sentence referencing a specific, recent thing from their profile —
the {recent role / talk / project / post}. Not a flattery line.}
I'm hiring a {role title} at {company}. The reason I reached out is
{specific connection between their background and the role — cite the
profile signal}. The role's {one specific differentiator that would
matter to someone with this background}.
If you're open to a 15-minute conversation, I'm happy to share more. The
comp range will be disclosed on screen if we get to that step.
{Recruiter name}
---
## Recruiter-only metadata (strip before sending)
- Aggregate score: {N}
- Top evidence string: "{excerpt}"
- Source URL: {URL}
- Run ID: {uuid}
- Reviewed by recruiter: [ ]
- Sent: [ ]
```
## Why these fields are non-negotiable
- **`Source` URL on every row** — required for the recruiter to spot-check the LLM's evidence claims against the actual profile.
- **`Pool: pre → post → top N`** — surfaces how many candidates were filtered out deterministically vs. by the LLM. Big LLM-side cuts on a small post-filter pool is a signal of overfitting to rubric noise.
- **`Rubric SHA-256`** — proves which rubric was used on this run (NYC LL 144 audit defense + EU AI Act traceability).
- **`Skipped` table** — candidates filtered out are listed with reasons, not erased. Erasing them turns the workflow into automated rejection.
- **Recruiter-only metadata in outreach** — stripped before sending; its presence in the draft is what reminds the recruiter the message is a draft, not a finished product.