AI lead recovery system: Voice, WhatsApp, and SMS with N8N

April 27, 2026 • 6 min read

Home / Blog / AI lead recovery system: Voice, WhatsApp, and SMS with N8N

About the author

Author

Gonzalo Gomez

AI & Automation Specialist

I design AI-powered communication systems. My work focuses on voice agents, WhatsApp chatbots, AI assistants, and workflow automation built primarily on Twilio, n8n, and modern LLMs like OpenAI and Claude. Over the past 7 years, I've shipped 30+ automation projects handling 250k+ monthly interactions.

Subscribe to my newsletter

If you enjoy the content that I make, you can subscribe and receive insightful information through email. No spam is going to be sent, just updates about interesting posts or specialized content that I talk about.

AI lead recovery system: Voice, WhatsApp, and SMS with N8N | Architectural review for an AI lead recovery system that works through voice, WhatsApp and SMS. Orchestrated with N8N

AI Lead Recovery System: How I Built a Multi-Channel Outreach Agent with N8N, Twilio, and ElevenLabs

 

Introduction

Most businesses lose leads not because the product is wrong, but because nobody followed up in time. The contact form gets submitted, someone adds a product to the cart, a call goes unreturned, and by the time someone on the team gets to it, the window is closed. I built a system that handles exactly this, and it runs every 5 minutes without anyone touching it.

 

The system detects new leads from three sources (contact forms, abandoned carts, missed contact requests), classifies them, generates a contextual message using Claude, and reaches out via the appropriate channel: WhatsApp, SMS, or a real-time voice call with an AI agent. Everything is orchestrated in N8N. The full workflow files, agent prompts, and configuration instructions are in the repo linked in the description.

 

Architecture overview

The data layer sits in Airtable. Three lead types feed into a single table:

- **Website contact forms** that never got a reply
- **Abandoned carts** where someone added a product but never completed the purchase
- **Missed contact requests** that fell through the cracks

 

Every record has a `status` field. The main workflow polls for records with `status = new` every 5 minutes and works through them one by one.

 

The two workflow files in the repo are:

1. **Main workflow**: fetches leads, classifies them, generates messages, routes to the right channel, updates Airtable
2. **Post-call webhook workflow**: receives the transcript from ElevenLabs after a voice call ends, extracts relevant data, updates the lead record

This separation matters. The main flow doesn't wait for call outcomes, it fires the outbound call and moves on. The transcript arrives asynchronously via webhook, which is why it lives in its own flow.

 

Lead normalization before hitting the agent

One of the first steps after fetching leads from Airtable is normalization. Before the Claude node sees anything, we pass leads through a normalization step that enforces a fixed structure, regardless of what fields exist in the source table.

 

This is worth doing even if it feels like overhead. Airtable schemas change. Someone adds a field, renames one, or removes it. Without normalization, any of that breaks the agent prompt. With normalization, the agent always receives the same shape of data and can tell you if something is missing instead of silently producing a bad message.

 

Prompt generation: why contact mode changes everything

The prompt generation node does more than fill a template. It branches based on two dimensions: lead origin (website, cart, missed call) and contact mode (text or call).

 

This is where a lot of similar systems cut corners and produce generic messages. A WhatsApp message has a character limit, needs to respect approved templates if you're on the Business API, and reads differently than a spoken sentence. An AI agent making a voice call needs to know its opening line before the lead picks up, not after. You can't have the same instructions handle both.

 

For text channels, the prompt tells Claude to generate a concise, direct message appropriate for the lead origin. For voice calls, the prompt generates an `opening` variable, which is what the ElevenLabs agent says the moment the lead picks up. That variable gets passed dynamically to the ElevenLabs API call so the agent doesn't open cold.

 

The ElevenLabs + Twilio integration

For voice calls, the flow makes an API call to ElevenLabs with a payload that includes:

- The agent ID (configured in ElevenLabs with the system prompt and conversation rules)
- The Twilio phone number registered inside ElevenLabs
- The destination number (the lead's phone)
- Dynamic variables: `opening`, lead ID, lead origin

 

The agent system prompt lives in the repo. Key design decision: if the lead signals disinterest, the agent wraps up and ends the call. No persistence, no pressure. The prompt explicitly handles this case because an AI agent that keeps pushing when someone says no is worse than no agent at all.

 

The post-call webhook fires from ElevenLabs once the conversation ends and the transcript is processed. It hits the N8N webhook URL (ngrok tunnel if you're running locally, public IP if deployed) and the secondary workflow takes it from there: extracts the conversation transcript, the agent's lines and the lead's lines separately, and writes everything back to Airtable alongside the updated status and contact timestamp.

 

Having the full transcript in Airtable is what makes this system useful beyond just ""did we contact them"". You can run sentiment analysis on what the lead said, identify objections that keep coming up, or flag calls where the agent did something unexpected.

 

Twilio setup

For SMS and WhatsApp: grab a phone number from the Twilio console (US numbers run $1.15/month, varies by country), copy the Account SID and Auth Token from the dashboard, and configure them as credentials in N8N. The WhatsApp sender and SMS sender can be different numbers, both defined as variables at the top of the main workflow so you change them in one place.

 

For voice: import the Twilio number into ElevenLabs under Phone Numbers, assign your agent to it, and configure the post-call webhook URL there. That's the URL that triggers the secondary N8N workflow after each call ends.

 

Airtable state management

After any contact attempt, the record gets updated immediately: status flips to `contacted`, contact date is set, last message sent is stored. This is what prevents the 5-minute polling loop from re-contacting the same lead on the next run. Simple but critical. If you forget this or the update fails silently, leads start getting duplicate messages or repeat calls, which is worse than no outreach at all.

 

On the low-code vs. custom code question

I want to address this directly because it comes up. This entire system runs on N8N with no custom backend. The trade-off is real: you give up some flexibility and debugging depth compared to writing this in code, and you're dependent on the N8N workflow format for portability.

 

But for this class of problem, the low-code approach was the right call. The logic here is orchestration: fetch, classify, branch, call API, update state. There's no algorithmic complexity that requires custom code. Building the same system from scratch would've taken significantly longer with no meaningful quality advantage. The AI agent behavior comes from the prompt, not from the surrounding infrastructure.

 

Where this would break down is if you needed to handle high concurrency (N8N's execution model has limits), complex retry logic with exponential backoff, or deeply custom conversation state management. For a lead recovery system handling dozens to low hundreds of leads per day, this holds up fine.

 

The design principle worth keeping: normalize your data early, define variables in one place, and keep the two flows separate. Those three decisions are what make this maintainable when Airtable fields change or you swap ElevenLabs for a different voice provider.

 

Liked the post? Share the knowledge!

-Gonza

23
JavaScript,  Twilio,  n8n
Published on April 27, 2026

Ready to automate your customer conversations?

Contact me

Related posts

Building an AI Outbound Call Sales Assistant with n8n, Twilio, and ElevenLabs

January 30, 2026
IntroductionOutbound sales calls are one of the hardest channels to automate with AI. Latency matters.Costs compound fast.Hallucinations are unacceptable.And voice systems fail loudly when something breaks. In... Continue reading

Building a WhatsApp AI Agent for Automated Booking: Architecture and Design Decisions

February 24, 2026
IntroductionMost AI assistant tutorials focus on prompts or models. In production, that is rarely the hard part. The real challenge is building a system that:accepts multiple input... Continue reading

Real-Time Call Translation With Twilio and OpenAI (Both Sides of the Line)

April 01, 2026
IntroductionLanguage barriers in call centers are a solved problem. Most people just don't know it yet, or they think it requires expensive middleware and a... Continue reading