AI Outbound Sales: Personalizing Prospecting at Scale Without Being Spammy
How to use AI to research prospects and write genuinely personalized outreach that gets replies
AI Outbound Sales: Personalized Prospecting at Scale
Cold outreach is broken. Generic "Hi [FirstName], I noticed you're a [Title] at [Company]" emails get 1-2% reply rates. But truly personalized outreach — referencing specific things about the person and company — gets 8-15% reply rates. AI makes personalization scalable.
The Personalization Paradox
True personalization requires research: reading the prospect's LinkedIn, their company's news, their recent posts, their company's tech stack. This takes 15-30 minutes per prospect.
At scale, this is impossible. But AI can do this research and drafting in seconds.
Building a Personalization Engine
python
import anthropic
from openai import OpenAI
import json
import httpx
from dataclasses import dataclass
from typing import Optionalclient = anthropic.Anthropic()
openai_client = OpenAI()
@dataclass
class ProspectResearch:
company_name: str
prospect_name: str
job_title: str
company_news: list[str]
linkedin_posts: list[str]
company_tech_stack: list[str]
company_size: str
recent_funding: Optional[str]
job_postings: list[str] # Hiring signals
competitor_connections: list[str]
class AIProspectResearcher:
"""
Automates prospect research for personalized outreach.
"""
def research_company(self, company_name: str, domain: str) -> dict:
"""
Research a company using available signals.
In production: use APIs from Clearbit, Apollo, LinkedIn, etc.
"""
# This is a framework - replace with real API calls
research_data = {
'company_name': company_name,
'recent_news': self._get_company_news(company_name),
'job_postings': self._get_job_postings(domain),
'tech_stack': self._get_tech_stack(domain),
'funding': self._get_funding_data(company_name),
'size_estimate': self._estimate_company_size(domain)
}
return research_data
def _get_company_news(self, company_name: str) -> list[str]:
"""Get recent company news from news APIs."""
# Would use: NewsAPI, Google News API, or web scraping
return [f"Recent news for {company_name} would appear here"]
def _get_job_postings(self, domain: str) -> list[str]:
"""Get job postings as intent signals."""
# Hiring for AI/ML engineers = investing in AI
# Hiring for SDRs = scaling sales
# Job postings reveal strategic priorities
return ["Example: 5 AI/ML engineer postings (investing in AI infrastructure)"]
def _get_tech_stack(self, domain: str) -> list[str]:
"""Get company's tech stack from Clearbit, BuiltWith, etc."""
return ["Salesforce", "HubSpot", "Slack", "AWS"]
def _get_funding_data(self, company_name: str) -> Optional[str]:
"""Get funding information from Crunchbase API."""
return "Series B - $45M raised, announced 3 months ago"
def _estimate_company_size(self, domain: str) -> str:
"""Estimate company size from LinkedIn or Clearbit."""
return "201-500 employees"
class OutreachPersonalizer:
"""
Generates personalized outreach based on prospect research.
"""
def __init__(self):
self.client = anthropic.Anthropic()
self.researcher = AIProspectResearcher()
def generate_cold_email(self, prospect: dict, your_product: dict,
email_type: str = 'first_touch') -> dict:
"""
Generate a personalized cold email for a prospect.
email_type: first_touch, follow_up_1, follow_up_2, breakup
"""
# Research the prospect's company
company_research = self.researcher.research_company(
prospect.get('company'),
prospect.get('company_domain', '')
)
# Identify the best personalization angle
angle = self._identify_best_angle(prospect, company_research, your_product)
email_prompt = f"""Write a personalized cold {email_type} email to:
Name: {prospect.get('name')}
Title: {prospect.get('title')}
Company: {prospect.get('company')}
Best personalization angle: {angle['angle']}
Evidence: {angle['evidence']}
About our product:
Name: {your_product.get('name')}
Value proposition: {your_product.get('value_prop')}
Relevant use case for them: {your_product.get('use_case_for_prospect')}
Social proof: {your_product.get('customer_proof', 'customer example')}
Email requirements:
Subject line: <40 characters, personalized, curiosity-driven (NO "Quick question" or "Following up")
Opening: Reference SPECIFIC, REAL thing about them (not generic flattery)
Middle: Connect their situation to a specific problem you solve (1-2 sentences)
CTA: Single, specific, low-commitment ask (15-minute call OR reply to question)
Length: Under 100 words for first touch
Tone: Peer-to-peer, not salesy or obsequious
NO: "I came across your profile", "I hope this finds you well", "I'd love to pick your brain" Return JSON with subject, preview_text, body, cta"""
message = self.client.messages.create(
model="claude-opus-4-5",
max_tokens=500,
messages=[{"role": "user", "content": email_prompt}]
)
try:
email_data = json.loads(message.content[0].text)
except json.JSONDecodeError:
email_data = {"body": message.content[0].text}
email_data['personalization_angle'] = angle['angle']
email_data['prospect_id'] = prospect.get('id')
return email_data
def _identify_best_angle(self, prospect: dict,
company_research: dict,
product: dict) -> dict:
"""
Identify the most relevant personalization angle.
Priority: recent news > job postings > tech stack > general role
"""
# Check for recent funding (major trigger)
if company_research.get('funding') and 'raised' in str(company_research['funding']).lower():
return {
'angle': 'recent_funding',
'evidence': company_research['funding'],
'reason': 'Companies scale teams and tools after funding'
}
# Check for relevant job postings
ai_hiring = [j for j in company_research.get('job_postings', [])
if any(tech in j for tech in ['AI', 'ML', 'data', 'automation'])]
if ai_hiring:
return {
'angle': 'ai_investment',
'evidence': ai_hiring[0],
'reason': 'Active investment in AI = likely to buy AI tools'
}
# Check tech stack for integration opportunities
if company_research.get('tech_stack'):
return {
'angle': 'tech_integration',
'evidence': f"Noticed you're using {company_research['tech_stack'][0]}",
'reason': 'Integration with existing stack'
}
# Default to role-based angle
return {
'angle': 'role_pain_point',
'evidence': f"As a {prospect.get('title')} at a growing company",
'reason': 'Generic but still targeted to role'
}
def generate_sequence(self, prospect: dict, product: dict,
num_emails: int = 4) -> list[dict]:
"""Generate a complete multi-touch sequence."""
email_types = ['first_touch', 'follow_up_1', 'follow_up_2', 'breakup']
delays_days = [0, 3, 7, 14] # Days from previous email
sequence = []
for i in range(min(num_emails, len(email_types))):
email = self.generate_cold_email(prospect, product, email_types[i])
email['send_delay_days'] = delays_days[i]
email['sequence_position'] = i + 1
sequence.append(email)
return sequence
Example: Generate outreach for a list of prospects
def run_personalization_campaign(prospects: list[dict], product: dict) -> list[dict]:
"""Generate personalized sequences for all prospects."""
personalizer = OutreachPersonalizer()
all_sequences = []
for i, prospect in enumerate(prospects):
print(f"Personalizing for {prospect.get('name')} ({i+1}/{len(prospects)})...")
try:
sequence = personalizer.generate_sequence(prospect, product)
all_sequences.append({
'prospect': prospect,
'sequence': sequence
})
except Exception as e:
print(f"Error for {prospect.get('name')}: {e}")
return all_sequences
Reply Rate Benchmarks
AI personalization gets you 80% of manual quality at 1000x the scale. For a team sending 200 emails/week, the difference between 3% and 9% reply rate is 12 additional conversations per week.
The key: Use AI to personalize the opening and angle, but make sure the product pitch is genuinely relevant. AI can't save an irrelevant offer.
Also available in 中文.