Email companies whose job posts show they need your product
Finds new job posts for roles you support with Exa, checks each for a real need or a competitor with Jev, and emails the hiring team.
Outcome
A table of every job post found, with the company, the role, whether it signals a need, the competitor it names and Jev's confidence.
The buyer at each company with a real need, with their work email.
An approved opening line for each buyer that points to the job post, queued in your lemlist campaign, or in your switching campaign when the post names a competitor.
How it works
- 1
Find job posts
ExaSearch each of
role_queriesonjob_boards, published in the lastlookback_days, with each page's text. Keep each post's URL, job title, company name, the company's own website domain when the post shows it, and the text; drop duplicates. - 2
Read each post
TypeSafe AISend the job title and text as the state, with a choice
signalof exact (the role that usescategoryor thatcategorywould replace), adjacent (a role that works alongsidecategory) and generic (a general hiring push unrelated tocategory), a noulnames_category(the post says the team will buy, build or runcategory), and a choicecompetitorovercompetitorsplus none. Keep every answer with its confidence or probability. - 3
Keep the real needs
Your agentKeep the posts whose signal is exact or whose
names_categoryis yes, one per company. Show the user the posts whose signal or competitor confidence is belowmin_confidenceor whosenames_categoryis unsure, and keep what the user decides. - 4
Find the domains
ExaFor each kept company whose post showed no domain, search company pages for its name. Keep the domains you can confirm, and drop the companies you can't.
- 5
Find the buyer
HunterSearch each kept company's domain, up to
max_lookups. Keep the person whose position best matchesbuyer_titles, with their name, position and email; list the companies with no match. - 6
Write the opening lines
Your agentDraft one sentence per buyer that names the role they are hiring for and the problem it hints at, with no pitch. Show the lines to the user.
- 7
Queue the emails
lemlist
After the user approves, add each buyer whose post named a competitor to
switch_campaign, and every other buyer tocampaign, with their approved line injob_post_line.
You'll be asked for
The job posts that signal a need, as searches
e.g. hiring first revenue operations manager; SDR team lead job
What your product does, in a buyer's words
e.g. sales engagement software
The tools a job post might name that you replace
e.g. Outreach, Salesloft
The job board domains to search
e.g. greenhouse.io, lever.co, ashbyhq.com
How recent a post counts
e.g. 14
How sure Jev must be before its answer is used without you
e.g. 0.8; a yes-or-no answer counts as yes at or above it and as no at or below 1 minus it
Who to email at each company
e.g. VP Sales, Head of Revenue Operations
The most company domains to search for a buyer in one run, since each search spends Hunter credits
e.g. 50
The lemlist campaign that sends the emails, set up once with a `job_post_line` custom variable
e.g. Hiring signal
The lemlist campaign for buyers whose post names a competitor, with copy about switching and the same `job_post_line` variable
e.g. Hiring signal: switching
The file your agent runs
hiring-signal-outbound.md
Email companies whose job posts show they need your product
Finds new job posts for roles you support with Exa, checks each for a real need or a competitor with Jev, and emails the hiring team.
Set up the tools below, then run the steps in order for the user, carrying each step's results into the next. The run is done when the user has the outcome below.
Outcome
- A table of every job post found, with the company, the role, whether it signals a need, the competitor it names and Jev's confidence.
- The buyer at each company with a real need, with their work email.
- An approved opening line for each buyer that points to the job post, queued in your lemlist campaign, or in your switching campaign when the post names a competitor.
Inputs
Ask the user for these before you start.
role_queries: the job posts that signal a need, as searches, e.g. hiring first revenue operations manager; SDR team lead jobcategory: what your product does, in a buyer's words, e.g. sales engagement softwarecompetitors: the tools a job post might name that you replace, e.g. Outreach, Salesloftjob_boards: the job board domains to search, e.g. greenhouse.io, lever.co, ashbyhq.comlookback_days: how recent a post counts, e.g. 14min_confidence: how sure Jev must be before its answer is used without you, e.g. 0.8; a yes-or-no answer counts as yes at or above it and as no at or below 1 minus itbuyer_titles: who to email at each company, e.g. VP Sales, Head of Revenue Operationsmax_lookups: the most company domains to search for a buyer in one run, since each search spends Hunter credits, e.g. 50campaign: the lemlist campaign that sends the emails, set up once with ajob_post_linecustom variable, e.g. Hiring signalswitch_campaign: the lemlist campaign for buyers whose post names a competitor, with copy about switching and the samejob_post_linevariable, e.g. Hiring signal: switching
Set up
Search the web (Exa, tool:exa/search-web)
Use the first option your agent supports.
Note: On MCP, domain, date and category filters need web_search_advanced_exa: list it in the server URL's tools parameter with every other tool you want, since the list replaces the defaults.
MCP (official, remote)
Add this server to your agent's MCP settings, then sign in when asked.
{ "mcpServers": { "exa": { "url": "https://mcp.exa.ai/mcp?login" } } }
Call the MCP tool web_search_exa.
API (official)
- Base URL: https://api.exa.ai
- Endpoint:
POST /search - Auth: send the header
Authorization: Bearer $EXA_API_KEY - Get a key: https://dashboard.exa.ai/api-keys
Answer typed questions (TypeSafe AI, tool:typesafe/answer-typed-questions)
Use the API.
- Base URL: https://api.typesafe.ai
- Endpoint:
POST /v1/systemone - Auth: send the header
Authorization: Bearer $TYPESAFE_API_KEY - Get a key: https://console.typesafe.ai
Note: Put every question about one record in one request. GET /v1/models lists the models and is the cheapest check of a key; a request over the rate limit gets a 429 with a Retry-After header.
Note: Send state, model (jev-latest) and named questions, each with type, instructions and criteria: a choice maps labels to descriptions, a score lists its levels in order, a noul's is optional. Read a score by its most likely level; send unsure answers to a person.
Search a domain for emails (Hunter, tool:hunter/search-domain)
Use the first option your agent supports.
Note: Returns 10 emails by default; page through the rest with limit and offset.
MCP (official, remote)
Add this server to your agent's MCP settings, then sign in when asked.
{ "mcpServers": { "hunter": { "url": "https://mcp.hunter.io/mcp" } } }
Call the MCP tool Domain-Search.
API (official)
- Base URL: https://api.hunter.io/v2
- Endpoint:
GET /domain-search - Auth: send the header
X-API-Key: $HUNTER_API_KEY - Get a key: https://hunter.io/api-keys
Add a lead to a campaign (lemlist, tool:lemlist/add-lead-to-campaign)
Use the first option your agent supports.
Note: The campaign automates outreach to its leads: confirm it first. findEmail, verifyEmail, findPhone and linkedinEnrichment spend credits, and a lead already in the campaign is refused with 400 LEAD_ALREADY_IN_CAMPAIGN.
CLI (official)
Install the command and sign in with it, then confirm it runs.
npm install -g @lemlist-official/cli
lemlist --version
Run lemlist api POST /campaigns/{campaignId}/leads/.
API (official)
- Base URL: https://api.lemlist.com/api
- Endpoint:
POST /campaigns/{campaignId}/leads/ - Auth: send the header
Authorization: Basic $LEMLIST_API_KEY - Get a key: https://app.lemlist.com/settings/integrations
Note: LEMLIST_API_KEY holds the base64 of :<api key>, an empty username and the key; 20 requests every 2 seconds per key.
Before step 1, confirm access to each service with its cheapest read-only call, like a list or a search. Never send or change anything to test access.
Steps
- Find job posts with Search the web (Exa). Search each of
role_queriesonjob_boards, published in the lastlookback_days, with each page's text. Keep each post's URL, job title, company name, the company's own website domain when the post shows it, and the text; drop duplicates. - Read each post with Answer typed questions (TypeSafe AI). Send the job title and text as the state, with a choice
signalof exact (the role that usescategoryor thatcategorywould replace), adjacent (a role that works alongsidecategory) and generic (a general hiring push unrelated tocategory), a noulnames_category(the post says the team will buy, build or runcategory), and a choicecompetitorovercompetitorsplus none. Keep every answer with its confidence or probability. - Keep the real needs yourself. Keep the posts whose signal is exact or whose
names_categoryis yes, one per company. Show the user the posts whose signal or competitor confidence is belowmin_confidenceor whosenames_categoryis unsure, and keep what the user decides. - Find the domains with Search the web (Exa). For each kept company whose post showed no domain, search company pages for its name. Keep the domains you can confirm, and drop the companies you can't.
- Find the buyer with Search a domain for emails (Hunter). Search each kept company's domain, up to
max_lookups. Keep the person whose position best matchesbuyer_titles, with their name, position and email; list the companies with no match. - Write the opening lines yourself. Draft one sentence per buyer that names the role they are hiring for and the problem it hints at, with no pitch. Show the lines to the user.
- Queue the emails with Add a lead to a campaign (lemlist). After the user approves, add each buyer whose post named a competitor to
switch_campaign, and every other buyer tocampaign, with their approved line injob_post_line.
Notes
The line points at the role the company is hiring for, not at your product; the campaign's own copy makes the pitch. Keep switch_campaign about what changes when a team moves off the competitor.
Run it weekly with lookback_days set to 7 so each post is seen once.
Rules
- Use only the services set up above. The read-only calls they need, like listing ids or polling for results, are fine.
- Ask the user before anything that sends messages, costs money, or changes data, and say how many records it touches. One approval covers a batch the user has seen.
- Never print API keys.
