πŸŽ‰ 75% of content is free forever β€” Unlock Premium from $10/mo β†’
CW
Search courses…
πŸ’Ό Servicesℹ️ Aboutβœ‰οΈ ContactView Pricing Plansfrom $10

B2B Sales Outreach Agent

AI AgentsSales Outreach Agent🟒 Free Lesson

Advertisement

B2B Sales Outreach Agent

Sales Outreach AgentLead ScorerEmail WriterCRM SyncFollow-upProspect ResearchCampaign ManagerSales Orchestrator

What is a Sales Outreach Agent?

Sales outreach agents automate the prospecting and engagement process by scoring leads, personalizing outreach, managing CRM data, and automating follow-up sequences. They enable sales teams to focus on high-value conversations while automation handles research and initial contact.

The key pipeline is: lead research β†’ scoring β†’ personalized outreach β†’ response tracking β†’ follow-up automation. Each step is optimized using data from previous campaigns to improve conversion rates.

These agents transform cold outreach into warm, personalized engagement by leveraging prospect data and company intelligence.

Project Overview

We will build a sales outreach agent that:

  • Scores leads based on fit and engagement signals
  • Researches prospects from public data
  • Generates personalized outreach emails
  • Manages follow-up sequences
  • Tracks campaign performance
  • Integrates with CRM systems

Expected outcome: An agent that increases response rates through personalized, data-driven outreach.

Difficulty: Advanced (requires understanding of sales methodology, personalization, and CRM integration)

Architecture

Sales Agent ArchitectureLead ScorerFit + engagementProspect ResearchCompany + personEmail GeneratorPersonalized copySequence ManagerCRM IntegrationAnalyticsSales Orchestrator

Tools & Setup

ToolVersionPurpose
Python3.11+Core language
openai1.0+LLM backbone
httpx0.27+API calls
pydantic2.0+Data models
pandas2.0+Analytics

Step 1: Environment Setup

python -m venv venv
source venv/bin/activate
pip install openai httpx pydantic pandas
export OPENAI_API_KEY="sk-your-key"

Step 2: Project Structure

Architecture Diagram
sales-agent/
β”œβ”€β”€ leads/
β”‚   β”œβ”€β”€ __init__.py
β”‚   └── scorer.py
β”œβ”€β”€ outreach/
β”‚   β”œβ”€β”€ __init__.py
β”‚   β”œβ”€β”€ researcher.py
β”‚   └── email_generator.py
β”œβ”€β”€ sequences/
β”‚   β”œβ”€β”€ __init__.py
β”‚   └── manager.py
β”œβ”€β”€ analytics/
β”‚   β”œβ”€β”€ __init__.py
β”‚   └── tracker.py
β”œβ”€β”€ agent.py
└── main.py

Step 3: Lead Scorer

# leads/scorer.py
from openai import OpenAI
from typing import Dict
import json

class LeadScorer:
    def __init__(self, model: str = "gpt-4-turbo-preview"):
        self.client = OpenAI()
        self.model = model

    def score(self, lead: Dict) -> Dict:
        response = self.client.chat.completions.create(
            model=self.model,
            messages=[
                {"role": "system", "content": """Score this B2B sales lead.
                Consider: company size, industry fit, role seniority, engagement signals, intent.
                Return JSON:
                {
                    "score": 1-100,
                    "fit_score": 1-10,
                    "intent_score": 1-10,
                    "timing_score": 1-10,
                    "grade": "A|B|C|D",
                    "reasoning": "explanation",
                    "recommended_approach": "strategy suggestion"
                }"""},
                {"role": "user", "content": json.dumps(lead, indent=2)},
            ],
            temperature=0.0,
        )
        try:
            return json.loads(response.choices[0].message.content)
        except:
            return {"score": 50, "grade": "C", "reasoning": "Unable to score"}

    def score_batch(self, leads: list) -> list:
        return [self.score(lead) for lead in leads]

    def prioritize(self, leads: list) -> list:
        scored = [{"lead": lead, "score": self.score(lead)} for lead in leads]
        return sorted(scored, key=lambda x: x["score"].get("score", 0), reverse=True)

Step 4: Prospect Research and Email Generation

# outreach/researcher.py
from openai import OpenAI
from typing import Dict
import json

