lead-qualification

Lead qualification engine with conversational intake. Asks structured questions to understand your qualification criteria, generates a reusable qualification prompt, then batch-enriches leads via Apify LinkedIn scraping and scores them with parallel processing. Outputs qualified/disqualified verdicts with confidence scores and reasoning to Google Sheets (via Rube) or CSV. Supports calibration mode for prompt refinement.

381 stars

Best use case

lead-qualification is best used when you need a repeatable AI agent workflow instead of a one-off prompt.

Lead qualification engine with conversational intake. Asks structured questions to understand your qualification criteria, generates a reusable qualification prompt, then batch-enriches leads via Apify LinkedIn scraping and scores them with parallel processing. Outputs qualified/disqualified verdicts with confidence scores and reasoning to Google Sheets (via Rube) or CSV. Supports calibration mode for prompt refinement.

Teams using lead-qualification should expect a more consistent output, faster repeated execution, less prompt rewriting.

When to use this skill

  • You want a reusable workflow that can be run more than once with consistent structure.

When not to use this skill

  • You only need a quick one-off answer and do not need a reusable workflow.
  • You cannot install or maintain the underlying files, dependencies, or repository context.

Installation

Claude Code / Cursor / Codex

$curl -o ~/.claude/skills/lead-qualification/SKILL.md --create-dirs "https://raw.githubusercontent.com/gooseworks-ai/goose-skills/main/skills/capabilities/lead-qualification/SKILL.md"

Manual Installation

  1. Download SKILL.md from GitHub
  2. Place it in .claude/skills/lead-qualification/SKILL.md inside your project
  3. Restart your AI agent — it will auto-discover the skill

How lead-qualification Compares

Feature / Agentlead-qualificationStandard Approach
Platform SupportNot specifiedLimited / Varies
Context Awareness High Baseline
Installation ComplexityUnknownN/A

Frequently Asked Questions

What does this skill do?

Lead qualification engine with conversational intake. Asks structured questions to understand your qualification criteria, generates a reusable qualification prompt, then batch-enriches leads via Apify LinkedIn scraping and scores them with parallel processing. Outputs qualified/disqualified verdicts with confidence scores and reasoning to Google Sheets (via Rube) or CSV. Supports calibration mode for prompt refinement.

Where can I find the source code?

You can find the source code on GitHub using the link provided at the top of the page.

SKILL.md Source

# Lead Qualification Engine

Qualify leads against custom criteria through a structured intake process, then score lead lists in parallel with confidence ratings and reasoning.

## Three Modes of Operation

### Mode 1: Full Intake + Qualify
No existing qualification prompt. Run intake to build one, save it, then qualify leads.

**Trigger:** User provides no qualification prompt file.

### Mode 2: Reuse Prompt + Qualify
User references an existing qualification prompt file — skip intake, go straight to scoring.

**Trigger:** User tags or references a file in `skills/lead-qualification/qualification-prompts/`.

### Mode 3: Refine / Calibrate
User has seen results and wants to adjust criteria. Update the saved prompt, re-run.

**Trigger:** User says something like "refine", "adjust", "that's wrong", or provides feedback on qualification results.

---

## Phase 1: Intake (Mode 1 Only)

The goal is to build a complete picture of who the user considers qualified vs disqualified. Present questions in bulk rounds so the user can answer efficiently.

### Round 1 — Core Questions (Present All at Once)

Present these questions as a numbered list. Tell the user: *"Answer what's relevant, skip what's not. I'll follow up on anything I need to clarify."*

**Product & Campaign Context:**
1. What's your product/service in one sentence?
2. What problem does it solve and for whom?
3. What's the specific campaign or outreach angle? (e.g., "targeting companies that just raised Series A", "going after teams switching from Competitor X")

**Company-Level Criteria:**
4. What company sizes are you targeting? (e.g., 1-10, 11-50, 51-200, 201-1000, 1000+)
5. What industries or verticals are a good fit?
6. Any industries or company types to explicitly EXCLUDE?
7. Geographic targets? Or is this global?
8. Geographic exclusions?
9. Does company stage matter? (e.g., seed, Series A, Series B+, public)
10. Any revenue range or funding range that matters?

