AI SDR Development — Digital Sales Manager
AI SDR (Sales Development Representative) is an autonomous agent performing first-line sales manager functions: lead discovery and enrichment, personalized outreach via email and LinkedIn, qualification using BANT/MEDDIC methodology, objection handling, and handoff of qualified leads to CRM with full context. Unlike script-based email senders, AI SDR conducts multi-turn dialogue and adapts strategy based on responses.
AI SDR Architecture
Lead Discovery: enrichment via Apollo, Hunter.io, LinkedIn Sales Navigator API, Clearbit.
Personalization Engine: generating unique messages based on company data (funding, hiring, news, tech stack).
Outreach Orchestrator: managing sequences and timing.
Qualification Engine: multi-turn dialogue with BANT/MEDDIC qualification.
CRM Integration: AmoCRM / Bitrix24 / Salesforce — automatic deal creation.
Lead Enrichment and Personalization
import asyncio
from openai import AsyncOpenAI
from pydantic import BaseModel
from typing import Optional
client = AsyncOpenAI()
class LeadProfile(BaseModel):
company: str
domain: str
contact_name: str
title: str
email: str
linkedin_url: Optional[str]
# Enriched data
company_size: Optional[int]
industry: Optional[str]
recent_funding: Optional[str] # Latest funding round
tech_stack: Optional[list[str]] # Technologies on website
recent_news: Optional[list[str]] # News mentions
job_openings: Optional[list[str]] # Open positions (growth signal)
pain_indicators: Optional[list[str]] # Pain signals
async def enrich_lead(lead: LeadProfile) -> LeadProfile:
"""Lead data enrichment from multiple sources"""
# Parallel data collection
clearbit_task = clearbit_api.enrich(domain=lead.domain)
apollo_task = apollo_api.get_company(domain=lead.domain)
news_task = newsapi.search(query=lead.company, days=30)
linkedin_task = proxycurl.get_company(linkedin_url=f"linkedin.com/company/{lead.company.lower().replace(' ', '-')}")
results = await asyncio.gather(
clearbit_task, apollo_task, news_task, linkedin_task,
return_exceptions=True,
)
# Update profile
if not isinstance(results[0], Exception):
lead.company_size = results[0].get("employees")
lead.tech_stack = results[0].get("tech", [])
if not isinstance(results[2], Exception):
lead.recent_news = [n["title"] for n in results[2][:3]]
# Detect pain indicators
lead.pain_indicators = await detect_pain_indicators(lead)
return lead
async def detect_pain_indicators(lead: LeadProfile) -> list[str]:
"""LLM analyzes pain signals from company data"""
response = await client.chat.completions.create(
model="gpt-4o-mini",
messages=[{
"role": "user",
"content": f"""Based on company data, identify potential pain points relevant to selling {OUR_PRODUCT}.
Company: {lead.company}
Industry: {lead.industry}
Size: {lead.company_size} employees
Job openings: {lead.job_openings}
News: {lead.recent_news}
Return JSON-list of 2-3 specific pain indicators."""
}],
)
return json.loads(response.choices[0].message.content)
Personalized Message Generator
class PersonalizedOutreachGenerator:
SEQUENCE_FRAMES = {
1: "cold_intro", # First contact: relevant value proposition
2: "pain_point_follow", # Follow-up: specific pain based on data
3: "social_proof", # Case study from their industry
4: "direct_ask", # Direct meeting request
5: "breakup", # Final email
}
async def generate_email(
self,
lead: LeadProfile,
step: int,
previous_responses: list[str] = None,
) -> str:
frame = self.SEQUENCE_FRAMES.get(step, "generic")
context = self._build_context(lead, previous_responses)
response = await client.chat.completions.create(
model="gpt-4o",
messages=[{
"role": "system",
"content": f"""You are an experienced B2B SDR. Write emails that get responses.
Rules:
- 80-120 words maximum
- First sentence — not about company, but about lead/their pain
- One specific CTA at end
- No clichés: "hoping this email finds you well"
- Personalization must be noticeable (not "saw your LinkedIn profile")
Email frame: {frame}"""
}, {
"role": "user",
"content": f"""Write email for:
Name: {lead.contact_name}, {lead.title} at {lead.company}
Pain points: {lead.pain_indicators}
Recent news: {lead.recent_news}
Tech stack: {lead.tech_stack}
Context from previous emails: {context}"""
}],
temperature=0.7,
)
return response.choices[0].message.content
def _build_context(self, lead: LeadProfile, previous_responses: list[str]) -> str:
if not previous_responses:
return "First contact"
return f"Previous emails: {len(previous_responses)}, last response: {previous_responses[-1][:200] if previous_responses else 'no responses'}"
Qualification Dialogue
from langgraph.graph import StateGraph, END
from typing import TypedDict, Annotated
import operator
class QualificationState(TypedDict):
lead_id: str
messages: Annotated[list, operator.add]
lead_profile: dict
qualification: dict # BANT progress
lead_score: int
next_action: str # "schedule_demo", "nurture", "disqualify", "continue"
QUALIFICATION_SYSTEM = """You are a B2B SDR, qualifying leads using BANT.
Conduct natural dialogue, not interrogation. 4-7 messages until decision.
Current qualification:
{qualification_status}
Handoff to AE criteria: score >= 70, budget confirmed, authority confirmed.
Disqualification criteria: no budget + no timeline, company < 50 employees for our product."""
def should_continue_qualification(state: QualificationState) -> str:
score = state["lead_score"]
qual = state["qualification"]
# Disqualification
if score < 20 and len(state["messages"]) > 4:
return "disqualify"
# Ready for AE handoff
if score >= 70 and qual.get("budget") and qual.get("authority"):
return "schedule_demo"
# Continue dialogue
if len(state["messages"]) >= 14: # Conversation limit
return "nurture" if score >= 40 else "disqualify"
return "continue"
CRM Integration
class CRMIntegration:
async def create_qualified_lead(self, state: QualificationState):
"""Creates deal in CRM with full context"""
# Format conversation history
conversation_summary = await self.summarize_conversation(state["messages"])
deal_data = {
"name": f"{state['lead_profile']['company']} — {state['lead_profile']['contact_name']}",
"status": "qualified",
"pipeline_stage": "SQL",
"lead_score": state["lead_score"],
"budget_range": state["qualification"].get("budget"),
"timeline": state["qualification"].get("timeline"),
"pain_points": state["lead_profile"].get("pain_indicators", []),
"conversation_summary": conversation_summary,
"ai_sdr_notes": self.format_handoff_notes(state),
}
deal = await amocrm.create_deal(**deal_data)
await amocrm.attach_conversation(deal.id, state["messages"])
return deal
def format_handoff_notes(self, state: QualificationState) -> str:
"""Brief handoff notes for AE"""
qual = state["qualification"]
return f"""SDR Handoff Notes:
Score: {state['lead_score']}/100
Budget: {qual.get('budget', 'TBD')}
Authority: {'confirmed' if qual.get('authority') else 'no'}
Need: {qual.get('need', '')}
Timeline: {qual.get('timeline', 'TBD')}
Key pain: {', '.join(state['lead_profile'].get('pain_indicators', [])[:2])}
Recommended AE approach: {self.recommend_approach(state)}"""
Case Study: B2B SaaS, Market of 5000 Companies
Company: HR-tech SaaS, ACV $24,000, target market — companies 100–1,000 employees.
Before AI SDR: 2 SDRs, 400 manual outreaches/month, pipeline generation took 60% of time.
AI SDR Configuration:
- Lead source: Apollo.io (ICP filters) + automatic Clearbit enrichment
- Outreach: email (5-step sequences) + LinkedIn InMail
- Qualification: BANT, 6–8 dialogue turns
- Handoff: AmoCRM, automatic deal creation at score >= 65
Results in First 3 Months:
- Outreach per month: 400 → 2,800 (+600%)
- Reply rate: 4.2% (human) → 3.1% (AI) — lower but volume compensates
- Qualified SQL per month: 18 (SDR) → 31 (AI SDR + SDR)
- SDRs refocused: conversations with already interested, warm intros
- Pipeline: +72% per quarter
Issues: First 3 weeks — too "robotic" emails, 2 iterations of prompt engineering. Some responses "unsubscribe me" — important to monitor and exclude domains.
Limitations: AI SDR does not conduct final negotiations on terms and enterprise deals with C-level decision makers — only warm-up and qualification.
Timeline
- Lead enrichment pipeline: 2–3 weeks
- Outreach generator with A/B testing: 2–3 weeks
- Qualification agent: 2–3 weeks
- CRM integration + handoff: 1–2 weeks
- Calibration and launch: 2 weeks
- Total: 9–13 weeks