class ProspectResearcher:
    def __init__(self, model: str = "gpt-4-turbo-preview"):
        self.client = OpenAI()
        self.model = model

    def research(self, prospect: Dict) -> Dict:
        response = self.client.chat.completions.create(
            model=self.model,
            messages=[
                {"role": "system", "content": """Research this prospect and provide insights for personalized outreach.
                Return JSON:
                {
                    "pain_points": ["likely challenges"],
                    "interests": ["professional interests"],
                    "recent_news": "any relevant company news",
                    "personalization_hooks": ["things to mention"],
                    "best_approach": "recommended outreach strategy"
                }"""},
                {"role": "user", "content": f"Prospect: {json.dumps(prospect, indent=2)}"},
            ],
            temperature=0.2,
        )
        try:
            return json.loads(response.choices[0].message.content)
        except:
            return {"pain_points": [], "personalization_hooks": []}

# outreach/email_generator.py
from openai import OpenAI
from typing import Dict

class EmailGenerator:
    def __init__(self, model: str = "gpt-4-turbo-preview"):
        self.client = OpenAI()
        self.model = model

    def generate_cold_email(
        self, prospect: Dict, research: Dict, product: str, tone: str = "professional"
    ) -> Dict:
        response = self.client.chat.completions.create(
            model=self.model,
            messages=[
                {"role": "system", "content": f"""Write a personalized cold outreach email.
                Tone: {tone}
                Product: {product}
                
                Rules:
                - Subject line under 50 characters
                - Opening that references something specific about them
                - Value proposition tied to their pain points
                - Clear, low-friction CTA
                - Under 150 words
                - No generic phrases like "I hope this finds you well\""""},
                {"role": "user", "content": f"Prospect: {prospect.get('name', 'Unknown')} at {prospect.get('company', 'Unknown')}\nRole: {prospect.get('role', 'Unknown')}\n\nResearch insights:\n{research}"},
            ],
            temperature=0.7,
        )
        content = response.choices[0].message.content
        return {
            "subject": content.split("\n")[0].replace("Subject:", "").strip() if "\n" in content else "Quick question",
            "body": content,
            "personalization_hooks": research.get("personalization_hooks", []),
        }

    def generate_followup(
        self, original_email: str, response: str = None, step: int = 1
    ) -> str:
        prompt = f"Write follow-up email #{step} for this sequence."
        if response:
            prompt += f"\n\nTheir response: {response}"
        prompt += f"\n\nOriginal email: {original_email[:500]}"
        response = self.client.chat.completions.create(
            model=self.model,
            messages=[
                {"role": "system", "content": "Write brief, value-adding follow-up emails. Under 100 words."},
                {"role": "user", "content": prompt},
            ],
            temperature=0.7,
        )
        return response.choices[0].message.content

Step 5: Sequence Manager and Agent

# sequences/manager.py
from typing import Dict, List
from datetime import datetime, timedelta

class SequenceManager:
    def __init__(self):
        self.sequences: Dict[str, List[Dict]] = {}

    def create_sequence(self, lead_id: str, steps: List[Dict]) -> str:
        sequence_id = f"seq_{lead_id}_{datetime.now().strftime('%Y%m%d')}"
        self.sequences[sequence_id] = {
            "lead_id": lead_id,
            "steps": steps,
            "current_step": 0,
            "status": "active",
            "created_at": datetime.now().isoformat(),
        }
        return sequence_id

    def get_next_action(self, sequence_id: str) -> Dict:
        seq = self.sequences.get(sequence_id)
        if not seq or seq["status"] != "active":
            return {"action": "none"}
        current = seq["current_step"]
        if current >= len(seq["steps"]):
            seq["status"] = "completed"
            return {"action": "none"}
        step = seq["steps"][current]
        seq["current_step"] = current + 1
        return step

    def pause_sequence(self, sequence_id: str) -> None:
        if sequence_id in self.sequences:
            self.sequences[sequence_id]["status"] = "paused"

    def resume_sequence(self, sequence_id: str) -> None:
        if sequence_id in self.sequences:
            self.sequences[sequence_id]["status"] = "active"

# agent.py
from leads.scorer import LeadScorer
from outreach.researcher import ProspectResearcher
from outreach.email_generator import EmailGenerator
from sequences.manager import SequenceManager
from typing import Dict, List