**Person-Level Criteria:**
11. What job titles or roles are your ideal buyers?
12. What titles are explicitly disqualified?
13. Does seniority level matter? (e.g., must be Director+, VP+, C-level)
14. What departments should they be in? (e.g., growth, marketing, sales, engineering)
15. Minimum tenure at current company? (e.g., 6+ months to have buying power)
16. Does total years of experience matter?

**Behavioral & Situational Signals:**
17. Are there tech stack signals that qualify or disqualify? (e.g., "uses Salesforce" = good fit)
18. Does recent company activity matter? (e.g., hiring spree, funding round, product launch)
19. Are there content/posting signals? (e.g., "posted about AI" = relevant)
20. Any other signals that indicate high intent or good fit?

**Dealbreakers & Instant Qualifiers:**
21. What are your HARD DISQUALIFIERS — things that instantly make someone a "no" regardless of other factors?
22. What are your STRONGEST QUALIFIERS — things that make someone an almost certain "yes"?

### Round 2 — Follow-Up Probes

Based on the user's answers, ask 5-10 targeted follow-ups to resolve ambiguity. Examples:
- "You said mid-market — does that mean 50-500 or 50-1000 employees?"
- "You mentioned VP of Growth — would a 'Head of Growth' also qualify, or only VP title?"
- "You didn't mention geography — should I treat this as global?"
- "For tenure, you said 6 months minimum. What about someone who's 4 months in but was promoted internally?"
- "You mentioned Series A companies. What about bootstrapped companies with equivalent revenue?"

### Round 3 — Edge Case Scenarios (Optional but Recommended)

Present 3-5 hypothetical lead profiles that test boundary cases. Ask "Would you qualify this person?"

