← Resources

Simple Lead Scoring Framework (0-100)

A two-axis scoring model - fit (who they are, 0-50) plus intent (what they did, 0-50) - with time decay and hard thresholds: MQL at 40, SQL at 70. Ships as a CRM field kit, two threshold automations, and an agent prompt that recomputes every score nightly.

Who this is for

This framework is for founder-led and small sales teams handling up to a couple thousand leads a month, especially teams where an AI agent does the triage. Use it when your queue is bigger than your calendar: scoring exists to decide who gets attention today, nothing more. It is not a qualification framework - once a conversation starts, switch to BANT for transactional deals or MEDDPICC for complex ones. Scoring ranks the pile; qualification interrogates the deal.

The two-axis fit-times-intent model comes out of the marketing-automation era - Marketo's Definitive Guide to Lead Scoring popularized it in the early 2010s. The version here is trimmed for small pipelines and machine operators: fewer signals, integer points, explicit decay windows an agent can compute from timestamps.

The model

lead_score = fit_score + intent_score, each clamped to 0-50. Fit is scored from firmographics and changes rarely. Intent is scored from behavior and decays. Keeping the axes separate matters: a perfect-fit lead who never engaged and a terrible-fit lead who booked a demo can both land at 50, and they need completely different plays. Store all three numbers, not just the total.

Fit: firmographics (0-50)

Score fit once on creation, then re-score only when the underlying facts change. Take the best match per row - industry points do not stack.

SignalPoints
Industry: exact ICP match+15
Industry: adjacent vertical+8
Company size in your sweet spot+10
Company size one band above or below+5
Role: economic buyer+15
Role: champion or influencer+8
Geography in a market you serve+5
Context signal: uses a tool you integrate with+5

Calibration rule: your single best real customer, scored honestly, should land at 45-50. If they score 30, your ICP definition is fuzzier than you think - fix the definition, not the points. Hard disqualifiers (student emails, competitors, sanctioned geographies) are not negative points; they are fit = 0 plus a flag, so activity volume can never buy them back into the queue.

Intent: behavior (0-50, decaying)

Intent points attach to events, not states, and every event carries its timestamp. Sum the decayed values and clamp at 50.

EventPoints
Attended a meeting or demo+20
Inbound hand-raise (pricing request, trial signup)+15
Replied to outreach+10
Second stakeholder from the account engaged+10
Opened a proposal, or repeat website visits+5
Email open alone0

Yes, opens are worth zero. Apple Mail privacy inflates them and bots click tracking pixels; scoring them trains your queue to chase ghosts.

Decay: skip the half-life math. Each event counts full value for 14 days from when it occurred, half value from day 15 to 45, and zero after day 45. Three windows, integer arithmetic, trivially computable by an agent reading activity timestamps. A lead nobody has touched in seven weeks quietly returns to nurture on its own - which is exactly what should happen.

Thresholds

ScoreStagePlay
0-39NurtureAutomated sequence, no human time
40-69MQLTargeted campaign, agent-drafted personalization
70+ and fit ≥ 20SQLHuman outreach within 24 hours

Why these numbers: 40 means decent fit plus one real engagement, or great fit with a faint signal - enough to justify a machine's attention. 70 forces a strong showing on both axes, which is what justifies a person's. The fit floor is the guardrail that makes the whole thing trustworthy: a student who attended your demo hits 20 intent points and zero fit, and no amount of enthusiasm should page a rep.

Why simple beats ML at small scale

Predictive scoring needs labeled outcomes - realistically 500+ closed-won deals before a model separates signal from noise. Small funnels have dozens. Below that line a trained model is just overfitting your last quarter, and it fails in the worst way: silently, with a confident number nobody can interrogate. A point rubric has the opposite properties. Anyone can read it, pipeline review can argue with it ("why is this 62?" has a checkable answer), and it lives in version control - change the points, note the date, compare cohorts. And once an LLM applies the rubric for you, the honest cost advantage of ML - no manual scoring labor - disappears. The rubric is the model; the agent is the inference engine.

The artifact: field kit + threshold automations

The kit below is expressed against Relm's API, but the shape is portable to any CRM with custom fields and automations. POST each entry in fields to /v1/fields, each entry in automations to /v1/automations.

{
  "fields": [
    { "object": "contact", "key": "fit_score", "label": "Fit score", "data_type": "number" },
    { "object": "contact", "key": "intent_score", "label": "Intent score", "data_type": "number" },
    { "object": "contact", "key": "lead_score", "label": "Lead score", "data_type": "number" },
    { "object": "contact", "key": "lifecycle", "label": "Lifecycle", "data_type": "text" },
    { "object": "contact", "key": "score_updated_at", "label": "Score updated at", "data_type": "date" }
  ],
  "automations": [
    {
      "name": "Flag MQL at 40",
      "trigger_event": "contact.updated",
      "conditions": [
        { "field": "lead_score", "op": "gte", "value": 40 },
        { "field": "lead_score", "op": "lt", "value": 70 },
        { "field": "lifecycle", "op": "nin", "value": ["mql", "sql"] }
      ],
      "actions": [
        { "type": "set_field", "field": "lifecycle", "value": "mql" }
      ]
    },
    {
      "name": "Flag SQL at 70",
      "trigger_event": "contact.updated",
      "conditions": [
        { "field": "lead_score", "op": "gte", "value": 70 },
        { "field": "fit_score", "op": "gte", "value": 20 },
        { "field": "lifecycle", "op": "neq", "value": "sql" }
      ],
      "actions": [
        { "type": "set_field", "field": "lifecycle", "value": "sql" },
        { "type": "create_activity", "activity_type": "note", "body": "Lead score {{lead_score}} (fit {{fit_score}} / intent {{intent_score}}) - SQL. Route to a human within 24 hours." }
      ]
    }
  ]
}

