A working n8n workflow built against your brief. Ten sample submissions were put through it, scored by Claude against a four criteria rubric, written into a real HubSpot portal, and the hot ones announced in Slack. This page is the record of that run.
Not a mockup. An n8n instance, a published workflow on a live webhook, ten POSTs, and the results read back out of HubSpot afterwards.
Every submission answered in about 3 seconds end to end. The duplicate and the malformed one answered in well under a second, because neither needs to call a model.
The reason text below is what the model wrote at the time. It is stored on the contact record, so anyone looking at the lead later can see why it was scored that way.
| Ref | Who | Score | Why |
|---|---|---|---|
| SUB-1041 | Dana Whitfield North Harbor Outfitters |
Hot | Founder-led ecommerce replatforming with strong budget ($35-50K), clear timeline (September kickoff, holiday deadline), and in-scope work (migration, build, subscription integration). |
| SUB-1042 | Marcus Bell Lattice Supply Co |
Hot | CEO of supply company with stated budget, hard deadline tied to trade show event, clear marketing site scope with CRM integration, and strong authority. |
| SUB-1043 | Priya Raman Meridian Ops |
Hot | VP Marketing with approved budget in stated range, clear timeline within the month, in-scope marketing site rebuild project, and strong authority to decide. |
| SUB-1044 | Tom Ashby Ashby Joinery |
Cold | In-scope fit but weak on budget (below minimum engagement), no timeline urgency, and while the owner has strong authority, only one of three commercial factors is strong. |
| SUB-1045 | Elena Kovac Brightfold |
Warm | In-scope marketing site project with strong budget signal and middling authority, but timeline is vague and exploratory. |
| SUB-1046 | Jamie Ortiz |
Cold | Out of scope: student work with no budget and no commercial project. |
| SUB-1047 | Growth Partner Outreach RankVelocity |
Cold | Out of scope: they are pitching their own SEO link services to us, not seeking our services for a project. |
| SUB-1048 | Chris Lam Peakfield Consulting |
Cold | Out of scope: logo tweaks are not in our service offerings, and the prospect is an intern without budget authority. |
| SUB-1049 | (no name given) Unnamed |
review queue | flagged |
| SUB-1050 | Priya Raman Meridian Ops |
duplicate | The same person filling the form a second time, which is what actually happens when someone is not sure the first one went through. Identical content, different submission id. |
The people and companies here are invented for this demo. The addresses use the reserved example.com domain, so nothing on this page belongs to anyone.
The workflow as it stands in n8n. 20 nodes, including both paths out to the review queue.
Your brief asked for documented handling of failed and malformed submissions. The rule here is that anything unscoreable is handed to a person, never guessed at and never silently dropped.
Two of the four criteria cannot be assessed at all, so it is not sent to the model. This is the payload the review queue actually received during the run:
{
"queue": "lead-review",
"reason": "incomplete_submission",
"detail": "no email address; no description of the work",
"submission_id": "SUB-1049",
"email": "",
"received_at": "2026-07-28T12:40:27.321Z"
}
If the reply does not parse, or carries a score outside Hot, Warm and Cold, the same review path is taken. It would have been easier to default those to Cold. That is exactly the wrong default, because Cold is where a mis-read hot lead would quietly go to die.
People resubmit when they are not sure the first one went through. The fingerprint of the answers is stored on the contact, so a repeat is recognised and ignored rather than overwriting a good score and firing a second alert. In the run above, SUB-1050 was SUB-1043 sent again, and it was caught.
Each of the three Hot leads raised a notification in Slack. This is the channel afterwards, not a mockup of one.
Posted through a Slack incoming webhook as a Block Kit message, so the fields stay readable on a phone. The submission reference and rubric version sit in the footer of each message, which means a notification can always be traced back to the record it came from.
The point of putting the reason in the notification is that a score on its own is not actionable. Whoever picks the lead up can see what the score was based on without opening the CRM, and can tell immediately when the model has read something the wrong way.
Read back from the portal through the API after the run, not captured on the way in. This is the first lead's contact record as HubSpot holds it.
{
"email": "dana.whitfield [at] northharbor.example.com",
"firstname": "Dana",
"lastname": "Whitfield",
"company": "North Harbor Outfitters",
"jobtitle": "Founder",
"lead_score": "Hot",
"lead_score_reason": "Founder-led ecommerce replatforming with strong budget ($35-50K), clear timeline (September kickoff, holiday deadline), and in-scope work (migration, build, subscription integration).",
"lead_score_criteria": "{\"budget\":\"strong\",\"timeline\":\"strong\",\"fit\":\"in_scope\",\"authority\":\"strong\"}",
"lead_rubric_version": "v1.2",
"lead_submission_id": "SUB-1041",
"lead_scored_at": "2026-07-28T12:39:56.914Z"
}
Writes went to a HubSpot developer test portal. On your side the same nodes point at your portal through your own private app token, and the seven lead fields are created once.
Both of these are the sort of thing worth knowing before a build rather than after, which is why the run happened first.
An automated score that moves when you re-run it is not worth having. Three submissions were scored five times each at temperature zero:
| Ref | Runs | Scores returned | Result |
|---|---|---|---|
| SUB-1041 | 5 | Hot, Hot, Hot, Hot, Hot | identical every time |
| SUB-1044 | 5 | Cold, Cold, Cold, Cold, Cold | identical every time |
| SUB-1045 | 5 | Warm, Warm, Warm, Warm, Warm | identical every time |
SUB-1044 is a small but real project from an owner with a stated budget. It came back Cold. The rubric said a budget below the minimum engagement is weak, but never said what the minimum was, so the model picked one:
In-scope fit but weak on budget (below minimum engagement), no timeline urgency, and while the owner has strong authority, only one of three commercial factors is strong.
Adding one sentence to the rubric moved it to Warm, where it belongs:
The minimum engagement is $5,000. Anything at or above that is not weak on budget. In-scope fit with strong budget and authority, but timeline is weak and vague.
Nothing in the workflow changed. That is the point of keeping the rubric as a document the workflow reads rather than logic buried in a node: the criteria stay yours to edit.
A stand in written for this demo, in the shape the real one would take. Yours would replace it.
Budget signal. A stated range at or above the minimum engagement, an existing vendor being replaced, or a funded project counts as strong.
Timeline. A named date or an event they are working backwards from is strong. Just exploring is weak. Silence is neutral, not weak.
Fit. The work is either the kind of work being sold or it is not. One off graphics, link packages, student work and inbound vendor pitches are not.
Authority. Founder, owner and VP are strong. Manager is middling. Intern or no stated role is weak.
Hot means strong on fit and at least two of the other three. Warm means in scope with one strong signal. Cold means out of scope, or in scope and weak everywhere else. Fit is the gate, so a vendor pitch quoting a large number is still a vendor pitch. That rule is why SUB-1047 scored Cold despite naming the largest budget of the ten.
The export below is taken from the running instance after the run, so it is the same workflow that produced everything on this page. It carries no credentials.
Import it into any n8n instance. It expects two credentials, a HubSpot private app token and an API key for the model, and the seven lead fields on the contact record.