#AI Lead Qualification on WhatsApp with OpenClaw
Your Sales Team Is Wasting Time on Unqualified Leads
Here's the problem: every lead looks the same until you qualify them. Your sales team burns hours chasing tire-kickers who were never going to buy, while hot prospects slip through the cracks because nobody got to them fast enough.
You need AI to do the initial qualification. Ask the right questions. Score the lead. And only hand off the ones worth pursuing—with full context on why they're qualified.
That's what we're building today. An OpenClaw agent that lives on WhatsApp, qualifies inbound leads through natural conversation, scores them based on BANT criteria, and routes hot prospects directly to your sales team. All automated. All instant.
Your salespeople will thank you.
Your salespeople will thank you. Let's do this.
The Qualification Framework: BANT for Conversational AI
BANT is the classic B2B qualification framework:
- Budget: Can they afford your solution?
- Authority: Are they a decision-maker?
- Need: Do they have a problem you solve?
- Timeline: When are they looking to buy?
Traditional BANT feels like an interrogation. "What's your budget? Who's the decision-maker? When do you need this?" Nobody likes being grilled.
AI changes the game. Instead of a survey, it's a conversation. The agent asks open-ended questions, listens to responses, and gently probes for qualification signals. The lead doesn't even realize they're being qualified—they just think they're having a helpful chat.
Here's what conversational qualification looks like:
Traditional approach:
Bot: What's your budget?
Lead: [leaves conversation]Conversational AI approach:
Agent: What's the biggest challenge you're facing with customer support right now?
Lead: We're drowning in WhatsApp messages. Takes hours to respond to everyone.
Agent: I hear that a lot. How many messages are you handling daily?
Lead: Around 500, maybe more during busy periods.
Agent: That's a lot. Are you using any tools to manage it, or is it all manual?
Lead: All manual. We've looked at a few solutions but they're too expensive.
Agent: What's "too expensive" in this context? Just so I can recommend something in the right range.
Lead: We can't justify more than $500/month right now.See what happened? The agent extracted budget, need, and pain level without asking "What's your budget?" directly. Natural. Human. Effective.
Step 1: Define the Qualification Agent
Let's build the OpenClaw agent with a qualification-focused system prompt:
from openclaw import Agent, LeadScoringSkill, CRMIntegrationSkill
qualification_agent = Agent(
name="WhatsApp Lead Qualifier",
system_prompt="""You are a friendly pre-sales consultant helping potential customers
evaluate whether our WhatsApp automation platform fits their needs.
Your job is to understand:
1. Their current pain points with customer communication
2. The scale of their operation (message volume, team size)
3. Their budget constraints
4. Who makes purchasing decisions
5. Their timeline for implementing a solution
Be conversational, not interrogative. Ask open-ended questions.
Listen to their responses and probe naturally based on what they share.
Keep responses brief (2-3 sentences). WhatsApp conversations move fast.
Use plain text only. No emojis unless they use them first.
If they're clearly not a fit (e.g., student working on a class project,
competitor doing research), politely disengage and wish them well.""",
skills=[
LeadScoringSkill(framework="bant", threshold=80),
CRMIntegrationSkill(crm="hubspot")
],
model="gpt-4o",
temperature=0.7 # Higher temp for more natural conversation
)Key elements:
- Conversational tone: The prompt emphasizes natural conversation over interrogation
- Qualification goals: Explicit list of what we're trying to learn
- Disqualification logic: Not every lead is worth pursuing—teach the agent to recognize bad fits
- LeadScoringSkill: Automatically tracks qualification signals and calculates a score
- CRMIntegrationSkill: Pushes qualified leads to your CRM with full context
Step 2: The Scoring Model
Every interaction with the lead generates signals. The agent assigns points based on qualification strength:
class LeadScoringSkill:
"""Tracks qualification signals and computes lead score."""
def __init__(self, framework: str = "bant", threshold: int = 80):
self.framework = framework
self.threshold = threshold
self.scoring_rules = {
"budget_signals": {
"explicit_budget_shared": 25,
"premium_tier_interest": 20,
"price_objection": -10,
"no_budget_mentioned": 0
},
"authority_signals": {
"decision_maker": 30,
"influencer": 15,
"end_user_only": -5
},
"need_signals": {
"urgent_pain": 25,
"moderate_pain": 15,
"exploring_options": 5,
"no_clear_need": -10
},
"timeline_signals": {
"immediate": 20,
"this_quarter": 15,
"next_quarter": 10,
"no_timeline": 0
}
}
def extract_signals(self, conversation_history: list) -> dict:
"""Parse conversation for qualification signals using LLM."""
# Simplified—in production, use structured extraction with function calling
signals = {}
# Budget signals
if "budget" in str(conversation_history).lower():
signals["budget"] = "explicit_budget_shared"
elif "expensive" in str(conversation_history).lower():
signals["budget"] = "price_objection"
# Authority signals
if any(term in str(conversation_history).lower() for term in ["ceo", "founder", "director", "vp"]):
signals["authority"] = "decision_maker"
elif "manager" in str(conversation_history).lower():
signals["authority"] = "influencer"
# Need signals
if any(term in str(conversation_history).lower() for term in ["urgent", "asap", "immediately"]):
signals["need"] = "urgent_pain"
elif any(term in str(conversation_history).lower() for term in ["problem", "issue", "struggling"]):
signals["need"] = "moderate_pain"
# Timeline signals
if any(term in str(conversation_history).lower() for term in ["now", "today", "this week"]):
signals["timeline"] = "immediate"
elif any(term in str(conversation_history).lower() for term in ["month", "quarter"]):
signals["timeline"] = "this_quarter"
return signals
def calculate_score(self, signals: dict) -> int:
"""Sum scores from all detected signals."""
total = 0
for category, signal in signals.items():
category_key = f"{category}_signals"
if category_key in self.scoring_rules:
total += self.scoring_rules[category_key].get(signal, 0)
return max(0, min(100, total)) # Clamp to 0-100This is simplified for illustration. In production, use the LLM's function calling capabilities to extract structured data from conversation history.
Step 3: The Conversation Flow
Here's what a typical qualification conversation looks like:
Message 1: Warm greeting + discovery
Agent: Hey! Thanks for reaching out. I'd love to learn more about what you're
looking for. What's the biggest challenge you're facing with customer communication right now?Lead responds: "We're getting hundreds of WhatsApp messages daily and can't keep up."
Message 2: Probe for scale
Agent: That sounds overwhelming. About how many messages are we talking per day?
And how big is your support team handling them?Lead responds: "Around 800 messages. We have 5 people but they're stretched thin."
Message 3: Budget qualification
Agent: Got it. So you're looking at around 24,000 messages per month with a small team.
Have you looked at automation tools before, or is this your first time exploring options?Lead responds: "We tried one tool but it was $2,000/month which was way too much."
Message 4: Authority + timeline
Agent: Makes sense—pricing needs to work for your budget. Are you the person
who'd make the call on a tool like this, or is there someone else involved in the decision?
And is this something you're looking to solve soon, or more of a long-term plan?Lead responds: "I'm the COO so I make the call. We need something in place by end of month."
Internal scoring after this exchange:
- Budget: explicit mention → +25
- Authority: decision-maker (COO) → +30
- Need: urgent pain (can't keep up) → +25
- Timeline: immediate (end of month) → +20
- Total: 100 points → HOT LEAD
The agent now knows this is worth immediate sales attention.
Step 4: Score and Route
Based on the score, the agent routes the lead appropriately:
async def route_lead(lead_data: dict, score: int):
"""Route lead based on qualification score."""
if score >= 80:
# HOT LEAD - immediate sales notification
await notify_sales_team(lead_data, urgency="high")
return "hot"
elif score >= 50:
# WARM LEAD - schedule follow-up
await schedule_follow_up(lead_data, days=3)
return "warm"
else:
# COLD LEAD - add to nurture sequence
await add_to_nurture(lead_data)
return "cold"
async def notify_sales_team(lead_data: dict, urgency: str):
"""Send lead details to sales team WhatsApp group."""
summary = f"""🔥 HOT LEAD ALERT
Name: {lead_data['name']}
Contact: {lead_data['phone']}
Company: {lead_data.get('company', 'N/A')}
Score: {lead_data['score']}/100
Pain Point: {lead_data['pain_point']}
Budget: {lead_data.get('budget', 'Not disclosed')}
Timeline: {lead_data['timeline']}
Authority: {lead_data['authority_level']}
Conversation:
{lead_data['conversation_summary']}
🎯 ACTION: Reach out within 1 hour"""
async with httpx.AsyncClient() as client:
await client.post(
f"https://apiv2.waiflow.app/api/v2/sessions/sales-bot/messages",
headers={"Authorization": f"Bearer {MOLTFLOW_API_TOKEN}"},
json={
"chatId": SALES_GROUP_ID, # Your sales team's WhatsApp group
"text": summary
}
)Hot leads get instant attention. Warm leads get scheduled follow-up. Cold leads go into a long-term nurture campaign. Nothing falls through the cracks.
Step 5: CRM Integration
Push qualified lead data to your CRM so sales has everything they need:
async def push_to_crm(lead_data: dict):
"""Send lead to HubSpot (or your CRM of choice)."""
hubspot_payload = {
"properties": {
"firstname": lead_data.get("name", "").split()[0],
"lastname": " ".join(lead_data.get("name", "").split()[1:]) or "Unknown",
"phone": lead_data["phone"],
"company": lead_data.get("company"),
"lead_score": lead_data["score"],
"lead_source": "WhatsApp Bot",
"pain_point": lead_data["pain_point"],
"qualification_status": lead_data["qualification_tier"], # hot/warm/cold
"notes": lead_data["conversation_summary"]
}
}
async with httpx.AsyncClient() as client:
response = await client.post(
"https://api.hubspot.com/crm/v3/objects/contacts",
headers={
"Authorization": f"Bearer {HUBSPOT_API_KEY}",
"Content-Type": "application/json"
},
json=hubspot_payload
)
if response.status_code == 201:
print(f"Lead {lead_data['phone']} pushed to HubSpot")
else:
print(f"CRM push failed: {response.text}")Now your CRM has:
- Lead contact info
- Qualification score
- Pain points and needs
- Budget and timeline
- Full conversation transcript
Sales doesn't start from zero—they start with context.
Step 6: Handle Disqualification Gracefully
Not every lead is worth pursuing. Students, competitors, people in the wrong industry—the agent should recognize bad fits and disengage politely:
system_prompt="""...
If you determine this is NOT a good fit, respond warmly:
'Thanks for reaching out! Based on what you've shared, it sounds like
our platform might not be the best fit for your needs right now.
I appreciate you taking the time to chat. Best of luck with your project!'
Disqualify if:
- They're a student working on a school project
- They represent a direct competitor doing research
- Their use case doesn't align with our product (e.g., personal use, non-business)
- Budget is less than $50/month (below our minimum plan)
"""Disqualifying bad leads fast saves everyone time. Your sales team doesn't chase ghosts. The lead doesn't get strung along.
Complete Webhook Integration
Here's the full pipeline wired up to MoltFlow:
from fastapi import FastAPI, Request
import httpx
from openclaw import Agent
app = FastAPI()
@app.post("/webhook/whatsapp")
async def qualify_lead(request: Request):
"""Receives inbound lead messages, qualifies via conversation, routes accordingly."""
payload = await request.json()
message = payload["data"]["body"]
sender = payload["data"]["from"]
session = payload["session"]
# Retrieve or initialize conversation state
conversation = get_conversation_state(sender)
conversation["messages"].append({"role": "user", "content": message})
# Process with qualification agent
response = await qualification_agent.process(
input_text=message,
conversation_history=conversation["messages"],
context={"sender_id": sender}
)
# Update conversation state
conversation["messages"].append({"role": "assistant", "content": response.text})
save_conversation_state(sender, conversation)
# Check if qualification is complete
if response.metadata.get("qualification_complete"):
lead_data = extract_lead_data(conversation, sender)
score = response.metadata["lead_score"]
# Route based on score
tier = await route_lead(lead_data, score)
# Push to CRM
await push_to_crm({**lead_data, "score": score, "qualification_tier": tier})
# Send confirmation to lead
if tier == "hot":
confirmation = "Thanks for all that info! Someone from our sales team will reach out shortly to discuss next steps."
elif tier == "warm":
confirmation = "Appreciate you sharing that. I'll have someone follow up with you in the next few days."
else:
confirmation = "Thanks for chatting! We'll add you to our mailing list for updates."
# Send response
async with httpx.AsyncClient() as client:
await client.post(
f"https://apiv2.waiflow.app/api/v2/sessions/{session}/messages",
headers={"Authorization": f"Bearer {MOLTFLOW_API_TOKEN}"},
json={"chatId": sender, "text": confirmation}
)
else:
# Qualification ongoing—continue conversation
async with httpx.AsyncClient() as client:
await client.post(
f"https://apiv2.waiflow.app/api/v2/sessions/{session}/messages",
headers={"Authorization": f"Bearer {MOLTFLOW_API_TOKEN}"},
json={"chatId": sender, "text": response.text}
)
return {"status": "ok"}Results: What to Expect
Based on deployments we've seen, here's what typically happens:
Before AI qualification:
- Sales team spends 60% of time on unqualified leads
- Response time for hot leads: 4-6 hours (too slow)
- Lead-to-opportunity conversion: ~5%
After AI qualification:
- Sales team focuses on leads with score above 80 (top 20% of inbound)
- Response time for hot leads: under 1 hour (immediate notification)
- Lead-to-opportunity conversion: 15-20% (3-4x improvement)
The math is simple: when salespeople spend time on qualified leads, more deals close. When hot leads get instant attention, they don't go cold waiting.
Optimization: A/B Test Your Questions
Not all qualification questions are created equal. Some uncover real signals. Others just waste time.
Track which questions correlate with closed deals:
# Log each question and the eventual outcome
qualification_log = {
"question": "How many messages do you handle daily?",
"lead_id": sender,
"answer": message,
"eventual_outcome": "closed_deal" # or "lost" or "no_response"
}
# After 100+ leads, analyze
# Which questions appear in 90% of closed deals?
# Which questions don't correlate with outcomes at all?Drop the low-signal questions. Double down on the high-signal ones. Your qualification gets tighter over time.
Advanced: Behavioral Scoring
BANT is great, but behavioral signals matter too:
- Response speed: Leads who reply within 5 minutes are 10x more likely to convert than leads who reply in 24 hours
- Message length: Long, detailed responses indicate serious interest
- Question depth: Leads asking about implementation details (not just pricing) are further along the buying journey
Add behavioral scoring to your model:
behavioral_score = 0
# Fast responders are hot
response_time_seconds = time.time() - conversation["last_bot_message_time"]
if response_time_seconds < 300: # 5 minutes
behavioral_score += 15
# Detailed responses show engagement
if len(message) > 100: # characters
behavioral_score += 10
# Technical questions indicate buying intent
if any(term in message.lower() for term in ["api", "integration", "implement", "deploy", "security"]):
behavioral_score += 10
total_score = bant_score + behavioral_scoreCombine BANT with behavior for a more complete picture.
What's Next?
You've built an AI lead qualification system that:
- Qualifies leads through natural conversation (no surveys)
- Scores based on BANT framework + behavioral signals
- Routes hot leads to sales instantly with full context
- Pushes qualified data to your CRM automatically
- Disqualifies bad fits gracefully
MoltFlow's OpenClaw integration gives you production-ready lead qualification in hours, not weeks.
Continue learning:
- WhatsApp Lead Scoring Automation — Build sophisticated scoring models with multiple signals
- WhatsApp Lead Capture & CRM Integration — Sync leads to HubSpot, Salesforce, or custom CRMs
- Build a WhatsApp Knowledge Base with OpenClaw RAG — Answer product questions with semantic search
- Build a WhatsApp Customer Support Bot — Turn qualified leads into happy customers
Ready to implement lead qualification? Follow our step-by-step guide: Qualify Leads with OpenClaw Agents
Sign up for MoltFlow and get your API credentials in under a minute. Stop chasing unqualified leads—let AI do the heavy lifting.
> Try MoltFlow Free — 100 messages/month