By Sagar Shankaran, Founder of CallSphere
Learn how to architect an AI-powered SDR agent that scores leads, generates personalized outreach messages, and manages multi-step follow-up sequences automatically.
Key takeaways
Sales development representatives spend the majority of their time on repetitive tasks: researching prospects, writing personalized emails, scoring leads, and scheduling follow-ups. An AI SDR agent automates this entire pipeline while maintaining the personalization that drives response rates. Unlike simple email templates, an agentic SDR reasons about each prospect individually, adapts messaging based on engagement signals, and decides when to escalate a warm lead to a human rep.
The architecture we will build has four components: a lead ingestion layer, a scoring engine, a message generation module, and a follow-up orchestrator.
Before the agent can do anything useful, it needs structured data about each prospect. Raw leads from forms or CRM exports often lack the context needed for personalization. The ingestion layer enriches each lead with company information, recent news, and technology stack signals.
Hear it before you finish reading
Talk to a live CallSphere AI voice agent in your browser — 60 seconds, no signup.
flowchart LR
LEAD(["Inbound lead"])
AGENT["AI voice or chat<br/>qualifier"]
BANT["BANT capture<br/>budget, authority,<br/>need, timing"]
SCORE{"Lead score<br/>and routing rules"}
HOT(["Hot — book<br/>AE meeting"])
WARM(["Warm — SDR<br/>sequence"])
NURT(["Nurture — drip<br/>and content"])
CRM[("CRM and SLA timer")]
LEAD --> AGENT --> BANT --> SCORE
SCORE -->|Hot| HOT --> CRM
SCORE -->|Warm| WARM --> CRM
SCORE -->|Cold| NURT --> CRM
style AGENT fill:#4f46e5,stroke:#4338ca,color:#fff
style HOT fill:#059669,stroke:#047857,color:#fff
style WARM fill:#0ea5e9,stroke:#0369a1,color:#fff
style NURT fill:#f59e0b,stroke:#d97706,color:#1f2937
from dataclasses import dataclass, field
from datetime import datetime
from typing import Optional
import httpx
@dataclass
class Lead:
email: str
name: str
company: str
title: Optional[str] = None
industry: Optional[str] = None
company_size: Optional[str] = None
enrichment_data: dict = field(default_factory=dict)
score: float = 0.0
stage: str = "new"
created_at: datetime = field(default_factory=datetime.utcnow)
async def enrich_lead(lead: Lead, api_key: str) -> Lead:
"""Enrich a lead with company data from an external API."""
async with httpx.AsyncClient() as client:
resp = await client.get(
"https://api.clearbit.com/v2/companies/find",
params={"domain": lead.email.split("@")[1]},
headers={"Authorization": f"Bearer {api_key}"},
)
if resp.status_code == 200:
data = resp.json()
lead.industry = data.get("category", {}).get("industry")
lead.company_size = data.get("metrics", {}).get("employeesRange")
lead.enrichment_data = data
return lead
Traditional scoring uses weighted feature models. An LLM-augmented scorer can evaluate unstructured signals like job title relevance, company news sentiment, and technology fit that rule-based systems struggle with.
from openai import AsyncOpenAI
client = AsyncOpenAI()
SCORING_PROMPT = """You are a lead scoring assistant for a B2B SaaS company
that sells AI-powered customer service tools.
Evaluate this lead and return a JSON object with:
- "score": integer from 1 to 100
- "reasoning": one sentence explaining the score
- "priority": "hot", "warm", or "cold"
Lead data:
- Name: {name}
- Title: {title}
- Company: {company}
- Industry: {industry}
- Company size: {company_size}
"""
async def score_lead(lead: Lead) -> dict:
response = await client.chat.completions.create(
model="gpt-4o",
response_format={"type": "json_object"},
messages=[
{"role": "system", "content": "Return valid JSON only."},
{
"role": "user",
"content": SCORING_PROMPT.format(
name=lead.name,
title=lead.title or "Unknown",
company=lead.company,
industry=lead.industry or "Unknown",
company_size=lead.company_size or "Unknown",
),
},
],
)
import json
result = json.loads(response.choices[0].message.content)
lead.score = result["score"]
lead.stage = result["priority"]
return result
Generic emails get ignored. The agent uses enrichment data to craft messages that reference specific company details, recent events, or role-relevant pain points.
OUTREACH_PROMPT = """Write a short, personalized cold outreach email.
Prospect: {name}, {title} at {company}
Industry: {industry}
Company size: {company_size}
Key insight: {insight}
Rules:
- Keep it under 120 words
- Reference something specific about their company
- End with a clear, low-friction call to action
- Do NOT use generic phrases like "I hope this finds you well"
"""
async def generate_outreach(lead: Lead) -> str:
insight = lead.enrichment_data.get("description", "a growing company")
response = await client.chat.completions.create(
model="gpt-4o",
messages=[
{
"role": "user",
"content": OUTREACH_PROMPT.format(
name=lead.name,
title=lead.title,
company=lead.company,
industry=lead.industry,
company_size=lead.company_size,
insight=insight,
),
},
],
)
return response.choices[0].message.content
The most critical part of an SDR agent is persistence. Research shows that most conversions happen after the third or fourth touch. The orchestrator tracks engagement events and decides when and what to send next.
from datetime import timedelta
FOLLOW_UP_SCHEDULE = [
{"delay_days": 3, "strategy": "value_add"},
{"delay_days": 5, "strategy": "social_proof"},
{"delay_days": 7, "strategy": "breakup"},
]
async def process_follow_ups(leads: list[Lead], email_service):
now = datetime.utcnow()
for lead in leads:
if lead.stage == "cold":
continue
history = await email_service.get_history(lead.email)
if history.last_replied:
# Lead engaged — escalate to human rep
await email_service.notify_rep(lead, reason="reply_received")
continue
touches = history.touch_count
if touches >= len(FOLLOW_UP_SCHEDULE):
lead.stage = "exhausted"
continue
step = FOLLOW_UP_SCHEDULE[touches]
due_date = history.last_sent + timedelta(days=step["delay_days"])
if now >= due_date:
message = await generate_follow_up(lead, step["strategy"])
await email_service.send(lead.email, message)
The main agent loop pulls new leads, enriches them, scores them, and starts the outreach pipeline. Hot leads get immediate outreach while warm leads enter a nurture sequence.
Still reading? Stop comparing — try CallSphere live.
CallSphere ships complete AI voice agents per industry — 14 tools for healthcare, 10 agents for real estate, 4 specialists for salons. See how it actually handles a call before you book a demo.
async def run_sdr_agent(new_leads: list[Lead], email_service):
for lead in new_leads:
lead = await enrich_lead(lead, api_key="your-key")
scoring = await score_lead(lead)
if scoring["priority"] == "hot":
message = await generate_outreach(lead)
await email_service.send(lead.email, message)
elif scoring["priority"] == "warm":
await email_service.add_to_nurture(lead)
# Process existing follow-ups
active_leads = await email_service.get_active_leads()
await process_follow_ups(active_leads, email_service)
Implement a review layer. Score every generated message against your brand guidelines using a second LLM call that acts as a quality gate. Messages below a confidence threshold get queued for human review instead of sending automatically.
At minimum you need read access to contacts and deals (to avoid contacting existing customers), write access to log activities and update lead stages, and webhook support to receive engagement events like email opens and replies. HubSpot and Salesforce both provide robust APIs for this.
Track reply rate, meeting booked rate, and pipeline generated per lead. Compare these against your human SDR benchmarks. Also monitor negative signals like unsubscribe rate and spam complaints to ensure the agent is not damaging your domain reputation.
#SalesAI #SDRAgent #LeadQualification #OutreachAutomation #Python #AgenticAI #LearnAI #AIEngineering

