Weekly recruiter sourcing pipeline into Bullhorn

Every Monday morning, pull a fresh longlist of passive candidates, shortlist the strongest, enrich their contact info, and load them into Bullhorn ready to outreach.

Agentic Task
RocketReachBullhornSlackHR & PeopleOperationsLead EnrichmentResearch & MonitoringDaily Digests

Build me a weekly recruiter sourcing workflow that turns a saved ideal-candidate brief into vetted prospects sitting in Bullhorn, ready to outreach. This should be an agent workflow.

Trigger: cron, every Monday at 7am in the user's local timezone.

Prompt config (the role brief the agent uses on every run): a free-text role title, a seniority level, a list of must-have skills, a list of target locations, a list of current employers to pull from, a list of past employers to pull from, a shortlist size (default 10 to 15), the Slack channel ID to post the digest into, and the Bullhorn owner user ID that should own newly created candidates.

Step 1: longlist (free). Call RocketReach Search People with the title, seniority, skills, location, and current/past employer filters from the prompt config. Use page_size 100 and paginate until you have at least 100 candidates or the result set is exhausted. Search People returns matches without contact info and does not consume lookup credits, so do not call Person Lookup yet.

Step 2: shortlist (free). Read the role brief and the longlist, score each profile against the brief (title fit, seniority fit, skills match, location fit, employer signal), and pick the top N where N is the shortlist size from the prompt config. Keep a one-line rationale per pick ("why this candidate") and a one-line reason for the strongest candidates you rejected. Do not enrich anyone yet.

Step 3: dedupe against Bullhorn (free). For each shortlisted candidate, call Bullhorn Search Entities on the Candidate entity with a Lucene query that matches on email or LinkedIn URL or (firstName AND lastName AND companyName). If a non-deleted Candidate already exists, drop the candidate from the enrichment list and remember them as "already in Bullhorn" for the digest. This step matters: it prevents wasting RocketReach lookup credits on candidates we already have.

Step 4: enrich (costs credits). For each remaining shortlisted candidate, call RocketReach Person Lookup with the RocketReach profile ID from Step 1 to retrieve verified email, phone, and LinkedIn URL. Use lookup_type "standard". Person Lookup is async — if the response status is "searching" or "progress", poll Check Person Lookup Status until status is "complete" (cap at ~30 seconds per candidate, then move on). If a lookup ultimately returns no verified email, skip that candidate and note it for the digest.

Step 5: create prospect in Bullhorn. For each successfully enriched candidate, call Bullhorn Create Entity on the Candidate entity. Populate firstName, lastName, email, mobile (if returned), and the LinkedIn URL on the appropriate social profile field. Set status to a passive/prospect status (e.g. "New Lead" or the equivalent in this Bullhorn instance) and set owner to the Bullhorn owner user ID from the prompt config. Do NOT attach the candidate to a specific JobOrder — there is no job application yet, this is a sourced prospect. After creating the Candidate, create a Bullhorn Note attached to it containing the one-line "why this candidate" rationale from Step 2 and a "sourced via weekly RocketReach pipeline" tag.

Step 6: digest. Call Slack Send a Message to the channel from the prompt config. The digest should include: how many profiles were sourced from RocketReach in total, how many were shortlisted, how many made it through dedupe, how many were successfully enriched and created in Bullhorn, the shortlist itself (name, current title, current company, one-line rationale, link to the new Bullhorn Candidate record), the candidates skipped because they were already in Bullhorn (name + "already in Bullhorn"), the candidates skipped because enrichment failed, and a closing link to the Bullhorn Candidate list view filtered to this week's sourced batch.

Guardrails: never call Person Lookup before dedupe; never create a Candidate in Bullhorn that already exists; always reuse the Bullhorn BhRestToken across operations in the same run instead of re-authenticating per call; respect RocketReach's 5 requests/second cap and honour Retry-After on 429 responses; if the entire RocketReach search returns zero results or the Bullhorn session can't be established, post a short Slack message to the same channel explaining what failed and exit cleanly.

Note on the ATS: the original ask referenced Greenhouse, but Bullhorn is the supported recruiting CRM here and is the right fit for sourced prospects (no job application required, full Candidate + Note model). Build against Bullhorn.

Additional information

What does this prompt do?
  • Runs every Monday at 7am and pulls a fresh candidate longlist from RocketReach using the search you saved in the prompt (title, seniority, skills, location, current and past employers).
  • Reads each profile, scores it against your role brief, and picks the 10 to 15 strongest fits to enrich.
  • Skips anyone already in Bullhorn so you never waste a contact lookup on a candidate you have, then pulls verified email, phone, and LinkedIn for the shortlist.
  • Creates a fresh prospect record in Bullhorn for every shortlisted candidate, with contact info and a short why-they-fit note attached.
  • Posts a Monday morning digest to Slack: how many were sourced, who made the shortlist with a one-line rationale, who was skipped and why, and a link to your Bullhorn view.
What do I need to use this?
  • A RocketReach account on a plan that includes API access (Essentials, Pro, Ultimate, or a dedicated API plan).
  • A Bullhorn account with REST API credentials and permission to create candidate records.
  • A Slack workspace and the channel you want the Monday digest posted to.
  • A role brief: title, seniority, must-have skills, target locations, and current or past employers worth pulling from.
How can I customize it?
  • Change the day or time. Monday at 7am is the default, but any weekday and any local time works.
  • Tune the search filters. Edit titles, seniority levels, locations, skills, or target employers right in the prompt config.
  • Move the shortlist size. The default is 10 to 15 per week. Raise it if you have credits to spare, lower it to stretch your plan.
  • Swap the destination Slack channel, or send the digest as a DM to the recruiter instead.
  • Tighten the dedupe rule. By default it skips anyone already in Bullhorn with the same email or LinkedIn URL.

Frequently asked questions

Why does this only enrich 10 to 15 people a week instead of the whole longlist?
RocketReach searches are free, but every verified contact lookup costs a credit. The agent reads the full longlist for free, picks the strongest fits against your role brief, and only spends credits on those. This keeps your monthly credit usage predictable.
Will it create duplicates in Bullhorn?
No. Before every contact lookup, the agent checks Bullhorn for an existing candidate with the same email or LinkedIn URL. Matches are skipped and called out in the Monday Slack digest as already in your ATS.
Can I use this without Bullhorn?
This template is built around Bullhorn because it is what we currently support for candidate creation. If you use a different ATS, you can still use the sourcing and shortlisting half of the workflow and adapt the final step to email or a shared sheet.
How do I update my role brief or filters?
Open the workflow after creation and edit the prompt config. Title, seniority, skills, location, and target employers are all plain text fields. The next Monday run picks up your changes automatically.
Does this contact candidates for me?
No. It builds a clean, deduped shortlist with verified contact details inside Bullhorn so you can run outreach yourself in whatever tone and sequencing your team uses.

Stop spending Monday morning sourcing from scratch.

Connect RocketReach, Bullhorn, and Slack once, and Geni delivers a fresh, vetted candidate shortlist into your ATS every Monday at 7am.