Agent skill
auto-research-public
Autonomous cold email campaign launcher.
Filed under Outbound email.
From growthenginenowoslawski/coldoutboundskills · 50 skills · 668 · pushed 2026-08-18
What it does when it runs
Autonomous cold email campaign launcher. Takes one target company domain, scrapes their website, generates an ICP with Claude, pulls matching leads via Prospeo, enriches emails + company descriptions, personalizes each lead with parallel Claude Code Task sub-agents (A/B/C variants), and uploads as a live Smartlead campaign. Uses local JSON files for state (no database required). Use for automated daily campaign launches after you have an initial `client-profile.yaml` from /icp-onboarding. Triggers on "auto-research", "launch an automated campaign", "daily campaign", "run the research loop".
Read from the skill and the 4 files bundled beside it. A skill’s own description is written to be selected by an agent, so it describes the job and not the dependencies.
- Keys and connectors you must supply
- API_KEY
- MILLIONVERIFIER_API_KEY
- MV_KEY
- PROSPEO_API_KEY
- PROSPEO_KEY
- SMARTLEAD_API_KEY
- Hosts it reaches
- api.millionverifier.com
- api.prospeo.io
- server.smartlead.ai
- Tool permissions it declares
- No
allowed-toolsin the frontmatter. It does act, so it runs under whatever permissions your session already grants. - Actions present in the files
- shellwrites filesnetwork
Install it
View source on GitHub ↗git clone --depth 1 --filter=blob:none --sparse https://github.com/growthenginenowoslawski/coldoutboundskills.git /tmp/coldoutboundskills git -C /tmp/coldoutboundskills sparse-checkout set "skills/auto-research-public" mkdir -p ~/.claude/skills/auto-research-public cp -R "/tmp/coldoutboundskills/skills/auto-research-public/." ~/.claude/skills/auto-research-public/
Picked up without a restart. A project skill of the same name is shadowed by your personal one. For one repository only, swap ~/.claude/skills for .claude/skills. Claude Code docs ↗
The folder is the same in every client that implements the format — 46 of them — so if yours is not above, only the destination changes.
Before you install: this skill will not complete its job on a bare agent. It needs API_KEY, MILLIONVERIFIER_API_KEY, MV_KEY, PROSPEO_API_KEY, PROSPEO_KEY, SMARTLEAD_API_KEY, which you have to obtain separately.
The skill
Source on GitHub ↗Reproduced in full from growthenginenowoslawski/coldoutboundskills/blob/f24320d4ab3ddb717402a065a3679aca5a7a8665/skills/auto-research-public/SKILL.md, which is licensed MIT (repository). 1,409 words, 22 headings.
Auto Research (Public)
Automated end-to-end campaign launcher. Feed it one target company domain, get back a live Smartlead campaign with per-lead personalization — in about 20 minutes.
This is the beginner-friendly version of the GEX internal auto-research-v2. All state lives in local JSON files; no Supabase, no Trigger.dev.
What you get
- Input: one target company domain + your
client-profile.yaml - Output: a running Smartlead campaign with:
- 200-1,000 leads (depending on targeting tightness)
- Per-lead personalization: 9 custom variables (situation, value, CTA × 3 variants)
- A/B/C subject + body variants tested in parallel
- Campaign assigned to your available inboxes
- Schedule: Mon-Fri 8am-5pm your timezone
Prerequisites
Before running:
-
client-profile.yamlexists (run/icp-onboardingif not) -
SMARTLEAD_API_KEYin env -
PROSPEO_API_KEYin env -
MILLIONVERIFIER_API_KEYin env (for email validation) - At least 20 Smartlead inboxes tagged "active" (run
/smartlead-inbox-managerfirst) - At least 1 campaign template in Smartlead (or the script creates a fresh one)
The orchestration (Claude Code runs this)
Unlike the other skills, this skill orchestrates through the Claude Code conversation itself — Claude does the reasoning (ICP generation, copy writing, personalization), and phase scripts do the heavy API I/O. This is the pattern from the GEX v2 internal.
Phase 1: Scrape the target company
npx tsx scripts/phase-scrape.ts --domain=<target.com> --out=/tmp/auto/scrape.json
Output: JSON with domain + text content from homepage, /about, /product, /pricing, /customers.
Claude reads the output and writes a short analysis to /tmp/auto/company-analysis.md:
- What the company does
- Who their likely customers are
- Social proof signals
- Potential angles for outreach
Phase 2: Claude generates ICP filters
Reading /tmp/auto/scrape.json + ~/cold-email-ai-skills/profiles/<slug>/client-profile.yaml, Claude writes Prospeo filters to /tmp/auto/filters.json:
{
"job_titles": ["VP Marketing", "Head of Marketing", ...],
"seniorities": ["Vice President", "Head", "Director"],
"industries": ["Software Development", "Financial Services"],
"company_size_min": 50,
"company_size_max": 500,
"countries": ["US"],
"excluded_industries": ["Religious Institutions", "Government Administration"]
}
Claude MUST use exact Prospeo industry names from ~/cold-email-ai-skills/skills/icp-onboarding/references/prospeo-industries.md.
Phase 3: Prospeo search
npx tsx scripts/phase-prospeo.ts --filters-file=/tmp/auto/filters.json --max-leads=1000 --out=/tmp/auto/leads.json
Output: JSON with leads array. Each lead has: first_name, last_name, email (may be empty), linkedin_url, job_title, company_name, company_domain, company_industry, company_headcount, company_description.
Phase 4: Email waterfall + description enrichment
npx tsx scripts/phase-enrich.ts --leads-file=/tmp/auto/leads.json --out=/tmp/auto/enriched.json
The script:
- Checks each lead for email; if missing, hits Prospeo's
enrich-personendpoint - If company_description is thin (<50 chars), scrapes company_domain homepage
- Runs MillionVerifier on every candidate email
- Writes enriched leads (only those with valid email) to output
Expect hit rates:
- Retail/SMB: ~99% email found
- B2B tech: ~65-80%
- Healthcare/public sector: ~25-40%
- MV rejection: ~20-30% of found emails
Phase 5: Copy writing (Claude)
Claude generates 3 copy variants (A, B, C) and writes to /tmp/auto/variants.json:
[
{
"variant": "A",
"subject": "<concrete, specific, <60 chars>",
"angle": "<pain observation>",
"body_template": "Hi {{first_name}},\n\n{{situation_line_a}}\n\n{{value_line_a}}\n\n{{cta_line_a}}\n\n%signature%\n\nP.S. If this isn't relevant, just let me know and I won't reach out again."
},
{
"variant": "B",
"subject": "<different angle>",
"angle": "<compliment + transition>",
"body_template": "..."
},
{
"variant": "C",
"subject": "<third angle>",
"angle": "<question>",
"body_template": "..."
}
]
Rules Claude MUST follow (run /spam-word-checker on output):
- No em dashes (—). Use commas or periods.
- No "leverage", "synergy", "solutions", "world-class", "cutting-edge".
- Body: 50-90 words max.
- Subject: under 60 chars, specific, no clickbait.
- End with
%signature%on its own line.
Phase 6: Personalization via Task sub-agents
Claude fans out to parallel Task sub-agents (one per variant × batch of 20-30 leads). See /personalization-subagent-pattern for the full pattern.
Per lead, each sub-agent writes to /tmp/auto/personalization-<batch>-variant-<X>.json:
[
{
"lead_id": "...",
"situation_line": "One sentence about the company.",
"value_line": "One sentence connecting to our offer.",
"cta_soft": "One soft ask sentence."
}
]
After all sub-agents finish, Claude merges by lead_id into /tmp/auto/personalized.json. Each lead now has 9 personalization fields.
Phase 7: Upload to Smartlead
npx tsx scripts/phase-upload.ts \
--leads-file=/tmp/auto/personalized.json \
--variants-file=/tmp/auto/variants.json \
--domain=<target.com> \
--inboxes-tag=active \
--inbox-count=10 \
--activate
This script:
- Creates a new Smartlead campaign named
[AUTO] <date> <target> Auto - Saves the 3-variant sequence with campaign-ID-scoped custom vars (
{{situation_line_a_{campaign_id}}}) - Selects N inboxes tagged "active" from Smartlead (LRU — least recently used first)
- Uploads leads in batches of 100 with custom fields mapped to their personalization
- Sets schedule (Mon-Fri 8am-5pm EST) and settings (tracking off, stop on reply)
- Activates the campaign
Outputs: { campaignId, inboxCount, leadsUploaded } to stdout.
Phase 8: Save experiment state (local JSON)
Write to ~/cold-email-ai-skills/profiles/<slug>/experiments/<YYYY-MM-DD>-<target>.json:
{
"date": "2026-04-17",
"target_domain": "example.com",
"smartlead_campaign_id": 123456,
"inboxes_assigned": [...],
"icp_filters": {...},
"variants": [...],
"lead_count_uploaded": 347,
"launched_at": "2026-04-17T14:23:00Z",
"status": "launched"
}
This is your experiment log. /experiment-design reads from here to compare runs. /positive-reply-scoring writes results back to this file after 21 days.
Running the full loop
To run all 8 phases in one command (with Claude orchestrating):
/auto-research-public --domain=<target.com>
Claude Code will execute each phase in order, pausing before phase 5 (copy) and phase 7 (upload) so you can review.
Daily / scheduled runs
Once comfortable, wrap it in a cron or use Claude Code's /loop skill to run daily:
/loop 1d /auto-research-public --domain=$(cat /tmp/auto/next-target.txt)
You need a way to pick the next target each day. Options:
- Maintain a
targets.txtlist and pop one per day - Let Claude pick based on TAM research (see
/GEX:Full-TAM-Waterfallfor inspiration) - Rotate through a list of competitors/lookalikes
State files (local JSON, no database)
Everything the skill needs lives under ~/cold-email-ai-skills/profiles/<slug>/:
profiles/
<business-slug>/
client-profile.yaml # from /icp-onboarding
lead-magnets.md # from /lead-magnet-brainstorm
experiments/
2026-04-16-targetco.json # per-campaign experiment log
2026-04-17-othertarget.json
scores/
123456-2026-05-07.json # from /positive-reply-scoring
Inbox assignment (no Supabase)
The GEX v2 uses a Supabase table auto_research_inbox_assignments to track which inboxes are assigned to which campaigns (to spread load). This public version:
- Queries Smartlead for inboxes tagged "active"
- Pulls each inbox's
daily_sent_countas a proxy for "how recently used" - Sorts ascending, picks the first N (least-sent-today = least recently used)
- Records the assignment in the local experiment JSON (not a database)
Works for <1000 inboxes. If you scale beyond that, migrate to a real DB.
Common issues
- Prospeo INVALID_FILTERS — Usually "industry name not in the 256 list." Check
/icp-onboardingreferences/prospeo-industries.md for exact matches. - Low email hit rate — If <30%, your list is targeting hard-to-find people (niche titles, small companies). Widen ICP or accept the cost.
- Sub-agent personalization repetitive — If you see the same phrasing across leads, rerun that batch with a diversity prompt. See
/personalization-subagent-patternreferences/failure-modes.md. - Smartlead "inbox not allowed" on upload — Inbox is flagged/blocked. The script skips and continues.
- Campaign stuck at 0 sends — Check campaign schedule, inbox warmup status (via
/smartlead-inbox-manager list-health), and that leads actually uploaded.
Cost per run
Typical run (1 target, 1000 leads pulled):
- Prospeo search: ~40 pages × search = ~$0.20
- Prospeo enrich-person (email finding for ~500 leads missing email): ~$5
- MillionVerifier validation: ~$0.50
- Smartlead send cost: ~$0.001/email sent over time
- Claude Code Task sub-agents: (uses your Claude Code plan — no extra API spend)
Total: ~$6-10 per campaign to reach 300-500 valid emails.
Scripts
scripts/phase-scrape.ts— website scrapescripts/phase-prospeo.ts— Prospeo paginated searchscripts/phase-enrich.ts— email waterfall + description enrichment + MillionVerifierscripts/phase-upload.ts— Smartlead campaign creation + uploadscripts/_lib.ts— shared API helpers
References
references/orchestration-checklist.md— full step-by-step for running the loop manuallyreferences/icp-to-prospeo.md— how to translate client-profile.yaml into Prospeo filter JSONreferences/copy-variant-guide.md— how to write 3 distinct A/B/C variants
What to do next
Wait 21 days for the campaign to accumulate reply data, then run /positive-reply-scoring on the launched campaign.
Meanwhile: continue the weekly rhythm via /cold-email-weekly-rhythm. Every Monday, /email-deliverability-audit on the new campaign to catch infrastructure issues early.
Or wait: this skill IS the automation loop. Next action can be "run again tomorrow with a different target domain" or integrate with /schedule skill to run daily.
Related skills
/icp-onboarding— produces client-profile.yaml (required input)/lead-magnet-brainstorm— produces the offer/CTA this campaign asks about/personalization-subagent-pattern— the fan-out pattern used in phase 6/smartlead-inbox-manager— must run BEFORE so inboxes are tagged/warmed/positive-reply-scoring— run AFTER 21 days to score the campaign/experiment-design— how to plan which target to try next
Files bundled with it
These load only when the skill asks for them, so they cost nothing until it runs.
Other skills for the same job
Different authors, same problem. Matched on the words in the skill name, across every library in the catalogue except this one.
- customer-research by coreyhaines31 · 46,928
- public-relations by coreyhaines31 · 46,928
- geo-content-research by onvoyage-ai · 1,299
- reddit-opportunity-research by onvoyage-ai · 1,299
- research-brand by onvoyage-ai · 1,299
- research-keywords by onvoyage-ai · 1,299
- sales-research by zubair-trabzada · 1,093
- domain-research by OpenClaudia · 677
Need help setting it up?
This page tells you what auto-research-public does and what it needs. Cheetah builds the agent setup it runs inside: data, CRM, sequencing and the guardrails.
Book a call →The directory stays free. There is nothing gated behind this.