# Icp Scoring Engine

> Use when the user says "build a scoring model", "ICP score", "lead scoring", "our score doesn't work", "fit and intent", "which accounts should reps work", "MQL threshold", "prioritize this list". Builds fit and intent as separate axes, fits thresholds to the real distribution, and runs the discrimination test before shipping. Writes workspace/data/scoring-model.md.

- Skill: `guerrilla2799/icp-scoring-engine` (Agent Skill)
- Install (CLI): `npx skillmds@latest add guerrilla2799/icp-scoring-engine`
- Raw SKILL.md: https://api.skillmd.com/api/skills/guerrilla2799/icp-scoring-engine/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: AI & ML
- Author: guerrilla2799 (https://skillmd.com/u/guerrilla2799)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/guerrilla2799/icp-scoring-engine

---


# ICP Scoring Engine

Score fit and intent separately, set thresholds from the actual distribution, and prove the model separates outcomes before anybody routes on it.

## When to use
- No scoring model exists
- A model exists and sales ignores it, which is the most common case
- Routing decisions need a priority signal
- Threshold review, quarterly

## Inputs
- Reads: `workspace/data/universe.csv` enriched, `workspace/data/object-model.md`
- Needs from user: last year's closed-won and closed-lost account lists, current model if any, and the weekly account capacity of the team that will work the output

The capacity number is required. A model whose top band exceeds what the team can work is not a prioritization.

## Workflow

### 1. Score fit and intent as two separate axes

Never blend them into one number. A perfect-fit account with no activity and a bad-fit account browsing pricing produce the same average, and that average routes both to the same place.

**Fit (10 points), the account's structural suitability:**

| Criterion | Points |
|---|---|
| In target industry or vertical | 2 |
| Correct size band, employees or revenue | 2 |
| Trigger event present | 2 |
| Budget authority identifiable in the committee | 2 |
| Competitive alternative confirmed, including status quo | 2 |

**Intent, separately, time-decayed.** Comes from `signal-pipeline`. Weight by proximity to a purchase decision, and decay by age.

### 2. Read the quadrants, do not average them

| | High intent | Low intent |
|---|---|---|
| **High fit** | Work now. This is the whole point of the model | Nurture and warm. The largest quadrant and the most neglected |
| **Low fit** | Inspect before acting. Usually a competitor, a student, or a job seeker | Suppress. Do not spend on this |

Each quadrant gets a different motion. That is the output of a scoring model, not a ranked list.

### 3. Score the existing database before setting any threshold

This is the step that gets skipped and it is the reason most models fail.

Score everything you already have, then look at the distribution. Set thresholds so that:

- The top band is a volume the team can actually work in a week
- No band holds more than half the list
- The bottom band is genuinely suppressible

**Thresholds come from the distribution, not from the design meeting.** A threshold chosen before you see the spread produces the 78%-in-one-band failure, where the field still populates and nobody looks at it.

### 4. Run the discrimination test

Non-negotiable before shipping.

```
Take last year's closed-won accounts    → score with the new model
Take last year's closed-lost accounts   → score with the new model
Compare the distributions
```

| Lift, top band vs bottom | Verdict |
|---|---|
| Over 3x | Ship it |
| 2 to 3x | Usable. Note which criterion is doing the work |
| Under 2x | Do not ship. The model is decoration |
| Under 1.5x | Something is inverted. Check the criteria individually |

If the test fails, the usual cause is a criterion that correlates with being in the database rather than with buying. Drop criteria one at a time and re-run.

### 5. Write the routing table

A score with no routing rule changes nothing.

```
Score band → what happens, who owns it, in what timeframe
```

Every band needs a destination, including the bottom one, where the destination is suppression.

### 6. Refit quarterly

Distributions shift as the market and the list change. A threshold set once is right for one quarter. Put the refit on a calendar and run the discrimination test again each time.

## Output
- Writes: `workspace/data/scoring-model.md`, scored list with both axes as separate columns
- Uses: `templates/icp-scoring-rubric-template.md`
- Prints: the rubric, the actual distribution, the chosen thresholds with their justification, the discrimination test result, and the routing table

## Rules & quality bar
- **Fit and intent never blend into one number**
- **Score the existing database before setting thresholds**
- **No band over 50% of the list**
- **Top band sized to real team capacity**
- **Discrimination test runs before shipping.** Under 2x lift means do not ship
- **Every band has a routing destination,** including suppression
- **Refit quarterly,** with the test re-run

## Related skills
- Requires: `enrichment-waterfall`, `signal-pipeline` for the intent axis
- Hands off to: `lifecycle-and-routing`
- See also: `docs/metrics.md` for scoring health metrics

