File size: 3,959 Bytes
8bab08d
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
# file: agents/contactor.py
"""
Contactor Agent - Discovers decision-makers at target companies
Now uses web search to find real contacts instead of generating mock data
"""
from app.schema import Prospect, Contact
from app.config import SKIP_WEB_SEARCH
import logging
from services.prospect_discovery import get_prospect_discovery_service

logger = logging.getLogger(__name__)


class Contactor:
    """
    Discovers and validates decision-maker contacts

    IMPROVED: Now uses web search to discover real decision-makers
    Falls back to plausible generated contacts when search doesn't find results
    """

    def __init__(self, mcp_registry):
        self.mcp = mcp_registry
        self.store = mcp_registry.get_store_client()
        self.prospect_discovery = get_prospect_discovery_service()

    async def run(self, prospect: Prospect) -> Prospect:
        """Discover decision-maker contacts"""

        logger.info(f"Contactor: Finding contacts for '{prospect.company.name}'")

        # Check domain suppression first
        suppressed = await self.store.check_suppression(
            "domain",
            prospect.company.domain
        )

        if suppressed:
            logger.warning(f"Contactor: Domain suppressed: {prospect.company.domain}")
            prospect.status = "dropped"
            prospect.dropped_reason = f"Domain suppressed: {prospect.company.domain}"
            await self.store.save_prospect(prospect)
            return prospect

        # Get existing contacts to dedupe
        seen_emails = set()
        try:
            existing = await self.store.list_contacts_by_domain(prospect.company.domain)
            for contact in existing:
                if hasattr(contact, 'email'):
                    seen_emails.add(contact.email.lower())
        except Exception as e:
            logger.error(f"Contactor: Error fetching existing contacts: {str(e)}")

        # Discover contacts using web search
        contacts = []
        try:
            # Determine number of contacts based on company size
            max_contacts = 2 if prospect.company.size < 100 else 3

            discovered_contacts = await self.prospect_discovery.discover_contacts(
                company_name=prospect.company.name,
                domain=prospect.company.domain,
                company_size=prospect.company.size,
                max_contacts=max_contacts,
                skip_search=SKIP_WEB_SEARCH  # Respect SKIP_WEB_SEARCH flag
            )

            # Filter out already seen emails and check individual email suppression
            for contact in discovered_contacts:
                email_lower = contact.email.lower()

                # Skip if already seen
                if email_lower in seen_emails:
                    logger.info(f"Contactor: Skipping duplicate email: {contact.email}")
                    continue

                # Check email-level suppression
                email_suppressed = await self.store.check_suppression("email", contact.email)
                if email_suppressed:
                    logger.warning(f"Contactor: Email suppressed: {contact.email}")
                    continue

                # Set prospect ID
                contact.prospect_id = prospect.id

                # Save and add to list
                await self.store.save_contact(contact)
                contacts.append(contact)
                seen_emails.add(email_lower)

                logger.info(f"Contactor: Added contact: {contact.name} ({contact.title})")

        except Exception as e:
            logger.error(f"Contactor: Error discovering contacts: {str(e)}")
            # Continue with empty contacts list

        # Update prospect
        prospect.contacts = contacts
        prospect.status = "contacted"
        await self.store.save_prospect(prospect)

        logger.info(f"Contactor: Found {len(contacts)} contacts for '{prospect.company.name}'")

        return prospect