AI Lead Qualification with n8n
Build an AI pipeline that scores and routes HubSpot leads using Claude.
Introduction
30 Second Summary
Every business gets new leads, but not every lead deserves the same attention. The difference between a high-performing sales team and a drowning one is knowing which leads to chase first.
In this project, you will build an AI-powered lead qualification pipeline that automatically scores new contacts in HubSpot using Claude, then routes them to the right deal stage based on their quality.
What You'll Build
A complete n8n workflow that polls HubSpot for new contacts, sends their data to Claude for structured scoring, and writes the results back to HubSpot with conditional routing.
By the end of this project, you'll have:
- A HubSpot Private App with scoped permissions connected to n8n via App Token authentication.
- An AI lead qualification agent using Claude Haiku 4.5 that produces structured JSON scores, reasoning, and next actions for every new contact.
- A conditional routing system that moves Hot, Warm, and Cold leads into different pipeline stages with full error handling.
- Secret Mission: a company enrichment step where Claude generates personalized outreach messages stored directly on the HubSpot contact record.
Are there any prerequisites?
You need n8n running locally, a free HubSpot account, and an Anthropic API key. This guide covers the full setup for connecting these tools together in Step 1.
Before We Start
Before We Start...
Set Up HubSpot and n8n Credentials
Before you can build an automation that connects HubSpot and Claude, both tools need a secure way to talk to n8n. You will set that up now by creating API credentials for each service.
HubSpot uses Private Apps to grant scoped access to your CRM data. You will also create custom contact properties so that Claude's AI analysis has a place to live inside HubSpot.
In this step, get ready to:
- Create a HubSpot Private App with scoped CRM permissions.
- Add custom contact properties to store AI scoring results.
- Configure HubSpot and Anthropic credentials inside n8n.
Create a Private App in HubSpot
A Private App generates an access token that is scoped to only the permissions you choose. This keeps your integration secure because n8n can only read and write the CRM data you explicitly allow.
- Open your browser and sign in to your HubSpot account.
- Click the Settings gear icon in the top navigation bar.
- In the left sidebar, click Integrations, then select Private Apps.
- Click Create a private app.
- On the Basic Info tab, enter n8n Lead Qualifier as the app name.
- Click the Scopes tab.
- Click Add new scope.
- Use the search bar to find and select each of these five scopes:
- crm.objects.contacts.read
- crm.objects.contacts.write
- crm.objects.deals.read
- crm.objects.deals.write
- crm.schemas.contacts.read
- Click Update to save the scopes.
- Click Create app in the top right.
- In the confirmation dialog, click Continue creating.
- Click Show token, then click Copy to copy your access token. Save it somewhere safe for the next substep.
What is a Private App?
A HubSpot Private App gives you a static access token scoped to specific permissions. Unlike a full OAuth flow, it only works for your single HubSpot account. The token never expires, but you can rotate it at any time if it is compromised.
The scopes you selected allow n8n to read and write contacts and deals, and to read the contact schema (needed to see your custom properties).
Don't see Private Apps in your settings?
On some HubSpot accounts, Private Apps live under Development in the left sidebar, then Legacy apps. If you see that path instead, click Create legacy app and select Private in the dialog. The rest of the steps are the same.
You must be a Super Admin on the HubSpot account to create Private Apps. If you do not see the option at all, check your user permissions.
Help me find Private Apps in my HubSpot account
Create custom contact properties in HubSpot
You need dedicated fields on each contact record to store Claude's AI scoring output. HubSpot does not have these fields by default, so you will create three custom properties.
- In HubSpot Settings (the gear icon), click Properties in the left sidebar.
- Click the Select an object dropdown and choose Contact properties.
- Click Create property above the table.
Create the first property with these settings:
- Property label: AI Lead Score.
- Field type: Number.
- Click Create property to save.
Click Create property again and create the second property:
- Property label: AI Qualification Notes.
- Field type: Multi-line text.
- Click Create property to save.
Click Create property one more time for the third property:
- Property label: AI Qualified Date.
- Field type: Date picker.
- Click Create property to save.
Why create custom properties?
HubSpot's default fields cover standard CRM data like name, email, and lifecycle stage. Your AI pipeline produces new data (a numeric score, qualification notes, and a timestamp) that has no default home. Custom properties give n8n a place to write these values back to each contact record.
HubSpot automatically generates internal names from the labels you enter. For example, AI Lead Score becomes ai_lead_score internally. You will use these internal names later in your n8n workflow.
- Verify all three properties appear in the Contact properties list. You should see AI Lead Score, AI Qualification Notes, and AI Qualified Date listed.
Properties not appearing in the list?
Make sure the Select an object dropdown at the top is set to Contact properties. If you accidentally created a property under a different object (like Companies), you will need to recreate it under Contacts.
Help me find my custom contact properties in HubSpot
Configure credentials in n8n
Now you will tell n8n how to authenticate with both HubSpot and Anthropic. Once these credentials are saved, every node in your workflow can reuse them without you having to paste tokens again.
- Open your n8n instance in your browser (typically at http://localhost:5678).
- Click the menu icon in the top-left corner, then select Credentials.
- Click Add Credential (or New Credential) in the top right.
- Search for HubSpot and select it.
- Set the Authentication method to App Token.
- Paste the Private App access token you copied earlier into the Access Token field.
- Click Test Connection to confirm it works. You should see a green success message.
- Click Save.
Now add the Anthropic credential for Claude:
- Click Add Credential again.
- Search for Anthropic and select it.
- Paste your Claude API key from the Anthropic Console into the API Key field.
- Click Test Connection to verify. You should see a green success message.
- Click Save.
What is App Token auth?
HubSpot's App Token method uses the static access token from your Private App. Unlike OAuth (which requires redirect URLs and token refreshing), App Token auth is a single long-lived token. It is the simplest approach for integrations that connect to a single HubSpot account.
Test Connection failing?
For HubSpot: make sure you selected App Token as the auth method (not OAuth). Double-check that you copied the full token without trailing spaces.
For Anthropic: confirm your API key starts with sk-ant- and that your Anthropic account has billing enabled. A key without active billing will fail to authenticate.
Help me debug my n8n credential connection
Both credentials are now saved in n8n and ready to use across your workflow. Next up, you will build the trigger and contact retrieval nodes that kick off the whole pipeline.
Build the Trigger and Contact Retrieval
Your credentials are configured and tested. Now it's time to build the actual workflow that pulls new contacts from HubSpot on a regular schedule.
Every lead qualification pipeline starts with a trigger. You need something that regularly checks for new contacts so they can be scored as soon as they appear. In this step, you'll create the workflow, set up a polling trigger, and add a filter that prevents contacts from being scored twice.
In this step, get ready to:
- Create a new n8n workflow with a Schedule Trigger that polls every 5 minutes.
- Add a HubSpot node that fetches recently created contacts with key properties.
- Add an IF node that filters out contacts already qualified by a previous run.
Create a new workflow and add the Schedule Trigger
The workflow needs a starting point that fires automatically. A Schedule Trigger runs your workflow at fixed intervals, similar to a cron job.
- In your n8n browser tab, click the + button in the top left (or click Workflows in the sidebar, then Add workflow).
- Click the workflow name at the top of the canvas (it defaults to "My workflow").
- Rename it to AI Lead Qualification Pipeline and press Enter.
- Click Add first step on the canvas.
- Search for Schedule in the node search panel.
- Select Schedule Trigger to add it to the canvas.
The Schedule Trigger node opens automatically. Configure it to poll every 5 minutes:
- Set Trigger Interval to Minutes.
- Set Minutes Between Triggers to 5.
- Close the node panel by clicking the X or clicking the canvas background.
You should see a Schedule Trigger node on your canvas with "Every 5 minutes" displayed beneath it.
Why a Schedule Trigger instead of a HubSpot Trigger?
HubSpot's webhook trigger requires a Developer account and a public app with webhook configuration. It also only allows one active webhook at a time, which means activating a second trigger stops the first.
The Schedule Trigger with "Get Recently Created" is simpler, works on the Free tier without extra setup, and teaches the same integration pattern.
Don't see the Schedule Trigger node?
Make sure you're searching for Schedule (not "Cron" or "Timer"). The node is called "Schedule Trigger" in n8n's current version.
Help me find the Schedule Trigger node in n8n
Add the HubSpot node to fetch recently created contacts
With the trigger in place, the next node needs to reach into HubSpot and pull the latest contacts along with all the data Claude will need to qualify them.
- Click the + connector on the right side of your Schedule Trigger node.
- Search for HubSpot in the node search panel.
- Select the HubSpot node (not "HubSpot Trigger").
- In the Credential to connect with dropdown, select the HubSpot credential you configured in Step 1.
Now configure the node parameters:
- Set Resource to Contact.
- Set Operation to Get Recently Created.
- Set Return All to No.
- Set Limit to 10.
- Click Add Field under Additional Fields.
- Select Properties.
- Enter the following property names, separated by commas: email, firstname, lastname, company, jobtitle, lifecyclestage, hs_lead_status, notes_last_updated, createdate.
- Close the node panel.
What does this node do?
The "Get Recently Created" operation fetches contacts ordered by creation date. The limit of 10 keeps each run efficient.
The properties list tells HubSpot which contact fields to return. These are the exact data points Claude will use to score the lead: their name, email, company, job title, lifecycle stage, and lead status.
Your canvas should now show Schedule Trigger connected to the HubSpot node with a line between them.
Seeing a credential error on the HubSpot node?
Double-check that your HubSpot credential uses the App Token authentication method and that the Private App access token was pasted correctly in Step 1. You can re-test the credential by clicking Credentials in the n8n sidebar and selecting your HubSpot credential.
Help me fix my HubSpot credential connection in n8n
Add an IF node to skip already-qualified contacts
Without a filter, the workflow would re-process every contact on each run. The IF node checks whether a contact has already been scored and only passes unqualified contacts forward.
- Click the + connector on the right side of your HubSpot node.
- Search for IF in the node search panel.
- Select the IF node to add it to the canvas.
Configure the condition to check that the AI lead score is not yet set:
- In the IF node panel, click Add Condition.
- Select Number as the data type from the dropdown.
- In the Value 1 field, click the expression tab (the small toggle on the right side of the field).
- Enter the expression: {{ $json.properties.ai_lead_score }}.
- Set the comparison to does not exist.
- Close the node panel.
How does this filter work?
The expression {{ $json.properties.ai_lead_score }} references the custom property you created in Step 1. If a contact has never been qualified, this field won't exist on the contact record.
Contacts that pass the condition (score does not exist) flow through the true output. Contacts that already have a score flow through the false output and are ignored.
Your workflow canvas should now show three connected nodes: Schedule Trigger, HubSpot, and IF.
Not sure which output to use from the IF node?
The IF node has two outputs. The true output (top connector) passes contacts that match your condition. In the next step, you'll connect the AI Agent to this true output so only unqualified contacts get sent to Claude.
Help me understand the IF node outputs in n8n
Your data retrieval pipeline is built. Next up, you'll connect an AI Agent that takes each unqualified contact and asks Claude to score them.
Build the AI Lead Qualification Agent
Your workflow can now pull new contacts from HubSpot and filter out ones that have already been scored. The next piece is the brain of the operation: an AI agent that analyzes each contact and decides whether they are a hot, warm, or cold lead.
In this step, you will wire up an AI Agent node powered by Claude to your workflow. You will also engineer a system prompt that instructs Claude to return structured, parseable JSON every time.
In this step, get ready to:
- Add an AI Agent node and connect the Anthropic Chat Model sub-node.
- Write a system prompt that turns Claude into a lead qualification specialist.
- Build a dynamic prompt that feeds each contact's details to Claude for analysis.
Add the AI Agent node with Claude
The AI Agent node is n8n's built-in way to connect large language models to your workflow. It needs a Chat Model sub-node attached to it so it knows which model to call.
- In your n8n workflow canvas, click the + button on the true output of your IF node.
- Search for AI Agent and select it.
- The AI Agent node appears on the canvas. Click on it to open its settings panel.
- At the bottom of the AI Agent panel, click the + Chat Model button.
- Select Anthropic Chat Model from the list.
What is the Chat Model sub-node?
Sub-nodes in n8n attach to root nodes and extend their functionality. The Anthropic Chat Model sub-node tells the AI Agent which model to call and how to authenticate. Without it, the AI Agent has no language model to work with.
- In the Anthropic Chat Model sub-node settings, select your Anthropic credential from the Credential dropdown.
- Set the Model to Claude Haiku 4.5.
- Under Options, set Maximum Number of Tokens to 500.
- Close the sub-node panel to return to the AI Agent node.
Why Haiku 4.5 instead of Sonnet?
For structured tasks like lead scoring with a well-engineered prompt, Haiku 4.5 is more than capable. It costs $1 per million input tokens compared to Sonnet's $3 per million. Over hundreds of leads, that cost difference adds up fast.
You should now see the AI Agent node on your canvas with the Anthropic Chat Model sub-node connected beneath it.
Seeing 'A Chat Model sub-node must be connected' error?
This means the Anthropic Chat Model sub-node did not attach properly. Click the AI Agent node to open it, then click the + Chat Model button again and re-select Anthropic Chat Model.
Help me fix the Chat Model sub-node connection error.
Configure the system prompt for lead qualification
The system prompt is where you engineer Claude's behavior. A good system prompt turns a general-purpose model into a specialist that returns consistent, structured output every single time.
- Click on the AI Agent node to open its settings.
- Scroll down and click Options to expand the options section.
- Click Add Option and select System Message.
- Paste the following system prompt into the System Message field:
You are an expert B2B lead qualification agent working for a marketing agency. Your job is to analyze incoming contact data and produce a structured qualification assessment.
Analyze the contact and return ONLY a JSON object with these exact fields:
- score: A number from 0-100 representing lead quality
- tier: One of exactly HOT, WARM, or COLD
- reasoning: A 1-2 sentence explanation of why you scored them this way
- next_action: A specific recommended next step for the sales team
Scoring criteria:
- 80-100 (HOT): Has a company, relevant job title (marketing, media, operations, founder), clear intent signals
- 50-79 (WARM): Has some qualifying info but missing key signals
- 0-49 (COLD): Minimal info, no company, generic email, or likely spam
Always respond with valid JSON only. No markdown, no explanation outside the JSON.
What does this system prompt do?
- The opening line establishes Claude's role as a B2B specialist, which anchors all its decisions.
- The JSON schema section forces Claude to return exactly four fields in a predictable structure your workflow can parse.
- The scoring criteria give Claude concrete rules so it does not invent its own interpretation of "hot" or "cold."
- The final instruction ("valid JSON only") prevents Claude from wrapping its response in markdown code fences or adding explanatory text.
Save the prompt externally
Copy this system prompt into a text file on your computer as well. If you ever need to rebuild the workflow or tweak the scoring criteria, having it saved separately saves time.
Set up the dynamic prompt with contact data
The system prompt tells Claude how to behave. The dynamic prompt tells Claude what to analyze. You need to pass each contact's details as variables so Claude can score them individually.
- In the AI Agent node settings, find the Prompt parameter at the top.
- Change it from Connected Chat Trigger Node to Define below.
- In the Text field that appears, paste the following expression:
Qualify this lead:
Name: {{ $json.properties.firstname }} {{ $json.properties.lastname }}
Email: {{ $json.properties.email }}
Company: {{ $json.properties.company }}
Job Title: {{ $json.properties.jobtitle }}
Lifecycle Stage: {{ $json.properties.lifecyclestage }}
Lead Status: {{ $json.properties.hs_lead_status }}
What are the double-curly-brace expressions?
n8n uses {{ }} syntax to pull data from earlier nodes in the workflow. Each $json.properties.* reference grabs a specific field from the HubSpot contact that passed through the IF node.
When the workflow runs, n8n replaces each expression with the real contact's data. Claude then sees a plain-text summary like "Name: Jane Smith" rather than raw code.
- Click Back to canvas or close the AI Agent node panel.
Your workflow canvas should now show a chain of four connected nodes: Schedule Trigger, HubSpot, IF, and AI Agent (with the Anthropic Chat Model sub-node visible beneath it).
Seeing 'No prompt specified' error?
This happens when the Prompt parameter is still set to "Connected Chat Trigger Node" instead of "Define below." Open the AI Agent node, find the Prompt dropdown, and switch it to Define below.
Help me fix the 'No prompt specified' error on my AI Agent.
Seeing '400 Invalid value for content: expected a string, got null'?
This means one of your {{ $json.properties.* }} expressions is resolving to null because the contact is missing that field. This is expected for test runs without real data. You will create proper test contacts in Step 5.
Help me troubleshoot null values in my AI Agent expressions.
Your AI agent is now fully configured. It knows what role to play, what output format to produce, and what contact data to analyze. Next, you will build the routing logic that reads Claude's response and takes different actions for hot, warm, and cold leads.
Route Leads and Update HubSpot
Your AI Agent is now producing structured JSON with a score, tier, reasoning, and next action for every contact it analyzes.
The problem is that this JSON is still just a text string sitting in the workflow. It needs to be parsed into usable fields, routed to the correct path based on the tier, and written back to HubSpot so the sales team can actually see the results. In this step, you will close the loop by turning Claude's analysis into real CRM data.
In this step, get ready to:
- Parse Claude's JSON response into separate fields your workflow can use.
- Route leads into HOT, WARM, or COLD paths using a Switch node.
- Update HubSpot contacts with AI scores and create deals for hot leads.
Parse Claude's JSON response
Claude returns its analysis as a JSON string inside the AI Agent's output field. Before you can route leads or update HubSpot, you need to parse that string into individual fields like score, tier, reasoning, and next_action.
- Click the + button after the AI Agent node to add a new node.
- Search for Code and select the Code node.
- Set the Language to JavaScript.
- Replace the default code with the following expression to parse Claude's JSON output:
// Parse Claude's JSON response into separate fields
const aiOutput = JSON.parse($input.first().json.output);
return [{
json: {
// Pass through the original contact ID for the HubSpot update
id: $input.first().json.id,
firstname: $input.first().json.properties.firstname,
lastname: $input.first().json.properties.lastname,
// Extracted AI qualification fields
score: aiOutput.score,
tier: aiOutput.tier,
reasoning: aiOutput.reasoning,
next_action: aiOutput.next_action
}
}];
What does this code do?
JSON.parse($input.first().json.output) takes the text string that Claude returned and converts it into a JavaScript object with named properties.
The return statement passes through the original contact id (so you can update the right HubSpot record later) alongside the four extracted AI fields.
- Click Execute Node (the play button) to test the Code node.
- In the Output panel on the right, you should see the individual fields (score, tier, reasoning, next_action) displayed as separate values instead of one big text block.
Seeing a JSON parse error?
This usually means the AI Agent node has not been executed yet in this test session. Click back on the AI Agent node and execute it first so the Code node has input data to parse.
If the AI Agent has run but you still see a parse error, Claude may have included markdown formatting (like backticks) around the JSON. You will add error handling for this in the next step.
Help me debug my Code node JSON parse error in n8n
Add a Switch node for routing
Now that you have the tier value extracted as its own field, you can send each lead down a different path based on whether Claude rated them HOT, WARM, or COLD.
- Click the + button after the Code node to add a new node.
- Search for Switch and select the Switch node.
- In the Switch node settings, configure three routing rules.
Set up Route 1 (HOT leads):
- Click Add Routing Rule.
- Set Value 1 to the expression {{ $json.tier }}.
- Set Operation to equals.
- Set Value 2 to HOT.
Set up Route 2 (WARM leads):
- Click Add Routing Rule.
- Set Value 1 to the expression {{ $json.tier }}.
- Set Operation to equals.
- Set Value 2 to WARM.
Set up Route 3 (COLD leads):
- Click Add Routing Rule.
- Set Value 1 to the expression {{ $json.tier }}.
- Set Operation to equals.
- Set Value 2 to COLD.
What is the Switch node doing?
The Switch node is like a traffic intersection. It reads the tier value from the parsed AI output and sends the data down a different path depending on whether the lead is HOT, WARM, or COLD.
Each output path can have different follow-up nodes. This lets you create a Deal for HOT leads without creating one for COLD leads.
- You should now see the Switch node on your canvas with three output connectors labeled for each route.
Update HubSpot contacts with AI results
Every lead, regardless of tier, needs its AI qualification results written back to HubSpot. This means connecting a HubSpot Update node to all three routes of the Switch node.
Start by adding the Update Contact node to the first route (HOT). You will connect the same configuration to the other routes afterwards.
- Click the + button on Route 1 (HOT) of the Switch node.
- Search for HubSpot and select the HubSpot node.
- Set Resource to Contact.
- Set Operation to Update.
- Set Contact ID to the expression {{ $json.id }} (this references the original HubSpot contact ID passed through from the Code node).
Now add the custom properties to update under Additional Fields:
- Click Add Field and select Properties.
- Add a property with Name ai_lead_score and Value set to the expression {{ $json.score }}.
- Add a second property with Name ai_qualification_notes and Value set to the expression {{ $json.reasoning + ' | Next action: ' + $json.next_action }}.
- Add a third property with Name ai_qualified_date and Value set to the expression {{ new Date().toISOString().split('T')[0] }} (this gives today's date).
- Now connect the same HubSpot Update Contact node to Route 2 (WARM) and Route 3 (COLD) outputs of the Switch node. Drag a connection from each route output to the input of the same HubSpot Update node.
Why connect all three routes to one node?
Every contact gets their AI score and notes written back to HubSpot, regardless of whether they are HOT, WARM, or COLD. By connecting all three Switch outputs to the same Update node, you avoid duplicating the same configuration three times.
For HOT leads specifically, you also want to create a Deal in HubSpot so the sales team can start working them immediately.
- Click the + button after the HubSpot Update Contact node.
- Add another HubSpot node.
- Set Resource to Deal.
- Set Operation to Create.
- Set Deal Name to the expression Opportunity - {{ $json.firstname }} {{ $json.lastname }}.
- Set Pipeline to Default (your HubSpot's default sales pipeline).
- Set Deal Stage to Appointment Scheduled (or your pipeline's first active stage).
- Under Additional Fields, add Associated Contact ID and set it to the expression {{ $json.id }} to link the deal to the contact.
Why only create deals for HOT leads?
Creating a deal signals to the sales team that this lead is ready for active engagement. WARM and COLD leads get their scores recorded, but they do not clutter the pipeline with premature opportunities.
- Now you need to ensure this Create Deal node only runs for HOT leads. Disconnect it from the WARM and COLD paths if n8n auto-connected them. Only the Route 1 (HOT) path from the Switch should flow through the Update Contact node and then into the Create Deal node.
Arrange your canvas
Your workflow canvas may look messy at this point. Drag nodes to arrange them so the flow is clear: AI Agent to Code to Switch, with all three routes feeding into the Update Contact node, and only the HOT route continuing to the Create Deal node.
Your routing and CRM update logic is now in place. Next up, you will add error handling to make this workflow production-ready and test it end-to-end with real contacts in HubSpot.
Add Error Handling and Test End-to-End
Your workflow can now score leads and route them to the right pipeline stage. That's impressive, but it has a gap.
What happens when Claude returns an unexpected format? Maybe the API times out, or the response isn't valid JSON. In production, a broken step can silently halt the entire pipeline. In this step, you'll add error handling that catches failures gracefully, then test the full workflow with real contacts in HubSpot.
In this step, get ready to:
- Add production error handling to the AI Agent node so the workflow never silently breaks.
- Create three test contacts in HubSpot that represent HOT, WARM, and COLD leads.
- Run the full pipeline end-to-end and verify the results in HubSpot.
Add error handling to the AI Agent node
Production workflows need to handle failure without stopping. If Claude returns malformed text or the API call fails entirely, your pipeline should still record a result and move on.
- In your n8n workflow, click the AI Agent node to open its settings.
- Click Settings (the gear icon at the top of the node panel).
- Find the On Error dropdown and change it from Stop Workflow to Continue on Fail.
- Close the AI Agent node settings.
Why Continue on Fail?
When a node is set to Continue on Fail, it passes the error information downstream instead of halting the entire workflow. This lets you catch the failure in the next node and handle it gracefully.
This is critical for production workflows. OFO Collective's clients need systems that never silently break.
Now you need a node that checks whether the AI Agent's output is valid JSON before the pipeline tries to parse it.
- Add a new IF node between the AI Agent node and your existing Code/Set node (the one that parses the JSON).
- Connect the AI Agent node's output to this new IF node.
- Set the IF condition to check that $json.output contains a valid JSON structure. Use the condition: $json.output is not empty AND contains the text "score".
- Connect the true output to your existing Code/Set node (the normal path that parses score, tier, reasoning, and next_action).
Next, create the fallback path for when the AI output is invalid or the node failed.
- Add a new Set node and connect it to the false output of the IF node.
- In the Set node, add the following fields:
- Set score to 0 (Number type).
- Set tier to COLD (String type).
- Set reasoning to AI qualification failed - manual review needed (String type).
- Set next_action to Manual review required (String type).
- Connect this Set node to a HubSpot Update Contact node that writes the default values to the contact (same configuration as your existing Update Contact nodes: sets ai_lead_score, ai_qualification_notes, and ai_qualified_date).
What does the fallback path do?
If Claude returns garbage or the API call fails entirely, the contact still gets updated in HubSpot with a score of 0 and a clear note saying manual review is needed. No lead falls through the cracks.
The sales team sees the note and knows to review that contact themselves, rather than wondering why nothing happened.
Can't connect the IF node between existing nodes?
In n8n, you can disconnect existing connections by clicking on the line between two nodes and pressing Delete. Then reconnect the AI Agent output to your new IF node, and the IF node's true output to the original parsing node.
Help me rewire my n8n workflow to add the error handling IF node
Create test contacts and run the workflow
You need contacts that represent each scoring tier so you can confirm the full pipeline works correctly.
- In HubSpot, click Contacts in the top navigation bar.
- Click Create contact in the top right.
Create the first test contact. This one represents a HOT lead with strong qualifying signals.
- Set First name to Jane.
- Set Last name to Smith.
- Set Email to jane@mediacorp.com.
- Set Job title to CMO.
- Set Company name to MediaCorp.
- Click Create contact.
Create the second test contact. This one represents a WARM lead with some qualifying info but missing key signals.
- Click Create contact again.
- Set First name to Bob.
- Set Last name to Johnson.
- Set Email to bob.j@gmail.com.
- Set Job title to Marketing Coordinator.
- Leave Company name empty.
- Click Create contact.
Create the third test contact. This one represents a COLD lead with minimal information.
- Click Create contact again.
- Set First name to Test.
- Set Last name to User.
- Set Email to test123@mailinator.com.
- Leave all other fields empty.
- Click Create contact.
Why these three specific contacts?
Each contact is designed to trigger a different tier in your scoring criteria. Jane has a company, a senior title, and a corporate email (HOT signals). Bob has a relevant title but no company and a personal email (WARM signals). Test User has almost nothing (COLD signals).
Testing all three tiers confirms your Switch node routes correctly and each HubSpot update path works.
Now activate your workflow and trigger a test run.
- Switch back to your n8n workflow.
- In the top right corner, toggle the Active switch to turn the workflow on.
- Click Execute Workflow (the play button) to trigger a manual test run instead of waiting for the next scheduled poll.
The workflow runs through every node in sequence. You can watch the execution in real time as data flows from left to right.
Workflow execution failed?
If you see a red error on the HubSpot node, double-check that your HubSpot credential is still connected and the Private App token hasn't expired. If the AI Agent node fails, confirm your Anthropic credential has a valid API key with available credits.
If the IF node (JSON check) routes everything to the false path, open the AI Agent node's output and check what Claude actually returned. The output might have markdown wrapping (like ```json) that your condition doesn't account for.
Help me debug my n8n workflow execution errors
Verify results in HubSpot
The workflow has run. Now you need to confirm that every piece of data landed where it should in HubSpot.
- In HubSpot, navigate to Contacts and click on Jane Smith.
- In the left sidebar of her contact record, scroll down to find the AI Lead Score property. Confirm it shows a number in the 80-100 range.
- Check that AI Qualification Notes contains Claude's reasoning about why Jane is a strong lead.
- Check that AI Qualified Date is set to today's date.
- Navigate to Sales then Deals in the top menu. Confirm a deal named Opportunity - Jane Smith exists and is associated with her contact record.
Now verify the other two contacts.
- Go back to Contacts and click on Bob Johnson. Confirm his AI Lead Score is in the 50-79 range (WARM) and his notes reference the missing company information.
- Click on Test User. Confirm the AI Lead Score is in the 0-49 range (COLD) and the notes mention the lack of qualifying information.
- Confirm that neither Bob nor Test User has an associated Deal (only HOT leads get deals).
Finally, review the execution logs in n8n to see the full data flow.
- In n8n, click Executions in the left sidebar.
- Click on the most recent execution to open its details.
- Click through each node to see the data that passed through it. Confirm the AI Agent output contains valid JSON with score, tier, reasoning, and next_action for each contact.
- Take a screenshot of the successful workflow execution showing all nodes completed (green checkmarks).
- Take a screenshot of one of the HubSpot contact records showing the populated AI properties.
Save these screenshots for your portfolio
The workflow execution view and the HubSpot records with AI-populated fields are your proof that you can build exactly the type of systems OFO Collective delivers to clients. Export your n8n workflow as JSON too (click ... then Download in the workflow editor).
Contacts not showing AI properties?
If the custom properties appear empty, check two things. First, make sure the internal property names in your HubSpot Update Contact node match exactly: ai_lead_score, ai_qualification_notes, ai_qualified_date. Second, confirm that the Contact ID being passed to the Update node matches the original contact from the HubSpot Get Recently Created node.
If the properties aren't visible on the contact record at all, you may need to add them to the visible properties. Click View all properties on the contact record and search for them.
Help me figure out why my HubSpot contact properties aren't being updated by n8n
Secret mission
Add Company Enrichment with Personalized Outreach
Your lead qualification pipeline scores contacts and routes them to the right stage. But what if it could also draft personalized outreach messages for your best leads? Add a second AI call that turns a scoring system into an actionable outreach tool.
Clean Up Your Resources
Clean Up Your Resources
Decide whether to keep your resources running, pause them to come back later, or delete them entirely.
This project uses n8n locally (no hosting cost) and HubSpot Free tier (no subscription cost). The only ongoing cost is Claude API usage, which occurs each time your workflow runs and calls the Anthropic API.
Cost warning
If your n8n workflow stays active and runs every 5 minutes, it will call the Claude API on every new unqualified contact. At Haiku 4.5 pricing ($1/MTok input, $5/MTok output), each qualification costs fractions of a cent. However, this adds up if you leave it running indefinitely with no new contacts to process.
If you are done testing, either pause or delete the workflow to avoid unnecessary API charges.
Resources you used:
- n8n workflow ("AI Lead Qualification Pipeline") running locally.
- HubSpot Private App ("n8n Lead Qualifier") with CRM scopes.
- HubSpot custom contact properties (AI Lead Score, AI Qualification Notes, AI Qualified Date).
- Anthropic API key stored in n8n credentials.
- HubSpot credential stored in n8n.
- Test contacts created in HubSpot (Jane Smith, Bob Johnson, Test User).
Keep everything running
No action needed. Choose this if you are still actively building or plan to extend the workflow soon.
- Your n8n workflow will continue polling HubSpot every 5 minutes and calling the Claude API for new unqualified contacts.
- Monitor your Anthropic Console usage dashboard to keep an eye on API costs.
Pause - I'll come back to this later
Deactivate the workflow to stop API calls while keeping everything configured for when you return.
- In n8n, open your "AI Lead Qualification Pipeline" workflow.
- Toggle the workflow from Active to Inactive using the switch in the top right.
- Your credentials, nodes, and configuration remain saved. Toggle it back to Active when you are ready to resume.
- Your HubSpot Private App and custom properties remain in place with no ongoing cost.
Delete - I don't want to use this again
Remove all project resources and start fresh.
- In n8n, open the workflow and click the three-dot menu, then select Delete.
- Go to n8n Credentials and delete both the HubSpot and Anthropic credentials.
- In HubSpot, navigate to Settings, then Integrations, then Private Apps. Find "n8n Lead Qualifier" and delete it.
- In HubSpot, navigate to Settings, then Properties, then Contact Properties. Delete the three custom properties: "AI Lead Score", "AI Qualification Notes", and "AI Qualified Date".
- Delete the three test contacts (Jane Smith, Bob Johnson, Test User) from your HubSpot CRM.
- Optionally, revoke your Anthropic API key in the Anthropic Console if you no longer need it.
Nice Work!
Nice Work!
Nice work! You just built a production-quality AI-powered lead qualification pipeline that automatically scores, routes, and updates contacts in HubSpot using Claude and n8n.
This is exactly the type of system OFO Collective builds for their agency clients. You now have documented proof that you can wire up CRMs, AI agents, and workflow automation into clean, reliable pipelines.
Here's what you learned:
- Connected HubSpot CRM to n8n using a Private App with scoped permissions, custom contact properties, and full read/write access to contacts and deals.
- Built an AI lead qualification agent with a carefully engineered system prompt that produces structured, parseable JSON output every time.
- Implemented conditional routing and production error handling so the workflow scores leads as Hot, Warm, or Cold and never silently fails.
- Secret Mission: Added multi-step AI enrichment that chains a second Claude call to generate personalized outreach messages stored directly on HubSpot contact records.
Ready to quiz yourself?