And the prompt that keeps the scores alive - schedule it nightly in any agent runtime (Claude Code cron, a scheduled task, or your own loop):

You are the lead scoring agent for this Relm workspace. Run once per night.

Rubric v1 - FIT (0-50, no decay): industry exact ICP +15 or adjacent +8;
company size sweet spot +10 or one band off +5; role economic buyer +15
or champion +8; target geography +5; uses a tool we integrate with +5.
INTENT (0-50, decays by activity age from occurred_at): meeting or demo
attended +20; inbound hand-raise +15; reply to outreach +10; second
stakeholder engaged +10; proposal opened or repeat visits +5. Full value
to day 14, half from day 15-45, zero after day 45. Clamp both at 50.
lead_score = fit_score + intent_score.

Procedure:
1. Page through GET /v1/contacts (limit=100, follow next_cursor until
   has_more is false).
2. For each contact, GET /v1/activities?contact_id=... and score intent
   from each activity's occurred_at, never created_at.
3. Score fit from the contact and its company (GET /v1/companies/{id}
   when company_id is set).
4. If any score changed, PATCH /v1/contacts/{id} with custom_fields
   { fit_score, intent_score, lead_score, score_updated_at } and an
   Idempotency-Key of scoring-YYYY-MM-DD-{contact_id}.
5. PATCH one by one. Do NOT use POST /v1/batch for these writes - batch
   is event-silent, and the MQL/SQL automations listen for
   contact.updated.
6. Never write lifecycle directly; the threshold automations own it.
7. Finish by logging one summary activity: contacts scored, promotions
   to mql and sql, and the three biggest movers.

Apply it with your agent

If your agent is connected to Relm's MCP server (https://api.relmcrm.com/mcp - setup in give your AI agent a CRM), paste this:

Read the workspace schema. Register the five contact fields and the two
threshold automations from relmcrm.com/resources/lead-scoring-framework
(fit_score, intent_score, lead_score as number; lifecycle as text;
score_updated_at as date; "Flag MQL at 40" and "Flag SQL at 70").
Then run the nightly scoring procedure once now against all contacts,
using each activity's occurred_at for decay, and report the score
distribution and every contact promoted to mql or sql.

Or register the core field with one call and build up from there:

curl https://api.relmcrm.com/v1/fields \
  -H "Authorization: Bearer relm_test_..." \
  -H "Content-Type: application/json" \
  -d '{ "object": "contact", "key": "lead_score", "label": "Lead score", "data_type": "number" }'

Run it against a relm_test_ key first - test mode is free, isolated from live data, and automation email actions are simulated. Once scores are flowing, wire the SQL flag into a triage flow with the lead triage agent playbook.

FAQ

What is a good lead scoring threshold for MQL and SQL?

On a 0-100 scale split evenly between fit and intent, 40 works well for MQL and 70 for SQL. 40 means decent fit plus one real engagement, or strong fit with a weak signal - enough to justify automated nurture. 70 requires strong showings on both axes, which is what justifies a human's time. Add a fit floor (fit of at least 20) so intent alone can never make someone an SQL.

Should lead scores decay over time?

Intent should decay, fit should not. A demo attended five months ago is not buying intent today. A simple window scheme beats exponential math: intent events count full value for 14 days after they occurred, half value from day 15 to 45, and zero after 45 days. Firmographic fit describes who the lead is, so it stays constant until the underlying facts change.

Do I need machine learning for lead scoring?

Not below roughly 500 closed-won outcomes. Predictive models need labeled training data that small funnels do not have, they drift silently, and nobody can argue with an opaque score in pipeline review. A transparent point rubric applied consistently - by a human or an LLM agent - is auditable, versionable, and usually more accurate at small scale because you encode judgment the data cannot yet learn.

Should I use negative scoring?

Sparingly. Hard disqualifiers (student email, competitor domain, no budget territory) are better handled as a fit score of zero plus a do-not-pursue flag than as negative points, because negative points let a bad-fit lead claw back to MQL through activity volume. Reserve subtractions for one case: an explicit not-now reply, which should zero out accumulated intent.

How often should lead scores be recomputed?

Nightly is the right default. Decay means a score is stale the day after it was computed, so a scheduled recompute keeps the ranking honest without burning API quota. Pair the nightly batch with event-driven threshold automations so a lead that crosses 70 mid-day still gets flagged the moment the score is written.

Score leads with an agent, not a spreadsheet

1,000 requests a month on the Free plan, no card. See pricing.

Start free →