skills/athina-ai/goose-skills/inbound-lead-qualification

inbound-lead-qualification

Originally fromnikiandr/goose-skills
SKILL.md

Inbound Lead Qualification

Takes a set of inbound leads and validates each against your full ICP criteria. Not a fast-pass triage (that's inbound-lead-triage) — this is the thorough qualification step that determines whether a lead is genuinely worth pursuing, and produces a scored CSV for the team.

When to Auto-Load

Load this composite when:

  • User says "qualify these inbound leads", "check if these leads are ICP", "score my inbound"
  • An upstream triage has been completed and leads need deeper qualification
  • User has a batch of leads and wants a qualified/disqualified verdict on each

Architecture

[Inbound Leads] → Step 1: Load ICP & Config → Step 2: CRM/Pipeline Check → Step 3: Company Qualification → Step 4: Person Qualification → Step 5: Use Case Fit → Step 6: Score & Verdict → Step 7: Output CSV

Step 0: Configuration (Once Per Client)

On first run, establish the ICP definition and CRM access. Save to clients/<client-name>/config/lead-qualification.json.

{
  "icp_definition": {
    "company_size": {
      "min_employees": null,
      "max_employees": null,
      "sweet_spot": "",
      "notes": ""
    },
    "industry": {
      "target_industries": [],
      "excluded_industries": [],
      "notes": ""
    },
    "use_case": {
      "primary_use_cases": [],
      "secondary_use_cases": [],
      "anti_use_cases": [],
      "notes": ""
    },
    "company_stage": {
      "target_stages": [],
      "excluded_stages": [],
      "notes": ""
    },
    "geography": {
      "target_regions": [],
      "excluded_regions": [],
      "notes": ""
    }
  },
  "buyer_personas": [
    {
      "name": "",
      "titles": [],
      "seniority_levels": [],
      "departments": [],
      "is_economic_buyer": false,
      "is_champion": false,
      "is_user": false
    }
  ],
  "hard_disqualifiers": [],
  "hard_qualifiers": [],
  "crm_access": {
    "tool": "Supabase | HubSpot | Salesforce | CSV export | none",
    "access_method": "",
    "tables_or_objects": []
  },
  "existing_customer_source": {
    "tool": "Supabase | CRM | CSV | none",
    "access_method": ""
  },
  "qualification_prompt_path": "path/to/lead-qualification/prompt.md or null"
}

If lead-qualification capability already has a saved qualification prompt: Reference it directly — don't rebuild ICP criteria from scratch.

On subsequent runs: Load config silently.


Step 1: Load ICP Criteria & Parse Leads

Process

  1. Load the client's ICP config (or qualification prompt from lead-qualification capability)
  2. Parse the inbound lead list — accept any format:
    • Output from inbound-lead-triage (already normalized)
    • Raw CSV with any column structure
    • Pasted list of names/emails/companies
    • CRM export
  3. Identify what data is available vs. missing per lead:
    • Have: Fields present in the input
    • Need: Fields required for qualification but missing
    • Gap report: "X leads have company name, Y have title, Z have nothing but email"

Output

  • Parsed lead list with available/missing field inventory
  • Gap report for the user

Human Checkpoint

If >50% of leads are missing critical fields (company name or person title), recommend running inbound-lead-enrichment first. Ask: "Many leads are missing company/title data. Want me to enrich them first, or qualify with what's available?"


Step 2: CRM & Pipeline Check

Process

For each lead, check against existing data sources to identify overlaps:

Check 1 — Existing customer?

  • Search customer database by company domain/name
  • If match found: Flag as existing_customer with customer details (plan, account owner, contract status)
  • This is NOT a disqualification — it's a routing flag (upsell vs. new business)

Check 2 — Already in pipeline?

  • Search CRM/Supabase for the company in active deals
  • If match found: Flag as in_pipeline with deal details (stage, owner, last activity)
  • Critical: Sales rep should know before reaching out that a colleague already has this account

Check 3 — Previous engagement?

  • Search outreach logs for the email/company
  • If match found: Flag as previously_contacted with history summary (when, what channel, outcome)

Check 4 — Known from signal composites?

  • Search Supabase signals table for the company
  • If match found: Flag as signal_flagged with signal type and date

Output

Each lead tagged with:

  • pipeline_status: new | existing_customer | in_pipeline | previously_contacted
  • pipeline_detail: One sentence explaining the overlap (or null)
  • signal_flags: Any signal composite matches

Handling Overlaps

  • Existing customer: Don't disqualify. Mark separately. Might be expansion/upsell.
  • In pipeline: Don't disqualify. Flag for sales rep coordination. Note the existing deal owner.
  • Previously contacted but no response: Still qualify. The inbound signal means they're now warmer.
  • Previously contacted and rejected: Still qualify the inbound. People change their minds. Note the prior context.

Step 3: Company Qualification

Process

For each lead's company, evaluate against every ICP company dimension:

Dimension 1 — Company Size

  • Check employee count against ICP range
  • Sources: enrichment data, LinkedIn company page, web search
  • Score: match | borderline | mismatch | unknown
  • Note: If the lead is from a subsidiary or division, evaluate the relevant unit, not the parent company

Dimension 2 — Industry

  • Check against target and excluded industry lists
  • Be smart about classification: "AI-powered HR platform" matches both "AI/ML" and "HR Tech"
  • Score: match | adjacent (related but not core target) | mismatch | unknown

Dimension 3 — Company Stage

  • Seed, Series A, Series B+, Growth, Public, Bootstrapped
  • Sources: Crunchbase, news, enrichment data
  • Score: match | borderline | mismatch | unknown

Dimension 4 — Geography

  • Check HQ location and/or the specific person's location
  • For remote-first companies, check where the majority of the team is
  • Score: match | borderline | mismatch | unknown

Dimension 5 — Use Case Fit

  • Based on what the company does, could they plausibly use the product?
  • This is the most nuanced dimension — requires understanding both the product and the company's operations
  • Sources: company website, product description, job postings (hint at internal tools/processes)
  • Score: strong_fit | moderate_fit | weak_fit | no_fit | unknown

Output

Each lead gets a company_qualification block:

{
  "company_size": { "score": "", "value": "", "reasoning": "" },
  "industry": { "score": "", "value": "", "reasoning": "" },
  "stage": { "score": "", "value": "", "reasoning": "" },
  "geography": { "score": "", "value": "", "reasoning": "" },
  "use_case": { "score": "", "value": "", "reasoning": "" },
  "company_verdict": "qualified | borderline | disqualified | insufficient_data"
}

Step 4: Person Qualification

Process

For each lead's contact person, evaluate against buyer persona criteria:

Dimension 1 — Title/Role Match

  • Check title against buyer persona title lists
  • Handle variations: "VP of Marketing" = "Vice President, Marketing" = "VP Marketing"
  • Be smart about title inflation at small companies (a "Director" at a 10-person startup ≠ "Director" at a 10,000-person enterprise)
  • Score: exact_match | close_match | adjacent | mismatch | unknown

Dimension 2 — Seniority Level

  • Map to: Individual Contributor, Manager, Director, VP, C-Level, Founder
  • Check against ICP seniority requirements
  • Score: match | too_junior | too_senior | unknown

Dimension 3 — Department

  • Engineering, Product, Marketing, Sales, Operations, Finance, HR, etc.
  • Check against ICP department targets
  • Score: match | adjacent | mismatch | unknown

Dimension 4 — Authority Type

  • Based on title + seniority, classify:
    • economic_buyer — Can sign the check
    • champion — Wants it, can influence the decision
    • user — Would use it daily, can validate need
    • evaluator — Tasked with research, limited decision power
    • gatekeeper — Can block but not approve
    • unknown

Dimension 5 — Right Person, Wrong Company (or Vice Versa)

  • If company qualifies but person doesn't: Flag as right_company_wrong_person — this is a referral opportunity
  • If person qualifies but company doesn't: Flag as right_person_wrong_company — rare for inbound, but possible with job changers

Output

Each lead gets a person_qualification block:

{
  "title_match": { "score": "", "value": "", "reasoning": "" },
  "seniority": { "score": "", "value": "", "reasoning": "" },
  "department": { "score": "", "value": "", "reasoning": "" },
  "authority_type": "",
  "person_verdict": "qualified | borderline | disqualified | insufficient_data",
  "mismatch_type": "null | right_company_wrong_person | right_person_wrong_company"
}

Step 5: Use Case Fit Assessment

Process

This step connects the company's likely needs to your product's actual capabilities. It goes deeper than Step 3's company-level use case check.

  1. Infer the lead's intent from their inbound action:

    • Demo request message → What did they say they need?
    • Content downloaded → What topic were they researching?
    • Webinar attended → What problem were they trying to solve?
    • Free trial signup → What feature did they try first?
    • Chatbot conversation → What questions did they ask?
  2. Map intent to product capabilities:

    • Does the product actually solve what they seem to need?
    • Is this a primary use case or a stretch?
    • Are there known limitations that would disappoint them?
  3. Assess implementation feasibility:

    • Based on company size and stage, can they realistically implement?
    • Do they likely have the technical resources / team to adopt?
    • Any known blockers for companies like this? (e.g., "banks need SOC2 and we don't have it yet")

Output

{
  "inferred_intent": "",
  "intent_source": "",
  "product_fit": "strong | moderate | weak | unknown",
  "product_fit_reasoning": "",
  "implementation_feasibility": "easy | moderate | complex | unlikely",
  "known_blockers": []
}

Step 6: Score & Verdict

Scoring Logic

Combine all dimensions into a final qualification verdict.

Composite Score Calculation:

Dimension Weight Possible Values
Company Size 15% match=100, borderline=50, mismatch=0, unknown=30
Industry 20% match=100, adjacent=60, mismatch=0, unknown=30
Company Stage 10% match=100, borderline=50, mismatch=0, unknown=30
Geography 10% match=100, borderline=50, mismatch=0, unknown=30
Use Case Fit 25% strong=100, moderate=60, weak=20, no_fit=0, unknown=30
Person Title/Role 15% exact=100, close=75, adjacent=40, mismatch=0, unknown=30
Person Seniority 5% match=100, too_junior=20, too_senior=60, unknown=30

Hard overrides (bypass the score):

  • Any hard disqualifier present → disqualified regardless of score
  • Any hard qualifier present → qualified regardless of score (but still show the full breakdown)
  • Existing customer → Route separately, don't score as new lead

Verdict thresholds:

  • Score ≥ 75: qualified — Pursue actively
  • Score 50-74: borderline — Qualified with caveats, may need manual review
  • Score 30-49: near_miss — Not qualified now, but close enough to consider (referral or nurture)
  • Score < 30: disqualified — Does not fit ICP

Sub-verdicts for routing:

  • qualified_hot — Score ≥ 75 AND Tier 1/2 urgency from triage
  • qualified_warm — Score ≥ 75 AND Tier 3/4 urgency
  • borderline_review — Score 50-74, needs human judgment call
  • near_miss_referral — Score 30-49 AND right_company_wrong_person (referral opportunity)
  • near_miss_nurture — Score 30-49, might fit in the future
  • disqualified_polite — Score < 30, needs polite decline
  • disqualified_competitor — Competitor employee
  • existing_customer_upsell — Existing customer with expansion signal

Output

Each lead gets:

{
  "composite_score": 0-100,
  "verdict": "",
  "sub_verdict": "",
  "top_qualification_reasons": [],
  "top_disqualification_reasons": [],
  "summary": "One sentence: why this lead is/isn't a fit"
}

Step 7: Output CSV

CSV Structure

Produce a CSV with ALL input fields preserved plus qualification columns appended:

Core qualification columns:

  • qualification_verdict — qualified | borderline | near_miss | disqualified
  • qualification_sub_verdict — qualified_hot | qualified_warm | borderline_review | near_miss_referral | near_miss_nurture | disqualified_polite | disqualified_competitor | existing_customer_upsell
  • composite_score — 0-100
  • summary — One sentence qualification reasoning

Pipeline check columns:

  • pipeline_status — new | existing_customer | in_pipeline | previously_contacted
  • pipeline_detail — One sentence on the overlap
  • signal_flags — Any signal composite matches

Company qualification columns:

  • company_size_score — match | borderline | mismatch | unknown
  • industry_score — match | adjacent | mismatch | unknown
  • stage_score — match | borderline | mismatch | unknown
  • geography_score — match | borderline | mismatch | unknown
  • use_case_score — strong | moderate | weak | no_fit | unknown

Person qualification columns:

  • title_match_score — exact_match | close_match | adjacent | mismatch | unknown
  • seniority_score — match | too_junior | too_senior | unknown
  • authority_type — economic_buyer | champion | user | evaluator | gatekeeper | unknown
  • mismatch_type — null | right_company_wrong_person | right_person_wrong_company

Use case columns:

  • inferred_intent — What they seem to need
  • product_fit — strong | moderate | weak | unknown
  • implementation_feasibility — easy | moderate | complex | unlikely

Save Location

clients/<client-name>/leads/inbound-qualified-[date].csv

Summary Report

After producing the CSV, present a summary:

## Inbound Lead Qualification: [Period]

**Total leads processed:** X
**Qualified:** X (Y%) — X hot, X warm
**Borderline (manual review):** X (Y%)
**Near miss:** X (Y%) — X referral opportunities, X nurture
**Disqualified:** X (Y%)

**Pipeline overlaps:**
- Existing customers: X (route to CS)
- Already in pipeline: X (coordinate with deal owner)
- Previously contacted: X (now warmer — re-engage)

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

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

**Data quality:**
- Leads with full data: X
- Leads with partial data (some dimensions scored as 'unknown'): X
- Leads needing enrichment: X

**CSV saved to:** [path]

Handling Edge Cases

Lead with only an email (no name, no company):

  • Extract company domain from email
  • If corporate domain: look up the company, proceed with company qualification (person qualification will be mostly "unknown")
  • If personal email (gmail, yahoo): Score as insufficient_data, recommend enrichment or manual review

Same company, multiple leads:

  • Qualify the company once, apply to all leads from that company
  • Person qualification runs individually for each
  • Flag the multi-contact opportunity: "3 people from [Company] came inbound — potential committee buy"

Contradictory signals:

  • Company is strong fit but person is completely wrong (e.g., intern at a perfect company)
  • Score honestly. The sub-verdict right_company_wrong_person routes this to referral handling in disqualification-handling

Borderline calls:

  • When the score is 50-74 and could go either way, lean toward qualifying for inbound leads
  • Rationale: they came to YOU. The intent signal tips borderline cases toward "worth a conversation"
  • Note this lean in the reasoning: "Borderline on [dimension], but inbound intent suggests pursuing"

Scoring with missing data:

  • Unknown dimensions score at 30 (not 0, not 50) — absence of data is mildly negative but not disqualifying
  • If >3 dimensions are "unknown", the lead is insufficient_data regardless of score — recommend enrichment first

Tools Required

  • CRM access — to check pipeline, existing customers, outreach history
  • Supabase client — for pipeline/signal lookups
  • Web search — for company research when enrichment data is sparse
  • Enrichment tools — Apollo, LinkedIn scraper, or similar (optional, enhances accuracy)
  • Read/Write — for CSV I/O and config management
Weekly Installs
8
GitHub Stars
340
First Seen
Mar 14, 2026
Installed on
opencode7
gemini-cli7
antigravity7
claude-code7
github-copilot7
codex7