| name | persona-clustering |
| description | Step 3 of the ICP playbook. Clusters per-call extractions into 4-8 distinct buyer personas using firmographics, technographics, and intent. Routes to Clay if available; otherwise uses the configured enrichment fallback. Use after Step 2 when the user has per-call markdown files and needs to find the recurring buyer pockets behind them. |
Step 3 — Cluster personas
You're looking for the recurring shape of buyers behind individual calls. Targets: 4–8 distinct personas, each with at least 3–5 calls of evidence.
Inputs
- All files in
./icp-output/calls/
- The configured enrichment tool (
stack.enrichment) — used to look up persona + company attributes
- Read
./icp-output/stack.json first
Routing for enrichment
clay → use the Clay MCP/connector. See skills/enrichment/clay.md.
- otherwise → see
skills/enrichment/fallbacks.md.
Clustering method (deterministic, then LLM-assisted)
Pass 1 — deterministic grouping by hard attributes
Read every per-call file and bucket on a tuple:
(function, seniority_band, headcount_band, stage_band, industry_band)
Where:
function ∈ {Sales, RevOps, Marketing, CS, Founder, Eng, Product, Other}
seniority_band ∈ {IC, Manager, Director+, VP+, C-level}
headcount_band ∈ {1-50, 51-200, 201-1000, 1001-5000, 5000+}
stage_band ∈ {Seed, A, B, C, D+/Public, Bootstrapped, Unclear}
industry_band (rough): {SaaS, FinServ, Healthcare, Retail, Industrial, Public Sector, Other}
Sort buckets by size. Look at the top buckets that account for ~80% of calls.
Pass 2 — refine with the soft attributes
For each top bucket, read the actual call files and identify the dominant:
- Trigger pattern (compelling event)
- Incumbent / replacement story
- Pain language theme
- Feature resonance
Two buckets that share hard attributes but differ on triggers + pain are two personas, not one. Don't collapse them.
Pass 3 — split or merge
- Merge if two clusters share >70% of pain language and triggers — likely the same persona.
- Split if a cluster has two distinct triggers each backed by ≥3 calls — likely two personas.
- Aim for 4–8 personas total. Less than 4 means under-resolution. More than 8 usually means you're slicing on noise.
Pass 4 — verify with enrichment
For each candidate persona, take the top 5 accounts and enrich them via the configured tool. Look for shared technographics (CRM, sequencer, data tooling), hiring patterns, funding stage, and geography. If enrichment reveals two attribute clusters inside one candidate persona, split.
Output format
For each persona, write ./icp-output/personas/<persona-slug>.md:
# Persona: <human-readable name>
slug: <lowercase-hyphenated>
call_evidence_count: <integer>
confidence: <high|medium|low>
## Hard attributes
- function: <…>
- seniority: <…>
- headcount: <…>
- stage: <…>
- industry: <…>
- geography: <…>
## Triggers (from Step 4 input)
- <trigger 1> (n calls)
- <trigger 2> (n calls)
## Incumbents commonly mentioned
- <tool> (n calls — leaving / evaluating / current)
## Pain language (verbatim, sourced)
- "<quote>" — <call-id>
- "<quote>" — <call-id>
- ...
## Feature resonance
- <feature> — <n calls> — sample quote: "<quote>" (<call-id>)
## Named accounts (call evidence)
- <Account Name> — <call-id> — <stage/outcome>
- ...
## Why this is a distinct persona
One paragraph defending the cluster against the closest neighboring persona.
State update
{
"step": "3",
"step_status": "completed",
"personas_clustered": <count>,
"persona_slugs": ["...", "..."]
}
Failure modes to catch
- One mega-persona with 60% of calls — you under-clustered. Split.
- A persona with only 1 call of evidence — drop or merge into the closest.
- Two personas with identical pain language — merge.
- A persona where the call evidence contradicts the enrichment (e.g., calls say "Series B" but the enrichment finds half are Public) — re-check; one of the two sources is wrong.