feat(hands): improve 6 lower-scoring hands — system prompts and SKILL.md depth

- browser: 5→7 phases, SPA detection, error recovery decision tree, 3 new settings
- strategist: framework integration methodology, 7 anti-patterns, uncertainty quantification
- lead: remove clip language, add BANT/MEDDIC qualification, 3 new settings + CRM export
- researcher: CRAAP→CRAAP+, 7-step conflict resolution, 6-item cognitive bias audit
- collector: concrete change classification (structural/content/metadata), 5-factor scoring, 2 new settings
- apitester: OWASP Top 10 checklist, 4 load test profiles, contract testing phase, GraphQL/Webhook patterns
This commit is contained in:
Evan Hu committed 2026-03-23 00:31:13 +09:00
1 parent 33d279889c
commit ed595230cf
12 files changed
+1663 -375

No files matched your search

+217 -18
View File
@@ -196,6 +196,67 @@ label = "Standard (+ company size, industry, tech stack)"
value = "deep"
label = "Deep (+ funding, recent news, social profiles)"
[[settings]]
key = "lead_score_threshold"
label = "Lead Score Threshold"
description = "Minimum score (0-100) for a lead to be included in reports"
setting_type = "select"
default = "60"
[[settings.options]]
value = "40"
label = "40 — Include warm and hot leads"
[[settings.options]]
value = "60"
label = "60 — Warm leads and above (recommended)"
[[settings.options]]
value = "80"
label = "80 — Hot leads only"
[[settings]]
key = "qualification_framework"
label = "Qualification Framework"
description = "Sales qualification methodology to apply during lead scoring"
setting_type = "select"
default = "bant"
[[settings.options]]
value = "bant"
label = "BANT (Budget, Authority, Need, Timeline)"
[[settings.options]]
value = "meddic"
label = "MEDDIC (Metrics, Economic Buyer, Decision Criteria, Process, Pain, Champion)"
[[settings.options]]
value = "auto"
label = "Auto (BANT for SMB, MEDDIC for Enterprise)"
[[settings]]
key = "crm_export_format"
label = "CRM Export Format"
description = "Generate an additional CRM-ready export alongside the standard report"
setting_type = "select"
default = "none"
[[settings.options]]
value = "none"
label = "None (standard report only)"
[[settings.options]]
value = "hubspot"
label = "HubSpot"
[[settings.options]]
value = "salesforce"
label = "Salesforce"
[[settings.options]]
value = "pipedrive"
label = "Pipedrive"
# ─── Agent configuration ─────────────────────────────────────────────────────
[agent]
@@ -207,7 +268,7 @@ model = "default"
max_tokens = 16384
temperature = 0.3
max_iterations = 50
system_prompt = """You are Lead Hand — an autonomous lead generation engine that discovers, enriches, and delivers qualified leads 24/7.
system_prompt = """You are Lead Hand — an autonomous lead generation engine that discovers, qualifies, enriches, and delivers sales-ready leads 24/7. You combine systematic web research with structured qualification frameworks (BANT/MEDDIC) to produce leads that sales teams can act on immediately.
## Phase 0 — Platform Detection (ALWAYS DO THIS FIRST)
@@ -225,7 +286,7 @@ Then set your approach:
On first run:
1. Check memory_recall for `lead_hand_state` — if it exists, you're resuming
2. Read the **User Configuration** section for target_industry, target_role, company_size, geo_focus, etc.
2. Read the **User Configuration** section for target_industry, target_role, company_size, geo_focus, qualification_framework, lead_score_threshold, crm_export_format, etc.
3. Create your delivery schedule using schedule_create based on `delivery_schedule` setting
4. Load any existing lead database from `leads_database.json` via file_read (if it exists)
@@ -236,7 +297,7 @@ On subsequent runs:
---
## Phase 2 — Target Profile Construction
## Phase 2 — Ideal Customer Profile Construction & Refinement
Build an Ideal Customer Profile (ICP) from user settings:
- Industry: from `target_industry` setting
@@ -244,6 +305,13 @@ Build an Ideal Customer Profile (ICP) from user settings:
- Company size filter: from `company_size` setting
- Geography: from `geo_focus` setting
**ICP Refinement Loop** (run after every 3 reports):
1. Analyze the top 20% of leads by score — what attributes do they share?
2. Analyze the bottom 20% — what attributes caused low scores?
3. Tighten ICP criteria based on patterns: narrow industry keywords, adjust company size range, add tech stack requirements
4. Log ICP revisions to `icp_revision_log.json` with date and rationale
5. memory_store `lead_hand_icp_version` with the current ICP revision number
Store the ICP in the knowledge graph:
- knowledge_add_entity: ICP profile node
- knowledge_add_relation: link ICP to target attributes
@@ -263,22 +331,27 @@ Execute a multi-query web research loop:
3. For promising results, use web_fetch to extract company/person details
4. Extract structured lead data: name, title, company, company_url, linkedin_url (if public), email pattern
Target: discover 2-3x the `leads_per_report` setting to allow for filtering.
Target: discover 2-3x the `leads_per_report` setting to allow for filtering and qualification.
---
## Phase 4 — Lead Enrichment
For each discovered lead, based on `enrichment_depth`:
Apply enrichment based on `enrichment_depth` setting. Higher depth costs more tool calls but produces better-qualified leads.
**Basic**: name, title, company — already have this from discovery
**Standard**: additionally fetch:
**Basic**: name, title, company — already have this from discovery. Use for high-volume, low-touch lists.
**Standard** (recommended default): additionally fetch:
- Company website (web_fetch company_url) — extract: employee count, industry, tech stack, product description
- Look for company on job boards — hiring signals indicate growth
**Deep**: additionally fetch:
- Cross-reference at least 2 sources per company to verify data accuracy
**Deep** (best for enterprise targets): additionally fetch:
- Recent funding news (web_search "[company] funding round")
- Recent company news (web_search "[company] news 2025")
- Social profiles (web_search "[person name] [company] linkedin twitter")
- Competitive landscape (what tools/vendors they currently use)
- Negative signals: layoffs, lawsuits, executive departures
**Enrichment depth escalation**: If a lead scores above 70 at Standard depth, automatically re-enrich at Deep depth to maximize qualification data. This targets deep enrichment resources only at the most promising leads.
Store enriched entities in knowledge graph:
- knowledge_add_entity for each lead and company
@@ -286,10 +359,44 @@ Store enriched entities in knowledge graph:
---
## Phase 5 — Deduplication & Scoring
## Phase 5 — Qualification
Apply the qualification framework configured by the `qualification_framework` setting.
### BANT Qualification (default — best for SMB/startup targets, short sales cycles)
For each lead, assess four dimensions from enrichment data:
- **Budget**: funding rounds, revenue estimates, pricing tier of current tools, job postings for related roles
- **Authority**: is the contact a decision-maker? VP+, C-level, Director, listed on Leadership page
- **Need**: job postings mentioning the pain point, tech stack gaps, competitor tool usage, forum complaints
- **Timeline**: contract renewals, compliance deadlines, product launches, recent leadership changes
Apply BANT bonus points on top of the base score:
Budget confirmed: +5 | Authority confirmed: +5 | Need confirmed: +5 | Timeline confirmed: +5 (max +20)
### MEDDIC Qualification (best for enterprise targets, $100K+ deal size)
For each enterprise lead (500+ employees or score > 80), attempt to discover:
- **Metrics**: quantifiable outcomes the buyer cares about (case studies, KPIs in job postings)
- **Economic Buyer**: person with budget authority (CFO, CEO, VP Finance, Head of Procurement)
- **Decision Criteria**: how they evaluate vendors (RFP docs, comparison posts, compliance requirements)
- **Decision Process**: steps from evaluation to purchase (procurement team, legal review, pilot mentions)
- **Identify Pain**: specific problems driving a purchase (support forums, reviews, analyst reports)
- **Champion**: internal advocate (conference speakers, blog authors, open-source contributors)
Log the MEDDIC score as X/6 dimensions discovered per lead.
### Mixed-list strategy
When the target list contains both SMB and enterprise leads:
1. Run BANT on all leads (fast first pass)
2. For enterprise leads that score A-grade (80+), run a MEDDIC deep pass
3. Include the qualification framework used in the output for each lead
---
## Phase 6 — Deduplication & Scoring
1. Compare new leads against existing `leads_database.json`:
- Match on: normalized company name + person name
- Match on: company website domain (most stable identifier)
- Skip exact duplicates
- Update existing leads with new enrichment data
2. Score each lead (0-100):
@@ -298,40 +405,59 @@ Store enriched entities in knowledge graph:
- Enrichment completeness: +20 (all fields populated)
- Recency: +15 (company active recently)
- Accessibility: +15 (public contact info available)
3. Sort by score descending
4. Take top N leads per `leads_per_report` setting
Then apply qualification bonuses (BANT: up to +20, MEDDIC: up to +10 for 5+ dimensions)
Then apply negative modifiers:
- Recent layoffs (>10% headcount): -10
- Lawsuit / regulatory action: -5
- Executive turnover (CEO/CTO departed): -5
3. Apply the `lead_score_threshold` — only include leads at or above this score
4. Sort by score descending
5. Take top N leads per `leads_per_report` setting
6. If fewer leads meet the threshold than requested, report honestly: "Found X leads meeting quality threshold; Y additional leads are partial matches below threshold"
### Score interpretation for output:
- 80-100 (A): Hot lead — prioritize immediate outreach
- 60-79 (B): Warm lead — worth nurturing
- 40-59 (C): Cool lead — needs further enrichment
- 0-39 (D): Cold lead — deprioritize unless ICP changes
---
## Phase 6 — Report Generation
## Phase 7 — Report Generation
Generate the report in the configured `output_format`:
**CSV format**:
```csv
Name,Title,Company,Company URL,Industry,Company Size,Score,Discovery Date,Notes
Name,Title,Company,Company URL,Industry,Company Size,Score,Grade,Qualification,Discovery Date,Notes
```
**JSON format**:
```json
[{"name": "...", "title": "...", "company": "...", "company_url": "...", "industry": "...", "size": "...", "score": 85, "discovered": "2025-01-15", "enrichment": {...}}]
[{"name": "...", "title": "...", "company": "...", "company_url": "...", "industry": "...", "size": "...", "score": 85, "grade": "A", "qualification": {"framework": "BANT", "budget": true, "authority": true, "need": true, "timeline": false}, "discovered": "2025-01-15", "enrichment": {...}}]
```
**Markdown Table format**:
```markdown
| # | Name | Title | Company | Score | Signal |
|---|------|-------|---------|-------|--------|
| # | Name | Title | Company | Score | Grade | Qualification | Key Signal |
|---|------|-------|---------|-------|-------|---------------|------------|
```
**CRM export** (when `crm_export_format` is set):
- **hubspot**: JSON with HubSpot contact property names (firstname, lastname, jobtitle, company, hs_lead_status)
- **salesforce**: CSV with Salesforce standard field names (FirstName, LastName, Title, Company, LeadSource, Rating)
- **pipedrive**: JSON with Pipedrive person/organization fields (name, org_id, title, email)
Save report to: `lead_report_YYYY-MM-DD.{csv,json,md}`
If CRM export is enabled, also save: `lead_report_YYYY-MM-DD_crm.{csv,json}`
---
## Phase 7 — State Persistence
## Phase 8 — State Persistence
After each run:
1. Update `leads_database.json` with all known leads (new + existing)
2. memory_store `lead_hand_state` with: last_run, total_leads, report_count
2. memory_store `lead_hand_state` with: last_run, total_leads, report_count, icp_version
3. Update dashboard stats:
- memory_store `lead_hand_leads_found` — total unique leads discovered
- memory_store `lead_hand_reports_generated` — increment report count
@@ -348,6 +474,7 @@ After each run:
- If a search yields no results, try alternative queries before giving up
- Always deduplicate before reporting — users hate seeing the same lead twice
- Include your confidence level for enriched data (e.g. "email pattern: likely" vs "email: verified")
- Quality over quantity: 10 well-qualified A-grade leads beat 50 unqualified names
- If the user messages you directly, pause the pipeline and respond to their question
"""
@@ -428,6 +555,18 @@ description = "优先关注的地理区域(例如美国、欧洲、亚太、
label = "信息丰富度"
description = "对每条线索收集多少上下文信息"
[i18n.zh.settings.lead_score_threshold]
label = "线索评分阈值"
description = "报告中包含线索的最低评分(0-100)"
[i18n.zh.settings.qualification_framework]
label = "资质评估框架"
description = "线索评分时使用的销售资质评估方法论"
[i18n.zh.settings.crm_export_format]
label = "CRM 导出格式"
description = "在标准报告之外生成 CRM 可导入的文件"
# ─── Korean (한국어) ────────────────────────────────────────────────────
[i18n.ko]
@@ -471,6 +610,18 @@ description = "우선적으로 집중할 지역 (예: 미국, 유럽, 아시아
label = "보강 깊이"
description = "리드당 수집할 컨텍스트 정보의 수준"
[i18n.ko.settings.lead_score_threshold]
label = "리드 점수 기준"
description = "보고서에 포함할 리드의 최소 점수 (0-100)"
[i18n.ko.settings.qualification_framework]
label = "자격 평가 프레임워크"
description = "리드 스코어링 시 적용할 영업 자격 평가 방법론"
[i18n.ko.settings.crm_export_format]
label = "CRM 내보내기 형식"
description = "표준 보고서와 함께 CRM 가져오기용 파일 생성"
# ─── Japanese (日本語) ────────────────────────────────────────────────────
[i18n.ja]
@@ -514,6 +665,18 @@ description = "優先する地理的リージョン(例: 米国、欧州、APA
label = "情報付加の深さ"
description = "リードごとに収集するコンテキスト情報の量"
[i18n.ja.settings.lead_score_threshold]
label = "リードスコア閾値"
description = "レポートに含めるリードの最低スコア(0-100)"
[i18n.ja.settings.qualification_framework]
label = "資格評価フレームワーク"
description = "リードスコアリング時に適用する営業資格評価の方法論"
[i18n.ja.settings.crm_export_format]
label = "CRMエクスポート形式"
description = "標準レポートに加えてCRMインポート用ファイルを生成"
# ─── Spanish (Español) ────────────────────────────────────────────────────
[i18n.es]
@@ -557,6 +720,18 @@ description = "Región geográfica a priorizar (ej. EE.UU., Europa, Asia-Pacífi
label = "Profundidad de enriquecimiento"
description = "Cuánto contexto recopilar por cada lead"
[i18n.es.settings.lead_score_threshold]
label = "Umbral de puntuación"
description = "Puntuación mínima (0-100) para incluir un lead en los informes"
[i18n.es.settings.qualification_framework]
label = "Marco de cualificación"
description = "Metodología de cualificación comercial a aplicar durante la puntuación de leads"
[i18n.es.settings.crm_export_format]
label = "Formato de exportación CRM"
description = "Generar un archivo importable para CRM junto al informe estándar"
# ─── French (Français) ────────────────────────────────────────────────────
[i18n.fr]
@@ -600,6 +775,18 @@ description = "Région géographique prioritaire (ex. USA, Europe, Asie-Pacifiqu
label = "Profondeur d'enrichissement"
description = "Niveau d'informations contextuelles à collecter par prospect"
[i18n.fr.settings.lead_score_threshold]
label = "Seuil de score"
description = "Score minimum (0-100) pour inclure un prospect dans les rapports"
[i18n.fr.settings.qualification_framework]
label = "Cadre de qualification"
description = "Méthodologie de qualification commerciale appliquée lors du scoring des prospects"
[i18n.fr.settings.crm_export_format]
label = "Format d'export CRM"
description = "Générer un fichier importable CRM en plus du rapport standard"
# ─── German (Deutsch) ────────────────────────────────────────────────────
[i18n.de]
@@ -642,3 +829,15 @@ description = "Priorisierte geografische Region (z.B. USA, Europa, Asien-Pazifik
[i18n.de.settings.enrichment_depth]
label = "Anreicherungstiefe"
description = "Umfang der pro Lead gesammelten Kontextinformationen"
[i18n.de.settings.lead_score_threshold]
label = "Lead-Score-Schwelle"
description = "Mindestpunktzahl (0-100), um einen Lead in Berichte aufzunehmen"
[i18n.de.settings.qualification_framework]
label = "Qualifizierungsrahmen"
description = "Vertriebsqualifizierungsmethodik für die Lead-Bewertung"
[i18n.de.settings.crm_export_format]
label = "CRM-Exportformat"
description = "Zusätzlich zum Standardbericht eine CRM-importierbare Datei erstellen"
+64 -4
View File
@@ -25,6 +25,16 @@ A good ICP answers these questions:
| SMB | 50-500 | $25K-$250K/yr | 1-3 months |
| Enterprise | 500+ | $250K+/yr | 3-12 months |
### ICP Refinement Loop
The ICP should not be static. After every 3 report cycles, refine it:
1. **Analyze top performers**: Look at leads scored 80+ — what industry sub-segments, company sizes, and role patterns appear most often?
2. **Analyze low performers**: Look at leads scored below 40 — which ICP criteria were they missing? Were there false positives from overly broad keywords?
3. **Tighten criteria**: Narrow industry keywords (e.g., "fintech" becomes "payment infrastructure fintech"), adjust company size range, add or remove geographic regions, refine role titles.
4. **Track revisions**: Log each ICP revision with date, changes made, and rationale. This creates an audit trail showing how targeting improved over time.
5. **Measure impact**: Compare average lead score before and after each ICP revision. A well-refined ICP should produce higher average scores with fewer total leads — quality over quantity.
---
## Web Research Techniques for Lead Discovery
@@ -171,6 +181,17 @@ site:thomasnet.com "[product category]"
- Company blog/content activity (engagement level)
- Executive team changes
### Enrichment Depth Escalation Strategy
Not all leads deserve the same enrichment investment. Use a two-pass approach:
1. **First pass (Standard depth)**: Enrich all discovered leads at Standard depth. This is cost-effective and provides enough data for initial scoring.
2. **Score checkpoint**: After the first pass, score all leads. Any lead scoring 70+ at Standard depth is a strong candidate.
3. **Second pass (Deep depth)**: Re-enrich only leads scoring 70+ at Deep depth. This focuses expensive research (funding history, news, competitive analysis) on leads most likely to convert.
4. **Skip threshold**: Leads scoring below 30 after Standard enrichment should not be enriched further — the data is unlikely to improve their score enough to matter.
This approach typically reduces total enrichment cost by 40-60% while maintaining the same output quality for top-tier leads.
### Email Pattern Discovery
Common corporate email formats (try in order):
1. `firstname@company.com` (most common for small companies)
@@ -275,6 +296,9 @@ For each enterprise lead, attempt to discover:
```
### Choosing Between BANT and MEDDIC
The `qualification_framework` setting controls which framework is applied. When set to "auto", use this decision table:
| Scenario | Recommended Framework |
|----------|----------------------|
| SMB / startup targets, short sales cycle | BANT |
@@ -343,12 +367,48 @@ Name,Title,Company,Company URL,LinkedIn,Industry,Size,Score,Discovered,Notes
### Markdown Table Format
```markdown
| # | Name | Title | Company | Score | Key Signal |
|---|------|-------|---------|-------|------------|
| 1 | Jane Smith | VP Engineering | Acme Corp | 85 | Series B funded, hiring |
| 2 | John Doe | CTO | Beta Inc | 72 | Product launch Q1 2025 |
| # | Name | Title | Company | Score | Grade | Qualification | Key Signal |
|---|------|-------|---------|-------|-------|---------------|------------|
| 1 | Jane Smith | VP Engineering | Acme Corp | 85 | A | BANT 4/4 | Series B funded, hiring |
| 2 | John Doe | CTO | Beta Inc | 72 | B | BANT 3/4 | Product launch Q1 2025 |
```
### CRM Export Field Mappings
When `crm_export_format` is configured, produce an additional file with CRM-native field names:
**HubSpot** (JSON):
| Lead Field | HubSpot Property |
|------------|-----------------|
| first_name | `firstname` |
| last_name | `lastname` |
| title | `jobtitle` |
| company | `company` |
| company_url | `website` |
| industry | `industry` |
| score | `hs_lead_status` (mapped: 80+ = "New", 60-79 = "Open", <60 = "In Progress") |
**Salesforce** (CSV):
| Lead Field | Salesforce Field |
|------------|-----------------|
| first_name | `FirstName` |
| last_name | `LastName` |
| title | `Title` |
| company | `Company` |
| company_url | `Website` |
| industry | `Industry` |
| score | `Rating` (mapped: 80+ = "Hot", 60-79 = "Warm", <60 = "Cold") |
| lead_source | `LeadSource` |
**Pipedrive** (JSON):
| Lead Field | Pipedrive Field |
|------------|----------------|
| full_name | `name` |
| title | `job_title` |
| company | `org_name` |
| company_url | `org_address` |
| notes | `note` |
---
## Worked Examples