Hyreflow
Recipes

JD → Shortlist

Paste a job description, get a qualified shortlist with reachable contacts.

The most-requested recruiter play. Paste a job description → extract searchable filters → source candidates (general search + prioritized competitor profiles) → enrich the work history → qualify against the JD → enrich the candidate channel → ready for outreach.

The competitor leg prioritizes, it never filters exclusively. You always run the general search; competitor-sourced candidates get boosted to the top because they carry the domain logic. General profiles fill the rest of the shortlist.

Capability chain

JD → PARSE (AI) → [DISCOVER COMPETITORS (exa)] → SEARCH (general + competitor-priority, merged & ranked)
   → ENRICH PROFILE (linkedin_profile — work history with dates) → QUALIFY (AI)
   → ENRICH CONTACT (personal email + LinkedIn) → (outreach)

Enrich the profile before you score it. Search output is a snapshot — current title, employer, location — which cannot separate a long-tenured specialist from a recent career changer, and hides relevant experience sitting behind an unrelated current title. Contact enrichment stays after qualification, so you only pay for a survivor's email.

Inputs

JD text (any language). Optional: target count N (default 10), location override, "competitors only" (off by default).

Steps

Parse the JD → a canonical PeopleQuery

Extract titles[] (role + searchable EN/DE variants), skills[] (must-haves only), certifications[], min_experience_years, locations[], seniority, keywords[], plus the hiring company {name, domain, category} and reports_to.

Location rule: remote with no geo/language requirement → locations: []; otherwise honor the stated region and any language requirement ("German C2" → DACH).

Discover competitors (add-on)

exa.answer("direct competitors of {company} ({domain}) in {category}") → parse Name (domain) pairs. Skip if the JD has no clear company/category.

Don't use exa.find_similar on the homepage — it returns directories, not competitors.

Search — two legs into one ranked pool

Leg A (competitor-priority): per competitor domain, run people_search company-scoped (company_domains) with the JD filters. Tag _source = competitor:<domain>.

Leg B (general): run the waterfall with the JD filters and no company scope. Tag _source = general, over-provision ~1.4×N.

Merge + dedup by linkedin_url, rank competitor-sourced first, general fills the rest.

Enrich the profile — the work history qualify scores on

Run the linkedin_profile waterfall over the ranked pool → each row gets a normalized profile with experience[{company, title, start, end, is_current, duration_months?, description?}], newest role first. A row that comes back without employment history is a miss and costs nothing.

hyreflow enrich --input pool.csv --output enriched.csv --rows 0:1 \
  --with '{"alias":"profile","tool":"linkedin_profile","payload":{"linkedin_url":"{{linkedin_url}}"}}'

Field coverage varies by provider: the dated experience[] is the contract, while about/skills/certifications are filled only by the providers that carry them — read an absence as unknown, not as a gap. Skip rows that already carry a dated history (CRM/ATS records).

Qualify against the JD

Score each candidate's enriched history vs the JD must-haves → tier_1 | tier_2 | no_fit; drop no_fit. This is the precision step (raw search is recall). hyreflow qualify reports whether each candidate was scored on work_history or title_only, and refuses a batch in which no row carries work history — enrich first, or opt in with --allow-thin-profiles (allow_thin_profiles: true over the API) to rank on the sourcing fields.

Enrich the contact — candidate channel

Personal email + LinkedIn, NEVER work email. Run the personal_email waterfall (see Integrations Overview for the provider order), first-hit; verify deliverability (catch_all_safe counts as usable).

hyreflow enrich --input qualified.csv --output enriched.csv --rows 0:1 \
  --with '{"alias":"email","tool":"personal_email","payload":{"linkedin_url":"{{linkedin_url}}"}}'

Outreach (optional)

Personalize a first line, enroll in a recruiting sequence. See Campaign Plays.

Gates

Pilot one row, surface the projected enrich cost, get approval, then run the full pull. The two enrichment stages are the charged ones — search and qualify are free; a profile lookup that returns no employment history costs nothing. Cap the profile pass to the pool you intend to shortlist (~1.4×N).

On this page