Skip to main content

How to Build Real-Time Slack Deal Alerts with OpenClaw [2026]

· 9 min read

Your best deal just went dark.

The champion replied to every email for two months, took three demos, got the contract last Tuesday. Then silence.

By the time someone notices, it's been 9 days. The deal is dead. The champion took another job. You find out from LinkedIn.

This happens constantly because CRM data is passive. It waits for someone to go look at it. No one does until it's too late.

The fix: Real-time alerts in Slack where your team already lives.

This guide shows you how to build an intelligent alerting system with OpenClaw that catches pipeline problems before they become pipeline losses.

Slack notification system for real-time deal alerts

Why Slack for Sales Alerts?

Slack Is Where Attention Lives

Your reps check CRM when they have to. They check Slack constantly.

  • Average Slack user checks 20+ times daily
  • Most teams have Slack on phone with notifications
  • Real-time visibility into team activity

CRM Alerts Are Broken

Most CRM notification systems:

  • Email alerts (goes to spam or ignored)
  • In-app badges (only see when you login)
  • Daily digests (too late for urgent issues)

Slack Is Actionable

A Slack alert isn't just information—it's a jumping off point:

🚨 DEAL ALERT: Acme Corp - $48K
Contact went dark (9 days no engagement)

Champion: Sarah Chen (VP Sales)
Last activity: Email opened Feb 2, no reply
Deal stage: Negotiation (was: Verbal commit)

Actions:
[📞 Call Now] [📧 Draft Email] [📋 View in HubSpot]

One click from alert to action.

What to Alert On

Tier 1: Immediate Alerts (Real-Time)

These need instant notification:

SignalWhy It MattersAlert Channel
Champion job changeDeal at risk#deal-alerts + DM to AE
Competitor mentionedCould lose to alternative#deal-alerts
Large deal stage changePipeline impact#deal-alerts
Contract viewedHot buying signal#deal-alerts + DM
Pricing page revisitDecision imminentDM to AE

Tier 2: Same-Day Alerts (Batched)

Important but not urgent:

SignalFrequencyAlert Channel
Deals gone quiet (3+ days)Morning digest#pipeline-health
Upcoming renewals (30 days)Weekly summary#cs-alerts
Meeting no-showsWithin 1 hourDM to AE
Email bouncesDaily digest#data-quality

Context for leadership:

ReportFrequencyChannel
Pipeline changesDaily#sales-leadership
Win/loss analysisWeekly#sales-leadership
Rep activity scoresWeeklyDM to managers
Forecast vs. actualWeekly#sales-leadership

Building with OpenClaw

Step 1: Connect to Your CRM

OpenClaw needs to watch your CRM for changes. Using HubSpot as an example:

# openclaw config
integrations:
hubspot:
portalId: "YOUR_PORTAL_ID"
privateAppToken: ${HUBSPOT_TOKEN}
watchEntities:
- deals
- contacts
- activities

Step 2: Define Alert Rules

Create an alert agent that watches for specific patterns:

// alert-rules.js
const alertRules = {
// Champion job change (via email bounce or LinkedIn)
championJobChange: {
trigger: 'contact.job_title_changed OR contact.email_bounced',
condition: (contact, deal) => deal.amount > 20000 && deal.stage !== 'Closed',
severity: 'critical',
channel: '#deal-alerts',
dmOwner: true,
message: (contact, deal) => `
🚨 *CHAMPION ALERT: Job Change Detected*
*Deal:* ${deal.name} — $${deal.amount.toLocaleString()}
*Contact:* ${contact.name} (${contact.old_title}${contact.new_title || 'Unknown'})
*Action Required:* Verify contact status, identify new champion

[View Deal](${deal.hubspot_url}) | [LinkedIn Search](https://linkedin.com/search?keywords=${encodeURIComponent(contact.name)})
`
},

// Deal gone dark
dealGoneDark: {
trigger: 'deal.last_activity_age > 5 days',
condition: (deal) => deal.amount > 10000 && !['Closed Won', 'Closed Lost'].includes(deal.stage),
severity: 'warning',
channel: '#pipeline-health',
message: (deal) => `
⚠️ *Deal Gone Quiet:* ${deal.name}
*Amount:* $${deal.amount.toLocaleString()}
*Last Activity:* ${deal.last_activity_date} (${deal.days_since_activity} days ago)
*Stage:* ${deal.stage}

[📞 Quick Action: Schedule Follow-up](${deal.hubspot_url})
`
},

// Contract viewed
contractViewed: {
trigger: 'document.viewed AND document.type = "contract"',
condition: (doc, deal) => true,
severity: 'positive',
channel: '#deal-alerts',
dmOwner: true,
message: (doc, deal) => `
🔥 *Hot Signal: Contract Viewed*
*Deal:* ${deal.name} — $${deal.amount.toLocaleString()}
*Viewer:* ${doc.viewer_email}
*Time on Doc:* ${doc.view_duration}

Strike while hot! [Call Now](tel:${deal.contact_phone})
`
},

// Large deal stage change
largeStageChange: {
trigger: 'deal.stage_changed',
condition: (deal) => deal.amount > 50000,
severity: 'info',
channel: '#deal-alerts',
message: (deal) => `
📊 *Pipeline Update:* ${deal.name}
*Amount:* $${deal.amount.toLocaleString()}
*Stage:* ${deal.old_stage}${deal.new_stage}
*Owner:* ${deal.owner_name}
`
}
};

