Tell sales which new sign-ups fit your ideal customer
Reads new Clerk sign-ups, looks up each work domain with Apollo, scores fit and flags fakes with Jev, and saves the result in Attio.
Outcome
A table of every new sign-up with its company, fit level, bucket and Jev's confidence.
Each company behind a work email created or updated in Attio with its fit level and bucket.
A Slack post for each sign-up ready for a sales touch.
The suspicious, never-touch and competitor sign-ups, listed for you to review.
How it works
- 1
Pull new sign-ups
ClerkList the users who signed up after
since. Keep each user's ID, name, email and sign-up time. Set aside personal email domains such as gmail.com, and sign-ups whose email domain is incompetitors. - 2
Look up the companies
ApolloLook up each work email's domain once, up to
max_lookups. Keep each company's name, industry, employee count and funding rounds. - 3
Score them
TypeSafe AISend each sign-up's email, name and company facts as the state, with a score
fitwhose levels describe the match withideal_customer: no fit (matches none of it), weak (matches some), good (matches most) and ideal (matches all); a choicekindof business (signing up for their company), individual (trying it alone) and never_touch (a student or a fake); and a noulsuspicious(a disposable domain or a made-up name). Keep every answer with its confidence or probability. - 4
Bucket them
Your agentShow the user every sign-up whose kind or fit confidence is below
min_confidence, or whosesuspiciousis unsure, and keep what the user decides. Mark each business sign-up that is not suspicious sales_ready when its fit ismin_fitor better and its company has at leastsales_flooremployees, sales_assist when it fits but is smaller, and self_serve otherwise; individuals are self_serve. List the suspicious, never_touch and competitor sign-ups. - 5
Save the fit
AttioAfter the user approves, upsert each company by its domain with its most likely fit level and its bucket in
fit_attributes. - 6
Alert sales
SlackPost each sales_ready sign-up to
sales_channelwith the person, the company's name, size, industry and funding, and the fit level.
You'll be asked for
When the last run ended, so only newer sign-ups are read
e.g. 2026-09-28
Who you sell to, in a sentence or two
e.g. software teams of 20 or more at venture-backed or profitable companies
The email domains whose sign-ups never get a sales touch
e.g. rival.com, othertool.io
The smallest company worth a sales touch
e.g. 50 employees
The lowest fit level worth a sales touch
e.g. good
The most companies to look up in one run, since each costs an Apollo credit
e.g. 100
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
The Attio company attributes that hold the fit level and the bucket, created once
e.g. jev_fit and jev_bucket
The Slack channel for sales-ready sign-ups
e.g. #plg-leads
The file your agent runs
signup-fit-scoring.md
Tell sales which new sign-ups fit your ideal customer
Reads new Clerk sign-ups, looks up each work domain with Apollo, scores fit and flags fakes with Jev, and saves the result in Attio.
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 new sign-up with its company, fit level, bucket and Jev's confidence.
- Each company behind a work email created or updated in Attio with its fit level and bucket.
- A Slack post for each sign-up ready for a sales touch.
- The suspicious, never-touch and competitor sign-ups, listed for you to review.
Inputs
Ask the user for these before you start.
since: when the last run ended, so only newer sign-ups are read, e.g. 2026-09-28ideal_customer: who you sell to, in a sentence or two, e.g. software teams of 20 or more at venture-backed or profitable companiescompetitors: the email domains whose sign-ups never get a sales touch, e.g. rival.com, othertool.iosales_floor: the smallest company worth a sales touch, e.g. 50 employeesmin_fit: the lowest fit level worth a sales touch, e.g. goodmax_lookups: the most companies to look up in one run, since each costs an Apollo credit, e.g. 100min_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 itfit_attributes: the Attio company attributes that hold the fit level and the bucket, created once, e.g. jev_fit and jev_bucketsales_channel: the Slack channel for sales-ready sign-ups, e.g. #plg-leads
Set up
List users (Clerk, tool:clerk/list-users)
Use the first option your agent supports.
CLI (official)
Install the command and sign in with it, then confirm it runs.
npm install -g clerk
clerk --version
Run clerk users list.
API (official)
- Base URL: https://api.clerk.com/v1
- Endpoint:
GET /users - Auth: send the header
Authorization: Bearer $CLERK_SECRET_KEY - Get a key: https://dashboard.clerk.com/~/api-keys
Enrich a company (Apollo, tool:apollo/enrich-company)
Use the first option your agent supports.
Note: Costs 1 credit per company. To enrich up to 10 companies in one call, use bulk organization enrichment instead.
MCP (official, remote)
Add this server to your agent's MCP settings, then sign in when asked.
{ "mcpServers": { "apollo": { "url": "https://mcp.apollo.io/mcp" } } }
Call the MCP tool apollo_organizations_enrich.
CLI (official)
Install the command and sign in with it, then confirm it runs.
brew install apolloio/apollo-io-cli/apollo-io-cli
apollo --version
Run apollo companies enrich.
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.
Create or update a record (Attio, tool:attio/upsert-record)
Use the first option your agent supports.
Note: The matching_attribute must be a unique attribute. Deals have no unique attribute by default, so add one before upserting deals.
MCP (official, remote)
Add this server to your agent's MCP settings, then sign in when asked.
{ "mcpServers": { "attio": { "url": "https://mcp.attio.com/mcp" } } }
Call the MCP tool upsert-record.
API (official)
- Base URL: https://api.attio.com
- Endpoint:
PUT /v2/objects/{object}/records - Auth: send the header
Authorization: Bearer $ATTIO_API_KEY - Get a key: https://attio.com/help/reference/apps/generating-an-api-key
Post a message (Slack, tool:slack/post-message)
Use the first option your agent supports.
Note: Needs the chat:write scope. Over MCP it posts as the signed-in user; the API and CLI post as the app's bot.
MCP (official, remote)
Add this server to your agent's MCP settings, then sign in when asked.
{ "mcpServers": { "slack": { "url": "https://mcp.slack.com/mcp" } } }
Call the MCP tool slack_send_message.
CLI (official)
Install the command, then confirm it runs.
curl -fsSL https://downloads.slack-edge.com/slack-cli/install.sh | bash
slack --version
Run slack api chat.postMessage.
Set $SLACK_BOT_TOKEN in your environment first (get a key: https://api.slack.com/apps).
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
- Pull new sign-ups with List users (Clerk). List the users who signed up after
since. Keep each user's ID, name, email and sign-up time. Set aside personal email domains such as gmail.com, and sign-ups whose email domain is incompetitors. - Look up the companies with Enrich a company (Apollo). Look up each work email's domain once, up to
max_lookups. Keep each company's name, industry, employee count and funding rounds. - Score them with Answer typed questions (TypeSafe AI). Send each sign-up's email, name and company facts as the state, with a score
fitwhose levels describe the match withideal_customer: no fit (matches none of it), weak (matches some), good (matches most) and ideal (matches all); a choicekindof business (signing up for their company), individual (trying it alone) and never_touch (a student or a fake); and a noulsuspicious(a disposable domain or a made-up name). Keep every answer with its confidence or probability. - Bucket them yourself. Show the user every sign-up whose kind or fit confidence is below
min_confidence, or whosesuspiciousis unsure, and keep what the user decides. Mark each business sign-up that is not suspicious sales_ready when its fit ismin_fitor better and its company has at leastsales_flooremployees, sales_assist when it fits but is smaller, and self_serve otherwise; individuals are self_serve. List the suspicious, never_touch and competitor sign-ups. - Save the fit with Create or update a record (Attio). After the user approves, upsert each company by its domain with its most likely fit level and its bucket in
fit_attributes. - Alert sales with Post a message (Slack). Post each sales_ready sign-up to
sales_channelwith the person, the company's name, size, industry and funding, and the fit level.
Notes
Look up each company once, even when several people from it sign up, and say in the Slack post when several did. Sales-assist sign-ups suit a product-led nudge rather than a rep's time.
Run it daily with since set to the previous run.
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.
