n8n's HubSpot integration is powerful — triggering on contact updates, deal stage changes, or new form submissions, then running AI to draft outreach, qualify leads, or summarize calls. But every workflow execution is stateless. The AI has no memory of this contact's past interactions, objections raised, or promises made.
This guide shows how to add persistent per-contact memory to any n8n HubSpot AI workflow using the retainr community node.
The Problem with Stateless HubSpot AI in n8n
A typical n8n HubSpot AI workflow looks like this:
- HubSpot Trigger — contact stage change or new contact
- OpenAI node — generate personalized email
- Gmail node — send the email
The AI output is generic. It generates the same quality response for a brand-new lead and a contact with six months of relationship history — because it genuinely has no idea the history exists.
With retainr:
- HubSpot Trigger
- retainr Search Memory — retrieve all past AI interactions with this contact
- OpenAI node — generate response with full relationship context
- Gmail node — send
- retainr Store Memory — log this interaction for next time
The AI now knows what was discussed, what objections were raised, and what was promised.
Setup
Step 1: Install the retainr community node
In n8n, go to Settings → Community Nodes → Install. Enter n8n-nodes-retainr. Click Install. Add a retainr credential with your API key from retainr.dev/dashboard.
Step 2: Connect HubSpot
Add a HubSpot credential in n8n using your HubSpot Private App access token (or OAuth). Configure the HubSpot Trigger node to watch for the events you care about: contact property changes, deal stage updates, new contacts.
Step 3: Add the Search Memory node
After the HubSpot trigger, add a retainr → Search Memory node:
- Namespace:
hubspot:{{ $json.id }}— uses the HubSpot contact ID - Query:
{{ $json.properties.hs_latest_source_data_1 ?? $json.properties.email }}— or any field representing the current context - Limit: 5
This retrieves the 5 most relevant past memories for this contact. Empty array for new contacts — handled gracefully.
Step 4: Configure the AI node
In the OpenAI node (or AI Agent), add memory to the system prompt:
You are a CRM-aware sales assistant.
Contact memory for {{ $('HubSpot Trigger').item.json.properties.email }}:
{{ $('Search Memory').item.json.results.map(r => r.content).join('\n') || 'No prior history.' }}
Current context: {{ $json.properties.lifecyclestage }} stage contact.
Draft a personalized response that acknowledges the relationship history.
Step 5: Add the Store Memory node
After the AI step, add a retainr → Store Memory node:
- Namespace:
hubspot:{{ $('HubSpot Trigger').item.json.id }} - Content:
{{ $json.lifecyclestage }}: {{ $('OpenAI').item.json.text.substring(0, 250) }}
Namespace Patterns for HubSpot
| Workflow | Namespace |
|---|---|
| Per contact | hubspot:{contact_id} |
| Per deal | hubspot:deal:{deal_id} |
| Per company | hubspot:company:{company_id} |
| Contact by email (stable across record recreations) | email:{contact_email} |
Use hubspot:{contact_id} for most workflows. Switch to email:{contact_email} when contacts may be deleted and recreated — the email namespace persists even if the HubSpot record ID changes.
High-Value HubSpot AI Use Cases
Deal follow-up automation
When a deal moves stage in HubSpot, n8n triggers and the AI drafts the next follow-up email. With memory, it knows about the pricing objection from two weeks ago and addresses it directly. Without memory, it sends a generic "checking in" email.
Trigger: HubSpot → Deal Stage Changed
Memory namespace: hubspot:deal:{deal_id}
Store: objections raised, commitments made, next steps agreed
New contact enrichment
When a new lead submits a form, the AI generates a personalized welcome. When the same person submits a second form three months later, the AI knows this — and the second response acknowledges the prior engagement.
Trigger: HubSpot → New Contact
Memory namespace: email:{contact_email}
Store: original inquiry topic, lead source, initial interest
Sales call prep
Before a scheduled call, trigger an n8n workflow that retrieves the full memory for this contact and generates a briefing: what was discussed, what was promised, what to cover today.
Trigger: HubSpot → Meeting Booked (webhook)
Memory namespace: hubspot:{contact_id}
Store: call notes, action items
Churn prevention
When a customer's health score drops or they stop engaging, retrieve the full interaction history and generate a personalized outreach that references specific past touchpoints — not a generic "we miss you" template.
Trigger: HubSpot → Contact Property Changed (health score)
Memory namespace: hubspot:{contact_id}
Store: engagement summary per quarter
Writing Memory Back to HubSpot
After storing memory in retainr, also write a summary back to HubSpot as a Note so human reps can see it:
HubSpot node:
Operation: Create Note
Contact ID: {{ $('HubSpot Trigger').item.json.id }}
Body: {{ $('OpenAI').item.json.text }}
Now both systems stay in sync: retainr for AI-retrievable semantic memory, HubSpot for human-readable CRM timeline.
Give your AI agents a real memory
Free plan includes 1,000 memory operations/month. No credit card required.
Add memory to your n8n HubSpot workflow — free plan →Frequently Asked Questions
How is retainr different from HubSpot's timeline for AI? HubSpot's timeline is human-readable and chronological. retainr uses semantic search — when a new email arrives mentioning "pricing", retainr retrieves the most relevant past memories about pricing discussions, not just the most recent note. This distinction matters when you have months of contact history.
Does this work with n8n's HubSpot webhook node? Yes. You can trigger the workflow via HubSpot's outbound webhook (configured in HubSpot Workflows) pointing to an n8n webhook URL. The retainr nodes work identically regardless of how the n8n workflow is triggered.
Can I use the same retainr namespace across n8n and Make.com? Yes. If you use hubspot:{contact_id} in n8n and hubspot:{contact_id} in Make.com, both platforms share the same memory pool for each contact. The AI on any platform sees the full history.
What n8n plan do I need? Community nodes require n8n Cloud Starter or above, or any self-hosted n8n instance. On n8n Cloud Free, replace the retainr community nodes with HTTP Request nodes calling the retainr REST API directly.
Add memory to any n8n workflow
Working with a different app? These guides cover the same pattern:
- n8n Gmail AI Memory — Per-sender memory for Gmail AI workflows
- n8n Zendesk AI Memory — AI memory for support ticket workflows
- n8n Airtable AI Memory — Persistent memory for Airtable workflows
- n8n WhatsApp AI Memory — Persistent memory for WhatsApp bots
- n8n Slack AI Memory — Persistent memory for Slack bots