Example scenarios to construct (adapt based on the user's criteria):
- Someone who fits the title but is at a company that's slightly too large/small
- Someone at the right company but with a borderline title
- Someone who matches on everything but has low tenure
- Someone who doesn't match the title exactly but has high intent signals
- Someone at a competitor's customer

This round catches implicit criteria the user hasn't articulated.

### Generate & Save Qualification Prompt

After intake is complete, synthesize all answers into a structured qualification prompt. Save it to:

```
skills/lead-qualification/qualification-prompts/[campaign-name].md
```

The saved prompt MUST follow this structure:

```markdown
# Qualification Prompt: [Campaign Name]

Generated: [date]

## Campaign Context
- **Product:** [one-liner]
- **Campaign Angle:** [specific angle]
- **Problem Solved:** [what and for whom]

## Hard Disqualifiers (Instant No)
- [list each with explanation]

## Hard Qualifiers (Instant Yes)
- [list each with explanation]

## Company Criteria
| Criterion | Qualified | Disqualified | Notes |
|-----------|-----------|--------------|-------|
| Size | [range] | [range] | |
| Industry | [list] | [list] | |
| Geography | [list] | [list] | |
| Stage | [list] | [list] | |
| Funding/Revenue | [range] | [range] | |

## Person Criteria
| Criterion | Qualified | Disqualified | Notes |
|-----------|-----------|--------------|-------|
| Titles | [list] | [list] | |
| Seniority | [level+] | [below level] | |
| Department | [list] | [list] | |
| Tenure | [minimum] | [below minimum] | |
| Experience | [range] | [range] | |

## Behavioral & Situational Signals
- [list signals that boost qualification]
- [list signals that reduce qualification]

## Confidence Rules
- **High Confidence:** Enough data available for company size, title, tenure, and at least one signal.
- **Medium Confidence:** Missing one or two non-critical data points but core criteria are clear.
- **Low Confidence:** Missing critical data points (e.g., no company size, unclear title). Still make a yes/no call but flag it.

## Edge Case Guidance
- [specific guidance derived from Round 3 scenarios]
- [any nuanced rules from the intake conversation]

## Qualification Reasoning Instructions
When evaluating a lead, structure your reasoning as:
1. Check hard disqualifiers first — if any match, immediately disqualify.
2. Check hard qualifiers — if any match, lean strongly toward qualifying.
3. Evaluate company criteria against thresholds.
4. Evaluate person criteria against thresholds.
5. Factor in behavioral/situational signals as tiebreakers.
6. Assign confidence based on data completeness.
7. Write 2-3 sentence reasoning summarizing the decision.
```

---

## Phase 2: Lead Qualification

### Step 1 — Parse Input

Accept any of these input formats:
- **Google Sheet URL** — Read via Rube MCP (`GOOGLESHEETS_GET_ALL_DATA_FROM_GOOGLE_SHEET` or similar)
- **CSV file path** — Read directly from filesystem
- **LinkedIn profile URLs** — One or more URLs provided inline
- **Inline list** — Names/companies listed in the message

Detect the format automatically. If it's a Google Sheet, use `RUBE_SEARCH_TOOLS` to find the right Google Sheets reading tool, then read the data.

### Step 1.5 — Batch Enrichment via Apify

**When:** The input contains a `linkedin_url` column (or LinkedIn URLs are available).
**Skip when:** No LinkedIn URLs are present, or the user explicitly says to skip enrichment.

Before LLM qualification, batch-enrich all leads to gather structured profile data. This is MUCH faster and cheaper than per-lead web searches during qualification.

**Run the enrichment script:**

```bash
python3 skills/lead-qualification/scripts/enrich_leads.py INPUT_CSV \
  --output ENRICHED_CSV \
  --cache-hours 24
```

Use `--dry-run` first to show the cost estimate without calling Apify.

**What this does:**
1. Reads all LinkedIn URLs from the input CSV
2. Checks local cache (24h default) — skips profiles already enriched
3. Sends uncached URLs to Apify in batches of 50
4. Returns enriched CSV with: `enriched_title`, `enriched_company`, `enriched_industry`, `enriched_location`, `enriched_connections`, `enriched_education`, `enriched_experience_years`, `enriched_headline`, `enriched_about`, `enrichment_status`
5. Cost: ~$3 per 1,000 profiles (~$0.03 per 100 leads)

**After enrichment, use the enriched CSV as input for Steps 2-4.** The enriched data lets the LLM qualification step work from structured fields instead of doing web searches, dramatically improving speed and consistency.

**If enrichment fails for some profiles:** They'll have `enrichment_status: failed` in the output. The LLM qualification step should fall back to web search for those leads only.

### Step 2 — Calibration Batch

Before processing the full list, run the first 5-10 leads and present results to the user in a table.

If batch enrichment was run (Step 1.5), use the enriched columns (`enriched_title`, `enriched_company`, etc.) as the primary data source. Only fall back to web search for leads where `enrichment_status` is `failed` or `no_url`.

```
| # | Name | Title | Company | Qualified | Confidence | Reasoning |
|---|------|-------|---------|-----------|------------|-----------|
| 1 | ... | ... | ... | Yes | High | ... |
| 2 | ... | ... | ... | No | Medium | ... |
| ... |
```

Ask: **"Do these look right? Should I adjust any criteria before processing the full list?"**

If the user flags issues:
1. Discuss what needs to change
2. Update the saved qualification prompt file
3. Re-run the calibration batch
4. Confirm again before proceeding

Repeat until the user approves.

### Step 3 — Full Run (Parallelized)

Once calibration is approved, process ALL remaining leads using parallel subagents. **You MUST parallelize — do NOT process leads sequentially.**

**Parallelization protocol (mandatory):**

1. **Calculate batch count:**
   - Total remaining leads / 15 = number of batches (round up)
   - Target: ~15 leads per batch
   - Minimum: 2 batches (even for small lists, to validate parallelism works)
   - Maximum: 10 concurrent batches (to avoid overwhelming context)

2. **Prepare batch inputs:**
   For each batch, create a self-contained context package:
   - The full qualification prompt (from `qualification-prompts/` file)
   - The batch of lead rows (with ALL columns including enriched data from Step 1.5)
   - Instructions for output format: Name, Qualified (Yes/No), Confidence (High/Medium/Low), Reasoning (2-3 sentences)
   - Instruction: "For leads with `enrichment_status=failed` or `no_url`, do a quick web search. Spend no more than 30 seconds per lead on search."

3. **Launch parallel Task agents:**
   Use the Task tool to launch ALL batches simultaneously in a single message with multiple tool calls:

   ```
   Task: "Qualify leads batch 1/N"
   Context: [qualification prompt] + [batch 1 lead rows]

   Task: "Qualify leads batch 2/N"
   Context: [qualification prompt] + [batch 2 lead rows]

   ... (launch ALL at once — do NOT wait for batch 1 before launching batch 2)
   ```

4. **Collect and merge results:**
   - Wait for all Task agents to complete
   - Merge all batch results into a single list
   - Preserve original row order from the input
   - If any batch fails, retry that batch once. If it fails again, flag those leads as "qualification_failed" and proceed.

5. **Validate completeness:**
   - Count: total qualified + disqualified + failed = total input leads
   - If any leads are missing, identify and re-process them

**Per-lead processing (within each batch agent):**
1. Read all available data from the input row (including enriched columns from Step 1.5)
2. If enriched data is present (`enrichment_status: success` or `cached`): use `enriched_title`, `enriched_company`, etc.
3. If enriched data is missing (`enrichment_status: failed` or `no_url`): do a quick web search (max 30 seconds)
4. Apply the qualification prompt:
   - Check hard disqualifiers first — if any match, immediately disqualify
   - Check hard qualifiers — if any match, lean strongly toward qualifying
   - Evaluate all criteria
   - Determine: Qualified (Yes/No), Confidence (High/Medium/Low)
   - Write 2-3 sentence reasoning
5. Return the result

### Step 4 — Output to Google Sheet

**Primary: Google Sheets via Rube MCP**

Use `RUBE_SEARCH_TOOLS` to find Google Sheets tools, then:

1. Create a new Google Sheet named: `[Campaign Name] - Qualified Leads - [Date]`
2. Write all original columns PLUS three new columns:
   - `Qualified` — Yes / No
   - `Confidence` — High / Medium / Low
   - `Reasoning` — 2-3 sentence explanation
3. Format the sheet:
   - Bold header row with dark background
   - Color-code the Qualified column: green for Yes, red for No
   - Color-code Confidence: green for High, yellow for Medium, red for Low
   - Auto-size columns for readability
   - Add a filter row so the user can filter by Qualified/Confidence
4. Present the Google Sheet link to the user

**Fallback: CSV**

If Rube MCP is unavailable or Google Sheets connection fails:
1. Write a CSV to: `skills/lead-qualification/output/[campaign-name]-[date].csv`
2. Include all original columns + Qualified, Confidence, Reasoning
3. Tell the user the file path

### Step 5 — Summary

After output is complete, present a summary:

```
## Qualification Results: [Campaign Name]

**Total leads processed:** X
**Qualified:** X (Y%)
**Disqualified:** X (Y%)

**Confidence breakdown:**
- High: X leads
- Medium: X leads
- Low: X leads (may need manual review)

**Top disqualification reasons:**
1. [reason] — X leads
2. [reason] — X leads
3. [reason] — X leads

**Output:** [Google Sheet link or CSV path]
**Qualification prompt saved to:** skills/lead-qualification/qualification-prompts/[campaign-name].md
```

---

## Tools Required

The qualification agent should have access to:

- **Apify LinkedIn Enrichment** — `scripts/enrich_leads.py` for batch profile enrichment before qualification
  - Uses `supreme_coder~linkedin-profile-scraper` Apify actor ($3/1k profiles, no cookies)
  - Requires `APIFY_API_TOKEN` environment variable
  - Run with `--dry-run` first to preview cost
- **Web Search** — to research leads when enrichment data is sparse or missing
- **Fetch (web page)** — to pull LinkedIn profiles, company pages, etc.
- **Rube MCP** — for Google Sheets input/output
  - `RUBE_SEARCH_TOOLS` — discover available tools
  - `RUBE_MANAGE_CONNECTIONS` — ensure Google Sheets connection is active
  - `RUBE_REMOTE_WORKBENCH` — execute sheet operations
- **Task tool** — to parallelize lead processing across subagents (mandatory for Step 3)
- **Read/Write** — for CSV I/O and saving qualification prompts
- **Glob/Grep** — to find existing qualification prompt files

---

## Example Usage

### Full intake + qualify from Google Sheet:
```
Qualify leads for our outbound campaign. Here's the lead list: [Google Sheet URL]
```
→ Agent detects no saved prompt, starts intake, builds prompt, then qualifies.

### Reuse existing prompt:
```
Qualify these leads using @skills/lead-qualification/qualification-prompts/series-a-founders.md
— lead list: [Google Sheet URL]
```
→ Agent skips intake, goes straight to calibration + qualification.

### Qualify LinkedIn profiles directly:
```
Using the series-a-founders qualification prompt, qualify these people:
- https://linkedin.com/in/person1
- https://linkedin.com/in/person2
- https://linkedin.com/in/person3
```

### Refine after seeing results:
```
Those results look off — also disqualify anyone at a consulting firm, and lower the
tenure minimum to 3 months for Director+ titles.
```
→ Agent updates the saved prompt and re-runs.

Related Skills

lead-discovery

381
from gooseworks-ai/goose-skills

Orchestrator that runs first for lead generation requests. Gathers business context via website analysis or questions, identifies competitors, builds ICP, and routes to signal skills with pre-filled inputs.

leadership-change-outreach

381
from gooseworks-ai/goose-skills

End-to-end leadership change signal composite. Takes any set of companies, detects recent leadership changes (new VP+, C-suite hires and promotions), evaluates relevance to your product, and drafts personalized outreach. Uses Apollo People Search (free) for fast detection + Apollo Enrichment (1 credit/person) for employment history, start dates, LinkedIn URLs, and verified emails.

inbound-lead-triage

381
from gooseworks-ai/goose-skills

Triages all inbound leads from a given period — demo requests, free trial signups, content downloads, webinar registrations, chatbot conversations. Classifies by urgency, qualifies against ICP, enriches with context, and produces a prioritized action queue with recommended response for each lead. Tool-agnostic — works with any CRM, form tool, or lead source.

inbound-lead-qualification

381
from gooseworks-ai/goose-skills

Qualifies inbound leads against full ICP criteria — company size, industry, use case fit, role/seniority of the person. Checks CRM and existing customer base for duplicates and existing relationships. Outputs a scored CSV with qualification status, reasoning, and pipeline overlap flags. Tool-agnostic — works with any CRM, enrichment tool, or data source.

inbound-lead-enrichment

381
from gooseworks-ai/goose-skills

Fills in missing data for inbound leads — researches the company, identifies the person's role and seniority, finds other stakeholders at the company, checks for existing CRM relationships, and updates the lead record. Produces enriched lead data ready for qualification or outreach. Tool-agnostic.

get-qualified-leads-from-luma

381
from gooseworks-ai/goose-skills

End-to-end lead prospecting from Luma events. Searches Luma for events by topic and location, extracts all attendees/hosts, qualifies them against a qualification prompt, outputs results to a Google Sheet, and sends a Slack alert with top leads. Use this skill whenever someone wants to find qualified leads from events, prospect event attendees, or run an event-based lead gen workflow. Also triggers for "find people at events and qualify them" or "who's attending X events that matches our ICP."

disqualification-handling

381
from gooseworks-ai/goose-skills

Handles disqualified and near-miss inbound leads gracefully. Drafts polite rejection emails, referral requests (right company wrong person), and nurture routing (future fit). Ensures no inbound lead gets ignored and every disqualification preserves the relationship. Tool-agnostic.

apollo-lead-finder

381
from gooseworks-ai/goose-skills

Two-phase Apollo.io prospecting: free People Search to discover ICP-matching leads, then selective enrichment to reveal emails/phones (credits per contact). Creates Apollo lists. Deduplicates against Supabase.

signal-detection-pipeline

381
from gooseworks-ai/goose-skills

Detect buying signals from multiple sources, qualify leads, and generate outreach context

seo-content-engine

381
from gooseworks-ai/goose-skills

Build and run an SEO content engine: audit current state, identify gaps, build keyword architecture, generate content calendar, draft content.

outbound-prospecting-engine

381
from gooseworks-ai/goose-skills

End-to-end outbound prospecting: detect intent signals, research companies, find decision-maker contacts, personalize messaging, launch campaign.

event-prospecting-pipeline

381
from gooseworks-ai/goose-skills

Find attendees at conferences/events, research their companies, qualify against ICP, and launch outreach