Build an AI Sales Agent with n8n — Step-by-Step Guide 2026
What You’ll Learn
By the end of this tutorial, you’ll have built a complete AI sales agent that:
- Scrapes prospect lists from Apollo.io or LinkedIn Sales Navigator
- Researches each prospect using web search + Perplexity
- Generates hyper-personalized cold email copy with GPT-4o
- Handles replies autonomously (objections, follow-ups, FAQs)
- Books qualified meetings into Calendly or HubSpot
Prerequisites: n8n instance (self-hosted or cloud), OpenAI API key, basic familiarity with the n8n visual editor.
Step 1: Set Up Your n8n Environment
Start by creating a new workflow in n8n named AI Sales Agent v1. Configure the following credential variables:
OPENAI_API_KEY— GPT-4o for email generation and reply classificationOPENAI_API_KEY_EMBED— text-embedding-3-small for prospect vector storagePERPLEXITY_API_KEY— for company deep-research nodesAPOLLO_API_KEY— (optional) for prospect importSMTP_CREDENTIALS— for sending emailsHUBSPOT_API_KEYorCALENDLY_API_KEY— for meeting booking
In n8n, store these under Settings → Credentials → OpenAI / HTTP Request for secure access.
Step 2: Build the Prospect Ingestion Pipeline
Add an n8n Schedule Trigger set to run daily at 08:00.
Chain it to an HTTP Request node hitting the Apollo.io GraphQL endpoint:
POST https://api.apollo.io/api/v1/mixed_people/search
Headers: { "X-Api-Key": "{{$credentials.apollo.apiKey}}" }
Body: {
"q_organization_domains": ["fintech-startups.com"],
"person_seniorities": ["vp", "director", "head"],
"limit": 50
}
Parse the response with an Item Lists → Extract from Array node. For each prospect (first_name, last_name, email, company, title), pass the data into the next stage.
Pro tip: If you don’t have Apollo, replace this with a Google Sheets trigger that watches a “Lead Import” sheet — just paste names and companies.
Step 3: Research Each Prospect with AI
Add a Loop Over Items node (batch size 5, parallelism 3) to process prospects without hitting rate limits.
Inside the loop, place two nodes:
Node A — Perplexity Company Deep Research (HTTP Request):
POST https://api.perplexity.ai/chat/completions
Headers: { "Authorization": "Bearer {{$credentials.perplexity.apiKey}}" }
Body: {
"model": "sonar-pro",
"messages": [
{"role": "system", "content": "Research this company and prospect. Return JSON with: company_mission, recent_news, funding_round, competitor_landscape, growth_challenge."},
{"role": "user", "content": "Company: {{$json.company}}. Prospect: {{$json.first_name}} {{$json.last_name}}, title: {{$json.title}}"}
],
"response_format": {"type": "json_object"}
}
Node B — OpenAI Research Summarizer:
// Code node — enrich prospect data with AI analysis
const research = $input.first().json.research_output;
const prompt = `Based on this research:
${JSON.stringify(research)}
Write a 3-sentence summary of:
1. What the company urgently needs
2. Why the prospect would care about our AI sales platform
3. The specific pain point to address in the email
Prospect title: ${$json.title}
Company: ${$json.company}`;
// Call OpenAI via n8n's AI node or HTTP Request
// Store result as $json.personalized_angle
Step 4: Generate Personalized Email Copy
Add an OpenAI Chat Model node with GPT-4o. Use this system prompt:
You are a senior B2B sales copywriter. Write a cold email to a prospect.
Rules:
- Max 120 words
- Lead with the prospect's specific challenge (from research)
- Reference a real company milestone or news item
- One specific value proposition (not generic "increase efficiency")
- End with a soft CTA: "Worth 10 minutes to discuss?"
- Never sound templated
- Tone: confident, helpful, peer-level
The user message injects the prospect data:
To: {{$json.first_name}} {{$json.last_name}}
Title: {{$json.title}}
Company: {{$json.company}}
Personalized angle: {{$json.personalized_angle}}
Output the email body into $json.email_body. Add a Wait node (300 seconds) between batches to respect sending limits.
Add a secondary Code node for subject line generation using the same research context:
// Generate 5 subject line variants
const subjects = [
`{{$json.company}}'s ${$json.recent_news_topic} — a thought`,
`Quick question re: ${$json.challenge_area}`,
`Idea for {{$json.company}}'s ${$json.goal_area}`,
`${$json.first_name}, saw your recent ${$json.news_item}`,
`{{$json.company}} + ${$json.pain_point}?`
];
return subjects.map(s => ({ subject: s }));
Step 5: Send and Track
Connect the email body to an Email (SMTP) node:
From: you@yourcompany.com
To: {{$json.email}}
Subject: {{$json.subject}}
Body (HTML): {{$json.email_body}}
Add a HubSpot or n8n Database node to log:
prospect_email,sent_at,email_body_preview,subject_variant- A unique
reply_tracking_idin the email footer:{{$json.email}}|{{$json.reply_tracking_id}}
For higher deliverability, set up a custom tracking domain in your email provider (e.g., track.yourdomain.com) and configure SPF/DKIM records.
Step 6: Handle Replies with AI Classification
This is where the agent gets autonomous. Add a Gmail Trigger (or IMAP node) that watches for replies.
Pass each reply into an OpenAI Chat Model node with this classifier prompt:
Classify this email reply into one category:
- "not_interested" — polite decline, unsubscribe request
- "interested" — asks for demo, pricing, more info
- "objection" — raises concerns (budget, timing, competitor)
- "out_of_office" — auto-reply
- "unrelated" — bounced or wrong person
Reply: {{$json.email_body}}
Respond with JSON: {"category": "...", "confidence": 0.0-1.0, "brief_reason": "..."}
Based on the classification, route the workflow:
- interested → Calendly node to send meeting booking link
- objection → OpenAI node with objection-handling prompt, then SMTP to send the response. Log objection type to a Google Sheet for sales team review.
- not_interested → SMTP with gentle goodbye, mark prospect as “cold” in DB, set 90-day re-engagement timer via n8n Wait node.
- out_of_office → Wait 7 days then re-deliver the original email
- unrelated → forward to human sales rep via Slack webhook
Step 7: Meeting Booking Automation
For interested prospects, use the HTTP Request node with Calendly’s API:
POST https://api.calendly.com/scheduling_links
Headers: {
"Authorization": "Bearer {{$credentials.calendly.apiKey}}",
"Content-Type": "application/json"
}
Body: {
"max_event_count": 1,
"owner": "https://api.calendly.com/users/YOUR_USER_UUID",
"owner_type": "EventType",
"event_type_uuid": "YOUR_EVENT_TYPE_UUID"
}
Include a personalized calendar link in a follow-up email:
Subject: Let's find a time — {{$json.first_name}}?
Body:
Hi {{$json.first_name}},
Great to hear you're interested. I've heard similar challenges from {{$json.company_reference_company}} before they adopted our solution.
Here's my calendar — grab any slot that works:
{{$json.calendly_link}}
Looking forward to it.
Best,
[Your Name]
After booking, trigger an n8n Webhook to Slack notifying your sales team:
Channel: #sales-leads
Message: "🎯 *Hot lead booked!*\nProspect: {{$json.first_name}} {{$json.last_name}}\nCompany: {{$json.company}}\nTime: {{$json.meeting_time}}\nAngle used: {{$json.personalized_angle}}"
Best Practices
- Start with 5–10 prospects per day. Tune your email copy and objection handling before scaling to 50+.
- A/B test subject lines. Use a random number node to cycle through 3 variants per prospect batch. Track open rates via your email provider.
- Review objection logs weekly. The most common objections should become new branches in your workflow. If “budget” appears >20% of the time, adjust your targeting criteria.
- Use a warmup tool. Integrate with Mailwarm or Lemwarm before cold-sending at scale — free email providers will throttle new domains hard.
- Keep a human in the loop. For replies with confidence < 0.85, route to Slack for manual review rather than sending autonomously.
Troubleshooting
Issue: Emails landing in spam
Fix: Check your domain’s SPF (v=spf1 include:your_smtp_provider.com ~all), DKIM, and DMARC records. Send a warmup sequence (50→200 emails/day over 3 weeks) before scaling. Use a dedicated sending subdomain like outreach.yourdomain.com.
Issue: OpenAI API exceeds rate limits Fix: Add an n8n Wait node (500ms) between each LLM call. Batch prospect research in groups of 3 with a single call using few-shot prompting.
Issue: Replies not being captured
Fix: Ensure your IMAP/Gmail trigger checks every 5 minutes. Use the reply_tracking_id in the email headers, not just the body. Some providers strip HTML footers.
Issue: Loop items failing mid-way Fix: Add a Stop and Error workflow with an Error Trigger that catches failures, logs the prospect row to a Google Sheet, and continues the loop from the failure point.
FAQ
Q: Can I run this on n8n Cloud or do I need self-hosted? A: Both work. n8n Cloud handles triggers reliably. Self-host is better if you need to keep prospect data on-premises for compliance (GDPR, SOC 2).
Q: How much will the AI API calls cost per 100 prospects?
A: Roughly $8–12. Perplexity research ($0.05/prospect), GPT-4o email generation ($0.02/prospect), and reply classification (~$0.01/reply). Perplexity can be swapped for a free web scrape node to cut costs.
Q: What if a prospect replies multiple times? A: The tracking ID preserves conversation history. Store the thread in an n8n database node and include the last 3 exchanges in the context for each new reply classification pass.
Q: Can I connect this to Salesforce instead of HubSpot? A: Yes — replace the HubSpot node with a Salesforce node using the OAuth2 credential type. Map the same fields (lead status, last touch, notes).
Q: How do I avoid looking spammy? A: Keep personalized angles genuinely specific (reference their recent blog post, funding, or product launch). Avoid generic “I loved your profile” openers. Send max 1 follow-up per prospect unless they reply. Use a real name and headshot in your email signature.