AI Agent for CRM & Sales: Automate Lead Scoring, Follow-ups & Pipeline Management
Sales reps spend 65% of their time on non-selling activities — data entry, CRM updates, research, admin. An AI agent handles the busywork so your team does what they're paid for: closing deals.
What's Inside
- The CRM Problem Nobody Talks About
- 7 Sales Agent Capabilities
- Build: AI Lead Scoring Agent
- Build: Personalized Follow-up Agent
- Build: Contact Enrichment Agent
- Build: Revenue Forecast Agent
- Build: CRM Hygiene Agent
- Tool Comparison: 8 Sales AI Tools
- Build Your Sales Agent in 45 Minutes
- 6 Mistakes That Kill Sales Agent ROI
The CRM Problem Nobody Talks About
Your CRM is supposed to help your sales team sell more. In reality, it does the opposite:
- Data entry tax: Reps spend 5+ hours/week updating CRM fields manually
- Stale data: 30% of CRM data becomes outdated every year — wrong titles, old emails, companies that merged
- Missed follow-ups: 44% of salespeople give up after one follow-up, but 80% of deals need 5+ touches
- Lead prioritization: Without scoring, reps waste time on leads that will never convert
- Pipeline blindness: Forecasts are based on "gut feel" instead of data patterns
An AI sales agent solves all five. It watches your CRM, enriches data automatically, scores every lead, drafts personalized follow-ups, and predicts which deals will close — all without your reps touching the CRM.
Companies using AI sales agents report: 35% increase in qualified pipeline, 27% higher win rates (from better lead prioritization), and reps getting back 8+ hours per week. The ROI is measured in weeks, not months.
7 Sales Agent Capabilities
AI Lead Scoring
Score every lead based on: company fit (industry, size, revenue), behavioral signals (website visits, email opens, content downloads), engagement pattern, and similarity to past won deals. Update scores in real-time as new signals arrive.
Personalized Follow-up Drafts
Draft follow-up emails that reference: the prospect's specific pain points, their recent activity (LinkedIn posts, company news), your last conversation, and relevant case studies. Not templates — genuinely personalized outreach.
Contact & Company Enrichment
Add a company name to your CRM. The agent fills in: industry, employee count, revenue range, tech stack, recent news, key decision makers, LinkedIn profiles, and competitive landscape. Automatically.
Revenue Forecasting
Analyze pipeline data to predict: which deals will close this quarter, expected revenue range (with confidence intervals), deals at risk of slipping, and which reps need coaching. Based on patterns, not opinions.
Meeting Prep Briefs
Before every sales call, the agent creates a one-page brief: prospect background, recent company news, past interactions from CRM, relevant case studies, suggested talking points, and potential objections with rebuttals.
CRM Hygiene & Cleanup
Finds: duplicate contacts, outdated job titles, stale deals that should be closed-lost, missing fields, contacts with bounced emails. Fixes what it can automatically, flags the rest for review.
Win/Loss Analysis
Analyzes closed deals to find patterns: which industries convert best, optimal deal size, average sales cycle by segment, most effective follow-up cadence, common objections in lost deals. Turns your CRM data into a playbook.
Build: AI Lead Scoring Agent
import Anthropic from "@anthropic-ai/sdk";
import Hubspot from "@hubspot/api-client";
const anthropic = new Anthropic();
const hubspot = new Hubspot.Client({ accessToken: process.env.HUBSPOT_TOKEN });
async function scoreLeads() {
// Get recent contacts
const contacts = await hubspot.crm.contacts.searchApi.doSearch({
filterGroups: [{
filters: [{
propertyName: "createdate",
operator: "GTE",
value: daysAgo(7).getTime().toString(),
}],
}],
properties: [
"email", "firstname", "lastname", "company",
"jobtitle", "industry", "numberofemployees",
"hs_lead_status", "num_contacted_notes",
"hs_email_last_open_date", "recent_conversion_event_name",
],
limit: 100,
});
// Get historical win data for comparison
const wonDeals = await getWonDealsProfile();
for (const contact of contacts.results) {
const props = contact.properties;
// Get engagement data
const engagements = await hubspot.crm.contacts.associationsApi
.getAll(contact.id, "engagements");
const response = await anthropic.messages.create({
model: "claude-sonnet-4-20250514",
max_tokens: 300,
messages: [{
role: "user",
content: `Score this lead 0-100 for sales readiness. Return JSON:
{
"score": number,
"tier": "hot|warm|cold",
"reasoning": "why this score",
"recommended_action": "what the rep should do next",
"ideal_customer_match": 0-100
}
Lead:
- Name: ${props.firstname} ${props.lastname}
- Title: ${props.jobtitle || "Unknown"}
- Company: ${props.company || "Unknown"}
- Industry: ${props.industry || "Unknown"}
- Company size: ${props.numberofemployees || "Unknown"}
- Engagement: ${engagements.results?.length || 0} interactions
- Last email open: ${props.hs_email_last_open_date || "Never"}
- Conversion: ${props.recent_conversion_event_name || "None"}
- Status: ${props.hs_lead_status || "New"}
Our ideal customer profile:
${JSON.stringify(wonDeals.profile)}
Scoring weights:
- Title match (VP+, Director, C-level = high): 25%
- Company size fit: 20%
- Industry match: 20%
- Engagement level: 20%
- Recency of activity: 15%`
}],
});
const score = JSON.parse(response.content[0].text);
// Update HubSpot
await hubspot.crm.contacts.basicApi.update(contact.id, {
properties: {
hs_lead_status: score.tier === "hot" ? "OPEN_DEAL"
: score.tier === "warm" ? "IN_PROGRESS" : "NEW",
ai_lead_score: score.score.toString(),
ai_score_reasoning: score.reasoning,
ai_recommended_action: score.recommended_action,
},
});
console.log(`📊 ${props.firstname} ${props.lastname}: ${score.score}/100 (${score.tier})`);
}
}
async function getWonDealsProfile() {
const deals = await hubspot.crm.deals.searchApi.doSearch({
filterGroups: [{
filters: [{
propertyName: "dealstage",
operator: "EQ",
value: "closedwon",
}],
}],
properties: ["dealname", "amount", "industry", "dealtype"],
limit: 50,
});
// Build ideal customer profile from won deals
return {
profile: {
avg_deal_size: deals.results.reduce((s, d) =>
s + (parseFloat(d.properties.amount) || 0), 0) / deals.results.length,
top_industries: countBy(deals.results, d => d.properties.industry),
total_won: deals.results.length,
},
};
}
Build: Personalized Follow-up Agent
async function draftFollowUp(contactId) {
// Get contact details
const contact = await hubspot.crm.contacts.basicApi.getById(
contactId,
["email", "firstname", "lastname", "company", "jobtitle",
"industry", "notes_last_updated"]
);
// Get all notes and emails from CRM
const notes = await hubspot.crm.contacts.associationsApi
.getAll(contactId, "notes");
const emails = await hubspot.crm.contacts.associationsApi
.getAll(contactId, "emails");
// Get company news (if company known)
let companyNews = "";
if (contact.properties.company) {
companyNews = await searchRecentNews(contact.properties.company);
}
// Get relevant case studies
const caseStudies = await findRelevantCaseStudies(
contact.properties.industry
);
const response = await anthropic.messages.create({
model: "claude-sonnet-4-20250514",
max_tokens: 500,
messages: [{
role: "user",
content: `Draft a personalized follow-up email.
Contact:
- Name: ${contact.properties.firstname} ${contact.properties.lastname}
- Title: ${contact.properties.jobtitle}
- Company: ${contact.properties.company}
- Industry: ${contact.properties.industry}
Previous interactions:
${notes.results?.slice(0, 5).map(n => `- ${n.properties?.hs_note_body}`).join("\n") || "No previous notes"}
Recent company news:
${companyNews || "No recent news found"}
Relevant case study:
${caseStudies[0]?.summary || "None available"}
Rules:
- Reference something specific from previous interactions
- If there's relevant company news, weave it in naturally
- Keep under 150 words
- One clear CTA (meeting, call, or specific question)
- Sound like a human, not a sales bot
- NO "I hope this email finds you well"
- NO "Just following up" or "Circling back"
Draft ONLY the email body. No subject line.`
}],
});
// Create draft in CRM (or send via email tool)
await hubspot.crm.objects.notes.basicApi.create({
properties: {
hs_note_body: `📝 AI Draft Follow-up:\n\n${response.content[0].text}`,
hs_timestamp: Date.now().toString(),
},
associations: [{
to: { id: contactId },
types: [{ associationCategory: "HUBSPOT_DEFINED", associationTypeId: 202 }],
}],
});
return response.content[0].text;
}
Create drafts in your CRM. The rep reviews, personalizes further, and sends. AI-generated sales emails without human review damage relationships and brand. The agent accelerates the rep — it doesn't replace their judgment.
Build: Contact Enrichment Agent
async function enrichContact(contactId) {
const contact = await hubspot.crm.contacts.basicApi.getById(
contactId, ["email", "company", "firstname", "lastname"]
);
const email = contact.properties.email;
const company = contact.properties.company;
// Enrich from multiple sources
const enriched = {};
// 1. Company data from Clearbit/similar
if (company) {
const companyData = await anthropic.messages.create({
model: "claude-sonnet-4-20250514",
max_tokens: 400,
messages: [{
role: "user",
content: `Research this company. Return JSON:
{
"industry": "string",
"employee_range": "1-10|11-50|51-200|201-500|501-1000|1000+",
"annual_revenue_range": "string or null",
"founded_year": number or null,
"headquarters": "city, country",
"description": "1 sentence",
"tech_indicators": ["technologies they likely use"],
"competitors": ["top 3 competitors"]
}
Company: ${company}
Email domain: ${email?.split("@")[1] || "unknown"}
Be factual. Use null if uncertain.`
}],
});
Object.assign(enriched, JSON.parse(companyData.content[0].text));
}
// 2. Update CRM
const updateProps = {};
if (enriched.industry) updateProps.industry = enriched.industry;
if (enriched.employee_range) updateProps.numberofemployees = enriched.employee_range;
if (enriched.headquarters) updateProps.city = enriched.headquarters.split(",")[0].trim();
if (enriched.description) updateProps.ai_company_description = enriched.description;
await hubspot.crm.contacts.basicApi.update(contactId, {
properties: updateProps,
});
return enriched;
}
// Batch enrich all contacts missing key data
async function enrichAllMissing() {
const contacts = await hubspot.crm.contacts.searchApi.doSearch({
filterGroups: [{
filters: [{
propertyName: "industry",
operator: "NOT_HAS_PROPERTY",
}],
}],
properties: ["email", "company", "firstname", "lastname"],
limit: 50,
});
let enriched = 0;
for (const contact of contacts.results) {
if (!contact.properties.company) continue;
await enrichContact(contact.id);
enriched++;
await sleep(1000); // Rate limit
}
console.log(`✅ Enriched ${enriched} contacts`);
}
Build: Revenue Forecast Agent
async function forecastRevenue() {
// Get all open deals
const deals = await hubspot.crm.deals.searchApi.doSearch({
filterGroups: [{
filters: [{
propertyName: "dealstage",
operator: "NOT_IN",
values: ["closedwon", "closedlost"],
}],
}],
properties: [
"dealname", "amount", "dealstage", "closedate",
"pipeline", "hs_deal_stage_probability",
"num_contacted_notes", "hs_time_in_current_stage",
],
limit: 100,
});
// Get historical close rates by stage
const historicalRates = await getHistoricalCloseRates();
const response = await anthropic.messages.create({
model: "claude-sonnet-4-20250514",
max_tokens: 1500,
messages: [{
role: "user",
content: `Forecast revenue for this quarter. Return JSON:
{
"forecast": {
"best_case": number,
"most_likely": number,
"worst_case": number,
"confidence": "high|medium|low"
},
"at_risk_deals": [
{
"name": "deal name",
"amount": number,
"risk_reason": "why it might slip",
"recommended_action": "what to do"
}
],
"likely_to_close": [
{
"name": "deal name",
"amount": number,
"probability": 0-100,
"expected_close": "date"
}
],
"insights": ["key patterns or recommendations"]
}
Open deals (${deals.results.length}):
${deals.results.map(d => {
const p = d.properties;
return `${p.dealname}: $${p.amount || 0} | Stage: ${p.dealstage} | ` +
`Close: ${p.closedate} | Probability: ${p.hs_deal_stage_probability}% | ` +
`Time in stage: ${p.hs_time_in_current_stage || "unknown"} days`;
}).join("\n")}
Historical close rates by stage:
${JSON.stringify(historicalRates)}
Quarter end: ${getQuarterEnd().toISOString().split("T")[0]}
Consider:
- Deals past expected close date are at higher risk
- Long time in current stage = stalled
- Low engagement (few notes) = going cold
- Apply historical stage-to-close rates, not CRM probability`
}],
});
return JSON.parse(response.content[0].text);
}
Build: CRM Hygiene Agent
async function crmHealthCheck() {
const report = {
duplicates: [],
stale_deals: [],
missing_data: [],
bounced_emails: [],
outdated_stages: [],
};
// Find duplicate contacts (same email or similar name + company)
const allContacts = await getAllContacts(["email", "firstname",
"lastname", "company"]);
const emailMap = {};
for (const c of allContacts) {
const email = c.properties.email?.toLowerCase();
if (!email) continue;
if (emailMap[email]) {
report.duplicates.push({
email,
ids: [emailMap[email], c.id],
});
}
emailMap[email] = c.id;
}
// Find stale deals (no activity in 30+ days, still "open")
const openDeals = await hubspot.crm.deals.searchApi.doSearch({
filterGroups: [{
filters: [{
propertyName: "dealstage",
operator: "NOT_IN",
values: ["closedwon", "closedlost"],
}, {
propertyName: "notes_last_updated",
operator: "LT",
value: daysAgo(30).getTime().toString(),
}],
}],
properties: ["dealname", "amount", "dealstage",
"notes_last_updated", "hubspot_owner_id"],
limit: 100,
});
report.stale_deals = openDeals.results.map(d => ({
name: d.properties.dealname,
amount: d.properties.amount,
stage: d.properties.dealstage,
last_activity: d.properties.notes_last_updated,
owner: d.properties.hubspot_owner_id,
}));
// Find contacts missing critical fields
const incomplete = await hubspot.crm.contacts.searchApi.doSearch({
filterGroups: [{
filters: [{
propertyName: "jobtitle",
operator: "NOT_HAS_PROPERTY",
}],
}],
limit: 50,
});
report.missing_data = incomplete.results.map(c => ({
id: c.id,
name: `${c.properties.firstname} ${c.properties.lastname}`,
missing: "jobtitle",
}));
// Generate report summary
console.log(`🧹 CRM Health Report:
- ${report.duplicates.length} duplicate contacts
- ${report.stale_deals.length} stale deals (30+ days no activity)
- ${report.missing_data.length} contacts missing job titles
Total issues: ${report.duplicates.length + report.stale_deals.length + report.missing_data.length}`);
return report;
}
Supercharge your sales pipeline
The AI Employee Playbook includes the complete CRM agent with lead scoring, follow-ups, enrichment, and forecasting — plus 12 other production-ready agent templates.
Get the Playbook — €29Tool Comparison: 8 Sales AI Tools
| Tool | Best For | Price | CRM Integration |
|---|---|---|---|
| HubSpot AI | Native CRM AI features | $45+/mo | ✅ Native |
| Salesforce Einstein | Enterprise lead scoring & forecasting | $50+/user/mo | ✅ Native |
| Apollo.io | Prospecting & contact enrichment | Free / $49/mo | ✅ HubSpot, SF |
| Clay | Data enrichment & outbound sequences | $149/mo | ✅ Most CRMs |
| Gong | Call intelligence & deal analytics | Custom pricing | ✅ Most CRMs |
| Lavender | AI email coaching for reps | Free / $29/mo | ⚠️ Email only |
| Instantly / Smartlead | Cold email at scale | $30-97/mo | ⚠️ Basic |
| Custom Agent (this guide) | Full control, any CRM | ~$10-30/mo (API) | ✅ You build it |
Our recommendation: Use Apollo or Clay for enrichment — they have real data, not AI guesses. Use Gong if you have budget for call intelligence. Build a custom agent when you need lead scoring tailored to your ICP, follow-up cadences that match your sales process, or integration across multiple tools.
Build Your Sales Agent in 45 Minutes
Connect Your CRM
Get your CRM API key (HubSpot: Settings → Integrations → API key. Pipedrive: Personal preferences → API. Salesforce: Connected Apps). Install the SDK: npm install @hubspot/api-client @anthropic-ai/sdk.
Build Lead Scoring
Copy the lead scoring code above. Define your Ideal Customer Profile from won deals. Create custom properties in your CRM for ai_lead_score and ai_recommended_action. Run it on your last 50 leads to test.
Add Follow-up Drafts
Copy the follow-up agent code. Test with 5 contacts. Review the drafts — are they specific enough? Adjust the system prompt based on your writing style and sales process.
Schedule Automation
Run lead scoring daily at 7 AM (before reps start). Run enrichment on new contacts immediately (webhook trigger). Run CRM hygiene weekly on Sundays. Run forecasting every Monday morning.
Set Up Alerts
Send Slack notifications for: hot leads (score > 80), deals at risk, stale pipeline alerts. Morning digest for each rep: "3 hot leads to call, 2 follow-ups due, 1 deal needs attention."
6 Mistakes That Kill Sales Agent ROI
Using AI data instead of real data for enrichment
Claude can guess company info, but it's often wrong or outdated. Use real data APIs (Clearbit, Apollo, ZoomInfo) for enrichment. Use AI to synthesize and analyze the real data — not to make up facts about prospects.
Auto-sending AI-generated emails
The fastest way to damage your brand and deliverability. AI drafts should always be reviewed by a human. Bad personalization ("I saw your company does [wrong thing]") is worse than no personalization at all.
Scoring leads without historical validation
If your scoring model wasn't trained on YOUR won deals, it's just guessing. Start by analyzing 50+ won deals to build your ICP. Then score new leads against that profile. Validate monthly: do high-scored leads actually convert more?
Over-automating the human parts
Some parts of sales NEED to be human: discovery calls, complex negotiations, relationship-building at events, handling sensitive objections. The agent handles admin so reps have MORE time for these high-value human moments.
Not tracking agent accuracy
Measure: how often do reps use AI drafts vs rewrite them? Do high-scored leads convert at higher rates? Are enriched fields accurate? Without tracking, you're flying blind. Review monthly and adjust.
Building before cleaning
Running AI on a messy CRM amplifies the mess. Before deploying any agent: deduplicate contacts, update stale records, standardize fields. Clean data in = useful output. Garbage in = confident garbage out.
Close more deals with less CRM busywork
The AI Employee Playbook includes the complete sales agent with scoring, follow-ups, enrichment, and forecasting — plus 12 other agent templates.
Get the Playbook — €29What's Next
Start with CRM hygiene — clean your data before building on it. Then add lead scoring based on your historical wins. Next, set up enrichment for new contacts. Finally, add follow-up drafts and forecasting.
The sales teams that win with AI aren't the ones with the most automation. They're the ones that use AI to eliminate the busywork that keeps reps from selling. Your best closer shouldn't be updating CRM fields — they should be on the phone.
Want the complete agent-building system?
The AI Employee Playbook covers the 3-file framework, memory systems, autonomy rules, and real production examples.
Get the Playbook — €29