Slack channel with deal alerts and pipeline notifications

Step 3: Set Up the Watcher Agent

OpenClaw runs the alerting logic:

# openclaw agent config
agents:
deal_watcher:
name: "Deal Watcher"
schedule:
realtime:
- hubspot.deal.updated
- hubspot.contact.updated
- hubspot.email.sent
cron:
- "*/15 * * * *" # Every 15 min for batch checks

task: |
For each CRM event:
1. Check against all alert rules
2. If triggered, format and send to appropriate Slack channel
3. If dmOwner, also DM the deal owner
4. Log alert to tracking table (avoid duplicates)

For batch checks (cron):
1. Query deals with no activity > threshold
2. Group by owner
3. Send summary to #pipeline-health

Step 4: Configure Slack Integration

integrations:
slack:
botToken: ${SLACK_BOT_TOKEN}
channels:
deal-alerts: "C0123456789"
pipeline-health: "C0123456790"
sales-leadership: "C0123456791"

messageDefaults:
unfurl_links: false
unfurl_media: false

Step 5: Add Smart Deduplication

Nobody wants the same alert 47 times:

// dedup.js
const alertCache = new Map();

function shouldSendAlert(alertKey, cooldownMinutes = 60) {
const lastSent = alertCache.get(alertKey);
const now = Date.now();

if (lastSent && (now - lastSent) < cooldownMinutes * 60 * 1000) {
return false; // Skip, sent recently
}

alertCache.set(alertKey, now);
return true;
}

// Usage
const alertKey = `dark_deal_${deal.id}`;
if (shouldSendAlert(alertKey, 1440)) { // Once per day max
sendSlackAlert(channel, message);
}

Advanced Patterns

Pattern 1: Engagement Scoring Alerts

Combine multiple signals into a score:

const engagementScore = (deal) => {
let score = 0;

// Positive signals
if (deal.email_opened_last_7d) score += 10;
if (deal.link_clicked_last_7d) score += 20;
if (deal.meeting_scheduled) score += 30;
if (deal.pricing_page_view) score += 25;
if (deal.contract_viewed) score += 40;

// Negative signals
if (deal.days_since_activity > 7) score -= 20;
if (deal.emails_no_reply > 3) score -= 15;
if (deal.meeting_no_show) score -= 30;

return score;
};

// Alert on score drops
if (deal.previous_score - deal.current_score > 30) {
sendAlert('engagement_drop', deal);
}

Pattern 2: Multi-Threading Alerts

When you only have one contact at a company:

const singleThreadAlert = {
trigger: 'deal.stage = "Proposal" AND deal.contacts.count = 1',
message: (deal) => `
⚠️ *Single Thread Risk:* ${deal.name}
Only contact: ${deal.contacts[0].name} (${deal.contacts[0].title})
Recommendation: Get intro to economic buyer before negotiation

[Research Contacts](https://linkedin.com/company/${deal.company_linkedin}/people)
`
};

Pattern 3: Competitive Intelligence Alerts

Watch for competitor mentions:

// Scan email content, call notes, Gong transcripts
const competitorMentioned = {
trigger: 'activity.body CONTAINS competitor_keywords',
competitors: ['Apollo', '6sense', 'ZoomInfo', 'Demandbase'],
message: (activity, deal, competitor) => `
🎯 *Competitor Mentioned:* ${competitor}
*Deal:* ${deal.name} — $${deal.amount}
*Context:* ${activity.snippet}

[View Full Activity](${activity.url}) | [Competitive Battlecard](${battlecard_url(competitor)})
`
};

Pattern 4: Renewal Risk Alerts

For customer success teams:

