How to Improve Sales Outreach: Stop Guessing, Start Building Agents
Last quarter, our sales team was drowning. We had a decent product, a clear ICP, but our outbound sequences felt like throwing darts in the dark. Personalization was the buzzword, but actually doing it at scale? That meant hours of manual LinkedIn stalking, CRM updates, and then still crafting emails that often missed the mark. We tried the usual “AI-powered” tools, the ones promising to write emails for us, but they mostly spat out generic fluff. The conversion rates were flat, and the team was burnt out. I knew there had to be a better way to improve sales outreach than just hiring more SDRs to do the same tedious work.
The Agent Approach: Beyond Basic Automation
We weren’t looking for another glorified mail merge. We needed something that could reason about a prospect, not just fill in blanks. My goal was to build an agent that could:
- Scrape relevant, recent company news or LinkedIn activity.
- Synthesize that information into a genuinely personalized opening line and value proposition.
- Draft a concise, human-sounding cold email.
- Adapt its approach based on initial replies (or lack thereof).
This isn’t a “set it and forget it” dream. It’s about augmenting, not replacing. We started with a simple LangGraph setup, defining nodes for data collection, content generation, and a human review step. The initial version was clunky, but it showed promise.
Building Smarter Outreach: Data, Personalization, and the Debugging Nightmare
The first step was data. Generic firmographics aren’t enough for true personalization. We needed recent, relevant triggers. This is where tools like Clay.com became invaluable. We’d feed it a list of target companies, and it would pull recent news, funding rounds, job postings, and even specific employee roles. It’s a powerful data enrichment platform, and frankly, it saved us weeks of custom scraping work. For anyone serious about data-driven outreach, I’d suggest checking out Clay.com; it pulls in so much more than just the basics.
Once we had the data, the agent’s job was to make sense of it. We used a custom tool within our LangGraph agent that would take the raw data and identify key talking points. For example, if a company just raised a Series B, the agent would prioritize messaging around scaling challenges or growth initiatives. If they hired a new Head of Sales, it would focus on sales efficiency or team enablement.
Here’s a simplified Python snippet of how we’d structure a “personalization” tool:
def generate_personalization_points(company_data: dict) -> list[str]:
points = []
if "recent_news" in company_data and company_data["recent_news"]:
points.append(f"Saw your recent news about {company_data['recent_news'][0]['headline']}.")
if "funding_round" in company_data and company_data["funding_round"]["amount"] > 0:
points.append(f"Congratulations on your recent {company_data['funding_round']['stage']} funding of ${company_data['funding_round']['amount']}.")
if "job_postings" in company_data and any("sales" in job.lower() for job in company_data["job_postings"]):
points.append("Noticed you're hiring for sales roles, suggesting growth in that area.")
return points
# Example usage within an agent step
# personalization_data = agent_tools.get_company_data(company_id)
# talking_points = generate_personalization_points(personalization_data)
# email_draft = llm_model.generate_email(prospect_name, talking_points)
This part worked surprisingly well, but it wasn’t without its headaches. Debugging multi-step agents, especially when an LLM is involved, is a special kind of hell. A minor prompt change in one node could cascade into completely irrelevant emails downstream. We quickly realized we needed proper observability. LangSmith became indispensable here. Being able to trace the execution path, see the inputs and outputs of each LLM call, and understand why an agent decided to take a certain path was crucial. Without it, we were just guessing, throwing prompts at the wall and hoping something stuck. Honestly, LangSmith is the only tool I’d actually pay for in this category, even at its current pricing, because it saves so much developer time.
My concrete gripe? The sheer cost of iterating on prompts with expensive models. When an agent gets stuck in a loop, or you’re just trying to find the right tone, those API calls add up fast. We burned through a few hundred dollars in a single afternoon just tweaking a single generation step. It’s a real barrier for smaller teams.