personalize-email
Skill0 starsChanged 4 months agoMITView on GitHub
Assemble a personalization signal pack for one prospect so a downstream LLM can compose a tailored email. Resolves the prospect, pulls company firmographics + recent business events + funding + workforce trends + LinkedIn posts + website changes + intent topics, and attaches the prospect's role context and LinkedIn activity. Returns a structured brief (signal ladder, recency stamps, anchor candidates, persona cues, proof hooks) ready to drop into a cold outbound, follow-up, re-engagement, renewal, expansion, or objection-handling email prompt. Use for sales prospecting, lead generation, account-based selling, signal-led outreach, B2B prospecting. Triggers on phrases like "personalize an email", "draft outreach", "outbound to X", "follow up on this prospect", "find a hook for this contact", "build me a personalization brief", "what should I say to this lead".
1 other project uses a version of this, 1 of them edited.
Adopted by
Most recently taken up by
- explorium-ai/gtm-skillsedited, first seen Oct 8, 2026
Other versions1 project uses a version of this.
Word for word · 0
None found.
Edited · 1
- explorium-ai/gtm-skills★ 34637% same
Wrote their own version · 0
None found.
How matches are found. Word for word: the exact same text. Edited: shares passages with this file (“99% same” means 99% of its five-word phrases also appear here; 10% or more counts). Their own version: similar meaning, or, weakest, the same name. We can’t tell which project had it first. Projects are counted among the 200 most-starred candidates, and mentions are links to the repository we found, up to 50 per site, so both counts are a floor.
In this repositoryOne other file it gives its agents.
- llms.txtllms.txt
The file
Show its rules and text
We split this skill into the rules it gives an agent
17 rules. About 0 are common, 1 is distinctive, and 16 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈1
Distinctive · estimate
This author's own choices. Worth a look.
16
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Very specific: line 13
Use case (default cold_outbound): one of cold_outbound, discovery_follow_up, demo_recap, re_engagement, renewal, expansion, …
- Very specific: line 23
If LinkedIn URL or email is supplied, call match-prospects with that identifier.
- Very specific: line 30
If the user named an industry, run autocomplete linkedin_category (or naics_category when they used a NAICS label) and show top 3 to 5 …
- Very specific: line 31
If they named a city, run autocomplete city_region.
- Very specific: line 32
Wait for the user to pick before filtering.
- Very specific: line 35
Create a session id (capture as <sid>) and seed a businesses table (e.g.
- Very specific: line 36
Call enrich-business --session-id <sid> --table-name outreach_company --type firmographics.
- Very specific: line 40
Call 1: enrich-business --session-id <sid> --table-name outreach_company --type funding-and-acquisitions workforce-trends linkedin-posts …
- Very specific: line 41
Call 2: enrich-business --session-id <sid> --table-name <view_from_call_1> --type website-changes challenges strategic-insights (new …
- Very specific: line 42
Call 3 (conditional): enrich-business --session-id <sid> --table-name <view_from_call_2> --type technographics competitive-landscape - …
- Very specific: line 56
Use case fit: cold_outbound and re_engagement lean on fresh external events.
- Very specific: line 68
If cold_outbound or re_engagement and zero events pass the recency floor and zero relevant prospect posts exist, mark signal_layer: thin …
- Very specific: line 69
If discovery_follow_up, demo_recap, or renewal and no prior touchpoint summary was supplied, surface the gap and ask the user for the …
- Very specific: line 70
If the prospect's profile last update is older than 12 months or the resolved company_name does not match the user-named company, add …
- Distinctive: line 131
No sort by signal recency at the API level.
- Very specific: line 132
No metro taxonomy; location filtering relies on city_region (autocomplete) plus company_country_code only.
- Very specific: line 133
No similar-companies tool.
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Personalize Email
Gather every personalization signal for a single prospect and their company so the calling model can write a sharp, specific email.
Input
- Prospect identifier (required): full name + company OR full name + company domain OR LinkedIn URL OR email.
- Use case (default
cold_outbound): one ofcold_outbound,discovery_follow_up,demo_recap,re_engagement,renewal,expansion,objection_handling. Drives which signals matter most. - Recency floor (optional): days. Defaults: 14 for intent topics, 30 for executive moves, 90 for company events.
- Sender / offering note (optional): one line on what the user sells, used only to rank signals; never sent to a model that drafts the email here.
- Prior touchpoint summary (optional, recommended for follow-ups, recaps, renewals): what was last discussed, when, who was involved.
This skill does NOT draft the email. It returns a structured brief; the calling model composes copy from it.
Workflow
- Resolve the prospect.
- If LinkedIn URL or email is supplied, call
match-prospectswith that identifier. - Otherwise call
match-businessfirst on the company name or domain to get abusiness_id, then callmatch-prospectswithfull_nameplus the resolvedbusiness_id(orcompany_domainpassed tomatch-prospects). - On miss, retry
match-prospectswith first+last instead of full name and the resolvedbusiness_id. Identity fields (full_name,first_name,last_name,company_name,company_domain) are inputs tomatch-business/match-prospects, never filters onfetch-entities. - Resolve-by-role path (no name supplied, e.g. "CFO at Notion", "CISO at Salesforce"):
match-prospectswithfull_name="CFO"returns 0 silently and is the wrong path. Instead callfetch-entitieswithentity_type: prospects,--businesses-table-name <match_business_table>, and ajob_titlefilter (autocomplete-resolved) plusjob_levelfilter. This is the dominant cold-outbound use case when the user knows the seat but not the person. - Capture
prospect_id,business_id,full_name,job_title,linkedin_url. If noprospect_idor nobusiness_idresolves, stop and surface the gap. Sanity check after firmographics lands in step 3: if the resolved business_id's firmographics show a major-brand input but headcount is 1-50 and NAICS is551114(Corporate Managing Offices) or SIC isHotels and motels, the match likely routed to a registered-agent shell entity. Re-try with the alternate domain (.so vs .com) or with the company name string. Do not proceed with the wrong business_id.
- If LinkedIn URL or email is supplied, call
- Confirm autocomplete-gated values before any filtered company pull.
- If the user named an industry, run
autocomplete linkedin_category(ornaics_categorywhen they used a NAICS label) and show top 3 to 5 matches. - If they named a city, run
autocomplete city_region. - Wait for the user to pick before filtering. Use
company_country_codedirectly with no autocomplete.
- If the user named an industry, run
- Pull firmographics for the company.
- Create a session id (capture as
<sid>) and seed a businesses table (e.g.outreach_company) from the step-1match-businessresolution. - Call
enrich-business --session-id <sid> --table-name outreach_company --type firmographics. Capturecompany_name,company_domain,linkedin_category,company_size,headcount,company_revenue,revenue_range, headquarters location, company_age.
- Create a session id (capture as
- Pull recent company signals in chunked calls (max 3 enrichments per call).
- Reuse the same
--session-id <sid>and pass--table-name outreach_companyon the first call.enrich-businessaccepts at most 3 enrichments per call. Capture the newtable_namereturned by each call (a freshview_<hash>); thread THAT new table forward into the next enrich/events/export call, NOT the originalmatch-businesstable. Each enrich call produces a new view table; the original fetch/match table does not get the enrichment columns. - Call 1:
enrich-business --session-id <sid> --table-name outreach_company --type funding-and-acquisitions workforce-trends linkedin-posts(rounds/M&A/IPO chatter, hiring surges/layoffs/department growth, recent posts). - Call 2:
enrich-business --session-id <sid> --table-name <view_from_call_1> --type website-changes challenges strategic-insights(new product pages/pricing/careers, stated challenges, stated priorities). - Call 3 (conditional):
enrich-business --session-id <sid> --table-name <view_from_call_2> --type technographics competitive-landscape-technographicsonly if the offering note implies a tech-stack-relevant pitch;competitive-landscapeonly when the use case isobjection_handlingor the offering note flags a competitive displacement. fetch-businesses-events --session-id <sid> --table-name <latest_view>and scope the events filter to the last 90 days. Keep every event with a date; drop ones older than the recency floor for the use case.
- Reuse the same
- Pull the prospect's own context. Seed a prospect-side table (e.g.
outreach_prospect) from thematch-prospectsstep in step 1; every call below must spell out--session-id <sid> --table-name outreach_prospect.enrich-prospects --session-id <sid> --table-name outreach_prospect --type profilesto get seniority, department, tenure, prior roles.- Prospect-side recent posts are not available via enrich-prospects. Pull
enrich-business --session-id <sid> --table-name outreach_company --type linkedin-postsinstead for the employer's recent voice; for the individual prospect's posting voice, document this as a current gap. enrich-prospects --session-id <sid> --table-name outreach_prospect --type contacts --contact-types emailonly when the user intends to send the email and needsemail. Cost is ~2 credits per row (email-only) vs ~5 credits per row (email + phone). Switch to--contact-types email phoneonly when phone numbers are required (e.g. SDR dialer flows). Skip the call entirely otherwise.fetch-prospects-events --session-id <sid> --table-name outreach_prospectfor job-change or promotion events on this person.
- Score and rank the signals.
- Stamp every signal with age in days and a source tag (event, post, funding round, website change, intent topic, role change).
- Score
recency_weightxpersona_relevancexuse_case_fit:- Recency: 0 to 14d = 1.0, 15 to 30d = 0.7, 31 to 60d = 0.4, 61 to 90d = 0.2, older = drop.
- Persona relevance: CFO maps to funding / earnings / M&A; CRO and VP Sales map to hiring surges, product launches, go-to-market posts; CTO and VP Eng map to website changes, technographics, engineering hires; CEO maps to all.
- Use case fit:
cold_outboundandre_engagementlean on fresh external events;discovery_follow_up,demo_recap,renewal,expansionlean on the prior touchpoint plus role / company posts;objection_handlingleans on competitive-landscape and strategic-insights.
- Rank top 5. Mark the highest as
anchor_candidate; next asrunner_up.
- Build the persona cue block.
- From the profile pull: seniority, department, tenure in seat, prior employers (last 2).
- Tone hint by seat: executive (outcome first, numeric), director or manager (problem then approach then outcome), IC (workflow friction then concrete benefit).
- Pull 1 to 3 direct quotes or themes from the prospect's recent posts when available.
- Assemble the proof hook list.
- Pull company peers from
linkedin_category+company_sizeband as candidate look-alike framings. Do not invent customer names or stats. Only flag categories where the calling model could later plug in real customer proof from the user's own materials.
- Pull company peers from
- Flag gaps and refuse conditions.
- If
cold_outboundorre_engagementand zero events pass the recency floor and zero relevant prospect posts exist, marksignal_layer: thinand recommend the user warm via another channel before sending. - If
discovery_follow_up,demo_recap, orrenewaland no prior touchpoint summary was supplied, surface the gap and ask the user for the summary; do not fabricate one. - If the prospect's profile last update is older than 12 months or the resolved
company_namedoes not match the user-named company, addstale_record: trueand recommend verifying role.
- If
Output Format
TL;DR
One paragraph: prospect name, title, company, the single strongest anchor signal with age, and the persona-tone hint.
Prospect
| Field | Value |
| Full name | ... |
| Job title | ... |
| Company name | ... |
| Company domain | ... |
| LinkedIn URL | ... |
| prospect_id | ... |
| business_id | ... |
... (only if enrich-prospects --type contacts --contact-types email was called) |
Company snapshot
Two to four lines covering linkedin_category, company_size bucket, headcount, revenue_range, headquarters, founding year.
Signal ladder (ranked)
For each of the top 5:
- Rank, signal type, age in days, source tag.
- One-line description.
- Why it matters for this persona and use case.
- Anchor candidate / runner-up flag.
Persona cues
- Seniority, department, tenure in seat.
- Prior employers (last 2).
- Tone hint.
- Direct quotes or post themes (up to 3, with date).
Proof hook categories
List of peer-segment framings the calling model could plug real customer proof into. No invented stats, no invented logos.
Brief for the drafting model
A compact JSON-shaped block the calling model can read:
{
"anchor": "<signal type> (<age>d)",
"runner_up": "<signal type> (<age>d)",
"persona": { "seniority": "...", "department": "...", "tone": "..." },
"company": { "name": "...", "size": "...", "industry": "..." },
"use_case": "<chosen use case>",
"gaps": ["..."],
"do_not_invent": ["customer names", "stats not in this brief"]
}Flags
signal_layer: rich | moderate | thin.stale_record: true | false.missing_prior_touchpoint: true | false (only set for follow-up family use cases).competitor_mention_detected: true | false (from competitive-landscape pull).
Limitations
funding-and-acquisitionsenrichment has coverage gaps for late-stage privates that haven't filed an S-1. Notion returned all-null funding fields despite being a well-known ~$10B+ valuation. For CFO personas at private targets, lean onfetch-businesses-events(merger_and_acquisitions, new_funding_round, cost_cutting, hiring_in_finance_department) instead.- No sort by signal recency at the API level; ranking is done client-side after pulling events.
- No metro taxonomy; location filtering relies on
city_region(autocomplete) pluscompany_country_codeonly. - No similar-companies tool; peer framing falls back to
linkedin_category+company_sizeband. - Headcount and revenue come as buckets, not exact values.
- This skill does not draft email copy. The calling model writes subject lines and bodies from the brief.
- Per-prospect linkedin-posts is not available; surface this as a gap when the use case wants the individual prospect's posting voice.
job_departmentis null for many cross-functional senior roles (Chief X Officer, President, Founder). Group these under "Unattributed" in the persona cue block rather than dropping them.- Map raw
prospect_job_seniority_levelvalues to canonical filter values for display:cxo->c-suite,vp->vice president.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