class SalesOutreachAgent:
    def __init__(self, model: str = "gpt-4-turbo-preview"):
        self.scorer = LeadScorer(model)
        self.researcher = ProspectResearcher(model)
        self.email_gen = EmailGenerator(model)
        self.sequence_mgr = SequenceManager()

    def process_lead(self, lead: Dict, product: str) -> Dict:
        score = self.scorer.score(lead)
        research = self.researcher.research(lead)
        email = self.email_gen.generate_cold_email(lead, research, product)
        return {
            "lead": lead,
            "score": score,
            "research": research,
            "email": email,
        }

    def create_outreach_sequence(self, lead: Dict, product: str) -> str:
        data = self.process_lead(lead, product)
        steps = [
            {"type": "email", "content": data["email"]["body"], "delay_days": 0},
            {"type": "email", "content": "followup_1", "delay_days": 3},
            {"type": "email", "content": "followup_2", "delay_days": 7},
            {"type": "task", "content": "LinkedIn connect", "delay_days": 5},
            {"type": "email", "content": "breakup_email", "delay_days": 14},
        ]
        return self.sequence_mgr.create_sequence(lead.get("email", "unknown"), steps)

    def batch_outreach(self, leads: List[Dict], product: str) -> List[Dict]:
        prioritized = self.scorer.prioritize(leads)
        results = []
        for item in prioritized[:10]:
            result = self.process_lead(item["lead"], product)
            results.append(result)
        return results

Mathematical Foundation

Lead Score Calculation:

Where each parameter means:

  • β€” fit score (company/role match)
  • β€” intent score (buying signals)
  • β€” timing score (urgency indicators)
  • β€” engagement score (interaction history)

Intuition: Weighted combination of fit, intent, timing, and engagement for holistic scoring.

Sequence Conversion Rate:

Intuition: Percentage of outreach that converts to desired outcome.

Testing & Evaluation

import pytest
from leads.scorer import LeadScorer

def test_lead_scoring():
    scorer = LeadScorer()
    lead = {"name": "John", "company": "TechCorp", "role": "CTO", "company_size": 500}
    score = scorer.score(lead)
    assert "score" in score
    assert 1 <= score["score"] <= 100

def test_email_generation():
    gen = EmailGenerator()
    email = gen.generate_cold_email(
        {"name": "John", "company": "TechCorp"},
        {"pain_points": ["scaling issues"]},
        "Cloud Platform"
    )
    assert "subject" in email
    assert "body" in email

Performance Metrics

MetricValueNotes
Lead Scoring Time2-5sPer lead
Email Generation3-8sPersonalized
Research Time5-10sPer prospect
Sequence Creation10-15sFull sequence
Batch Processing50+ leads/hrWith prioritization

Deployment

# main.py
from agent import SalesOutreachAgent

def main():
    agent = SalesOutreachAgent()
    print("Sales Outreach Agent Ready\n")
    while True:
        cmd = input("Command (score/outreach/batch/quit): ").strip()
        if cmd == "quit":
            break
        elif cmd == "outreach":
            name = input("Prospect name: ").strip()
            company = input("Company: ").strip()
            product = input("Your product: ").strip()
            result = agent.process_lead({"name": name, "company": company}, product)
            print(f"\nScore: {result['score']['score']}/100")
            print(f"Email:\n{result['email']['body']}\n")

if __name__ == "__main__":
    main()

Real-World Use Cases

  • SaaS Sales: Outbound prospecting for software products
  • Agency Business Development: Client acquisition campaigns
  • Recruiting: Candidate outreach and engagement
  • Partnership Development: Business development outreach
  • Event Promotion: Conference and webinar invitations

Common Pitfalls & Solutions

PitfallSolution
Generic emails feel spammyDeep personalization with research
Low response ratesA/B test subject lines and CTAs
Email deliverabilityWarm up domains, monitor reputation
CRM data qualityRegular data enrichment and validation
Compliance (CAN-SPAM)Include unsubscribe, physical address

Summary with Key Takeaways

  • Lead scoring prioritizes outreach for highest conversion potential
  • Prospect research enables genuine personalization at scale
  • Multi-step sequences nurture leads over time
  • Performance tracking enables continuous optimization
  • Always comply with email regulations (CAN-SPAM, GDPR)

Need Expert AI Agents Help?

Get personalized tutoring, project support, or professional consulting.

Advertisement