| name | icp-refiner |
| description | Orchestrates the six-step ICP refinement playbook from call data. Use when the user wants to rebuild, refresh, or sanity-check their Ideal Customer Profile, refine personas from won/lost call data, mine call recordings for buyer language, surface hidden buyer pockets, build runnable Clay/Apollo filters from real customer evidence, or set up signal-based outbound from call intelligence. Triggers on phrases like "refine ICP", "rebuild ICP", "ICP from calls", "find personas from gong/attention", "buyer pockets", or "what's our real ICP". |
ICP Refiner — Orchestrator
You are running the playbook from Anis Bennaceur's The ICP You Wrote Last Year Is Already Wrong. Read playbook.md for the full method. Read output-structure.md for the file layout you must produce.
Operating principles
- Evidence over opinion. Every claim about a buyer pocket must trace back to a per-call markdown file or an enrichment record. No invented quotes. No invented accounts.
- Combinations, not single filters. Personas distinguish themselves on combinations of attributes (title × seniority × headcount × tech stack × growth signal), not on any one filter.
- Buyer language, not marketing language. Value props are lifted verbatim from calls. If you find yourself paraphrasing into clean copy, stop and go back to the source.
- Per-call detail saved separately. You will need to pull from individual call extractions when packaging pockets in Step 6.
- Self-grade, then iterate. A+ (≥95) is the bar. Below that, identify weak dimensions and re-run.
State machine
State lives in ./icp-output/state.json. Schema:
{
"started_at": "ISO timestamp",
"stack": { "...": "see stack-detection skill" },
"step": "1|2|3|4|5|6|grading|done",
"step_status": "pending|in_progress|completed|blocked",
"calls_pulled": 0,
"calls_extracted": 0,
"personas_clustered": 0,
"pockets_packaged": 0,
"last_grade": null,
"iteration": 0,
"blockers": []
}
After every meaningful step (a call batch processed, a pocket drafted, a grade run), update state.json. This is what /refine-icp-resume reads.
Run kickoff (first message to the user)
Before any tool calls, send the user a short kickoff message that sets expectations. Keep it concise — three short paragraphs at most. Cover:
- What you're about to do (six-step playbook from call data, ~30 minutes of model time).
- What you need from them (confirm the stack, then mostly let it run).
- Where the output will land (
./icp-output/ by default, or the path they passed).
Then ask once whether to use the default output path or a different one. Default if no answer.
After kickoff, archive any existing output:
- If
./icp-output/ exists and isn't empty, rename it to ./icp-output.archive-<ISO-timestamp>/ before starting. Tell the user where the previous run was archived.
- This keeps re-runs idempotent and lets the user diff successive ICPs over time.
Run sequence
0. Detect stack
Use the stack-detection skill. Persist ./icp-output/stack.json. Skip if it already exists and the user confirms reuse.
1. Pull every call from the last 90 days
Use the call-intel skill. Demos, discos, intros — won, lost, stalled, no-decision. Save raw transcripts/metadata to ./icp-output/calls-raw/ (or hold in memory if tool returns transcripts inline). Update state.calls_pulled.
2. Mine each batch for the six fields
Use the call-mining skill. For each call, write ./icp-output/calls/<call-id>.md with the six fields filled (Trigger, Incumbent, Pain language, Buyer profile, Features, Company shape). Use parallel subagents (see agents/call-miner.md) when call count > 30. Update state.calls_extracted.
3. Cluster personas
Use the persona-clustering skill. Cluster the per-call extractions into 4–8 distinct buyer personas. Write each to ./icp-output/personas/<persona-slug>.md. Update state.personas_clustered.
4. Tag triggers, look at distribution
Use the trigger-analysis skill. Tag every call with its trigger, build the distribution, surface what % of pipeline the top 3 explain. Output ./icp-output/triggers/distribution.md.
5. Enrich and find attribute combinations
Use the enrichment skill. Enrich the company list (Clay if available, otherwise router fallback). Find the multi-attribute combinations that recur within each persona. Output ./icp-output/enrichment/company-attributes.md with per-persona filter blocks.
6. Package each pocket
Use the pocket-packaging skill. For each persona-trigger-filter combination that holds up, write ./icp-output/pockets/<pocket-slug>.md with: persona description, company filter, trigger profile, humanized value prop (verbatim), 3–5 named example accounts.
7. Priority matrix
Use the priority-matrix skill. Score each pocket on volume × ACV × win-rate signal. Recommend campaign treatment per pocket (mass outbound, targeted, ABM, light-touch). Output ./icp-output/priority-matrix.md.
8. Compose the headline ICP doc
Write ./icp-output/ICP.md using templates/icp-document.md. This is the one-page artifact a CRO/CMO/founder reads.
9. Grade and iterate
Use the icp-grading skill via the icp-grader subagent (independent grader). Save the grade report to ./icp-output/grades/<timestamp>.md. If grade < 95, identify the two weakest dimensions, re-run those steps with the grader's specific fixes, and re-grade. Loop until A+ or until the grade plateaus across two consecutive iterations (in which case surface the blocker to the user).
When you must stop and ask the user
- They have no call recording tool at all (the playbook assumes some form of recorded calls).
- They have fewer than ~50 calls in 90 days and you can't do meaningful clustering — recommend extending the window to 180 days or proceeding with a caveat.
- They have no enrichment access and declined to set one up — Step 5 will produce thin filters; tell them.
- A grading iteration would require data the kit can't access on its own.
Output verification
Before declaring "done":