Written by
Sagar Shankaran· Founder, CallSphere
LinkedInSagar Shankaran is the founder of CallSphere, where he builds production AI voice and chat agents deployed across healthcare, hospitality, real estate, and home services. He writes about agentic AI, LLM engineering, and shipping voice agents that handle real calls in production.
See how AI voice agents work for your industry. Live demo available -- no signup required.
Chengdu, Beijing, and Shenzhen SaaS teams lose trials to slow follow-up. CallSphere qualifies inbound leads 24/7 in Mandarin and English and books demos straight into the calendar.
Salesman AI in 2026: a founder's honest take on where AI sales agents win, where humans still win, and how CallSphere's outbound agent works.
Step-by-step build of a working agent with the OpenAI Agents SDK — Agent class, tools, handoffs, tracing — plus an eval pipeline that catches regressions before merge.
Microsoft's Copilot for Sales shipped 2026 updates that knit Dynamics, Outlook, and Teams into a single agentic surface. Here's the playbook, the per-seat pricing.
Salesloft's Rhythm AI agents shipped autonomous workflow execution in 2026 across enterprise. Here's the architecture, the pricing model, the rollout pattern.
SF Bay Area SaaS standardized on sales AI agents in 2026 across the unicorn cohort. We profile six deployments at Snowflake, Notion, Stripe, Figma.
© 2026 CallSphere Inc. All rights reserved.
Made within San Francisco
Watch how CallSphere handles real customer calls, schedules appointments, and processes payments — live.