const renewalRisk = {
trigger: 'deal.type = "renewal" AND deal.close_date < 60_days_out',
condition: (deal) => {
const riskFactors = [];
if (deal.nps_score < 7) riskFactors.push('Low NPS');
if (deal.support_tickets_open > 3) riskFactors.push('Open tickets');
if (deal.usage_trend === 'declining') riskFactors.push('Usage down');
if (deal.champion_left) riskFactors.push('Champion departed');
return riskFactors.length >= 2;
},
message: (deal, risks) => `
🚨 *Renewal at Risk:* ${deal.company}
*ARR:* $${deal.amount} | *Renewal:* ${deal.close_date}
*Risk Factors:* ${risks.join(', ')}

[Customer Health Dashboard](${deal.cs_dashboard_url})
`
};

Organizing Your Channels

#deal-alerts          — Critical real-time alerts (AEs + managers)
#pipeline-health — Daily summaries and trends (AEs + managers)
#sales-leadership — High-level pipeline updates (leadership)
#cs-alerts — Customer success notifications (CS team)
#data-quality — Bounces, duplicates, etc. (ops team)

Channel Hygiene

Keep channels useful:

  • #deal-alerts: Only urgent, actionable items. Max 10-15/day.
  • #pipeline-health: Batched digests. Once or twice daily.
  • #sales-leadership: Weekly summaries unless something major.

If a channel gets too noisy, people mute it. Then it's useless.

Measuring Alert Effectiveness

Track whether alerts actually help:

const alertMetrics = {
// Track each alert type
alertsSent: {},
alertsActedOn: {}, // User clicked action button
outcomeAfterAlert: {}, // Did the deal status improve?

// Calculate value
alertROI: (alertType) => {
const sent = alertsSent[alertType];
const acted = alertsActedOn[alertType];
const saved = outcomeAfterAlert[alertType].filter(o => o === 'saved');

return {
actionRate: acted / sent,
saveRate: saved / acted,
dealValueSaved: saved.reduce((sum, d) => sum + d.amount, 0)
};
}
};

Good benchmarks:

  • Action rate (clicked button): >40%
  • Alert-to-save rate: >15%
  • Average response time: &lt;2 hours for critical alerts

Common Mistakes to Avoid

Alert Fatigue

The biggest risk. If everything is an alert, nothing is.

Fix it:

  • Ruthlessly prioritize what deserves real-time alerts
  • Use batching for everything else
  • Track channel mute rates—if >30%, you're too noisy

Missing Context

An alert without context creates work:

❌ BAD:
"Deal Acme Corp updated"

✅ GOOD:
"🔥 Deal Acme Corp ($48K) — Champion viewed contract 3x in last hour
Last touch: Pricing call Tuesday
Decision: Expected this week
[Call Sarah Now] [View Timeline]"

No Action Path

Every alert should answer: "What do I do next?"

Include buttons/links to:

  • Call the contact
  • Send a pre-drafted email
  • View the full record
  • Escalate to manager

Ignoring Time Zones

Don't send alerts at 3am. Configure quiet hours:

const shouldAlertNow = (owner, alertPriority) => {
const ownerTz = owner.timezone || 'America/Chicago';
const localHour = moment().tz(ownerTz).hour();

// Critical alerts: always
if (alertPriority === 'critical') return true;

// Others: business hours only
return localHour >= 8 && localHour <= 20;
};

Integrating with MarketBetter

MarketBetter's Daily SDR Playbook already identifies the highest-priority accounts and actions. Add Slack alerts to:

  • Push today's top priorities — Morning notification of must-do tasks
  • Alert on engagement — When a playbook account shows buying signals
  • Track follow-through — Confirm reps are working suggested accounts

Want to see intelligent alerting built into your SDR workflow? Book a demo and we'll show you how real-time signals drive real-time action.

Getting Started

Week 1: Foundation

  1. Set up OpenClaw with HubSpot/Salesforce connection
  2. Create #deal-alerts channel
  3. Configure 3 critical alert types
  4. Test with your own deals

Week 2: Expand

  1. Add engagement scoring
  2. Create #pipeline-health for digests
  3. Add action buttons to alerts
  4. Roll out to full sales team

Week 3: Optimize

  1. Measure action rates
  2. Tune thresholds (too many? too few?)
  3. Add advanced patterns (multi-threading, competitor)
  4. Document what's working

Ongoing

  • Review alert effectiveness monthly
  • Add new patterns as you learn what matters
  • Remove alerts no one acts on
  • Share wins in team meetings

The deals you save are the ones you see in time. See them in Slack, where you're already looking.