| name | sales-workflow-orchestrator |
| description | The cross-platform sales automation hub. Chains CRM, Email, Calendar, LinkedIn, and Sheets into autonomous multi-step workflows. Run a morning sales routine, process new leads end-to-end, or automate deal progression -- all from a single command. |
Sales Workflow Orchestrator
The "command center" that chains all your sales tools into autonomous multi-step workflows. Instead of switching between HubSpot, Gmail, Calendar, LinkedIn, and Sheets, tell Sai what you need and it orchestrates everything.
Why this exists: Every sales tool (Salesforce, HubSpot, Reply.io, Outreach) only automates WITHIN its own platform. Sai is the only tool that can read your CRM pipeline, draft a Gmail follow-up, check your Calendar, send a LinkedIn message, and log everything to Sheets -- all in one autonomous workflow.
When to Use
- "Run my morning sales routine"
- "I have a new lead: [Name] from [Company]. Do the full cycle."
- "Check my pipeline, follow up on stale deals, and update my tracker"
- "What should I be doing today for sales?"
- "Process these 5 inbound leads"
- "My deal with [Company] just moved to proposal stage. What's next?"
Required Context (ask if not provided)
- CRM platform: Which CRM are you using? (HubSpot, Salesforce, Pipedrive, or none)
- CRM URL: The URL for your CRM dashboard (e.g., app.hubspot.com/contacts/12345/deals)
- Tracking sheet: Do you have an existing Google Sheet for pipeline tracking? (Or create new)
- LinkedIn logged in?: Confirm user is logged into LinkedIn in browser
Prerequisites
- Gmail connected (gmail_write)
- Google Calendar connected (calendar)
- Google Sheets connected (drive)
- User logged into CRM in browser (for browser automation)
- User logged into LinkedIn in browser (for LinkedIn actions)
Connect All Services
await requestApproval({
reason: "Need Gmail access to scan and send follow-up emails",
type: "service_auth",
payload: { provider: "google", service: "gmail_write" }
})
await requestApproval({
reason: "Need Calendar access to check meetings and schedule follow-ups",
type: "service_auth",
payload: { provider: "google", service: "calendar" }
})
await requestApproval({
reason: "Need Sheets access to log activities and manage pipeline tracker",
type: "service_auth",
payload: { provider: "google", service: "drive" }
})
Safety Rules (CRITICAL)
- ALWAYS present the full action plan for user review before executing ANY actions.
- Batch approval is allowed ("approve all 3 follow-ups"), but user must see every action listed.
- Never send emails or LinkedIn messages without explicit user approval.
- CRM modifications (create contact, change deal stage) require individual approval.
- Maximum 10 outbound touches per session (emails + LinkedIn combined).
- Rate limiting: 90-180 seconds between LinkedIn actions, 30-60 seconds between emails.
- If any platform shows error/CAPTCHA/rate-limit, stop the ENTIRE workflow and report.
Workflow A: Morning Sales Routine
Trigger: "Run my morning sales routine" or scheduled as daily cron at 8am.
Total time: 15-20 minutes autonomous.
Replaces: 1-2 hours of manual pipeline review, email checking, and LinkedIn browsing.
Phase 1: Pipeline Scan (3-4 min)
var crmPage = await browser.newtab(userCrmUrl)
await crmPage.wait({ waitTime: 5 })
var deals = []
var snap = await crmPage.snapshot()
var healthReport = {
green: [],
yellow: [],
red: [],
total: 0,
weighted: 0
}
console.log("Pipeline scan complete: " + deals.length + " deals")
console.log("Critical: " + healthReport.red.length + " | At risk: " + healthReport.yellow.length)
Phase 2: Email Scan (2-3 min)
var newReplies = await google.gmail.listMessages({
query: "in:inbox newer_than:1d",
maxResults: 20
})
var emailActions = {
needsReply: [],
informational: [],
dealRelated: []
}
var staleEmails = await google.gmail.listMessages({
query: "in:sent newer_than:7d",
maxResults: 30
})
Phase 3: Calendar Check (2 min)
var todayMeetings = await google.calendar.listEvents({
timeMin: new Date(new Date().setHours(0, 0, 0, 0)).toISOString(),
timeMax: new Date(new Date().setHours(23, 59, 59, 999)).toISOString()
})
var meetingPrep = todayMeetings.filter(m =>
m.attendees && m.attendees.some(a => a.email && !a.email.includes(userDomain))
).map(m => ({
time: m.start,
title: m.summary,
with: m.attendees.filter(a => !a.email?.includes(userDomain)),
needsPrep: true
}))
Phase 4: LinkedIn Check (3-4 min)
var linkedinPage = await browser.newtab("https://www.linkedin.com/feed/")
await linkedinPage.wait({ waitTime: 5 })
var linkedinOpportunities = []
Phase 5: Generate Daily Action Plan
var actionPlan = {
urgent: [],
followUp: [],
meetings: [],
engage: [],
crmUpdates: []
}
Present Action Plan
## Daily Sales Action Plan - [Date]
### Pipeline Summary
Total: $450K (25 deals) | Weighted: $180K
Critical (needs attention): 3 deals | At risk: 5 deals
### Urgent Actions (do now)
1. REPLY: Jane Doe (Acme, $50K) emailed about pricing at 11pm last night
> Draft ready: [click to review]
2. FOLLOW-UP: Bob Smith (Widget, $35K) - 8 days no reply to proposal
> Draft ready: [click to review]
### Today's Meetings (prep ready)
3. 2:00 PM: Acme Corp demo with Jane Doe
> Brief: Last email about pricing, Series B news, her recent LinkedIn post
> [View full brief]
4. 4:00 PM: Widget Inc check-in with Bob Smith
> Brief: Proposal sent 8 days ago, no response, check if they received it
### LinkedIn Engagement
5. Jane Doe posted about "content scaling challenges" (3h ago)
> Suggested comment: "The attribution challenge at scale is real..."
> [Review and approve]
### CRM Updates
6. Move Acme Corp from "Demo Scheduled" to "In Progress"
7. Create task: "Send Widget proposal follow-up" (due today)
---
Approve actions: [All] [Select individually] [Skip]
Phase 6: Execute Approved Actions
await requestApproval({
reason: "Execute " + approvedActions.length + " sales actions: " +
approvedActions.map(a => a.type + ": " + a.summary).join("; ")
})
for (var action of approvedActions) {
switch (action.type) {
case "email_reply":
await google.gmail.sendMessage(action.emailData)
console.log("Sent reply to " + action.contact)
await wait({ waitTime: 30 + Math.floor(Math.random() * 30) })
break
case "email_followup":
await google.gmail.sendMessage(action.emailData)
console.log("Sent follow-up to " + action.contact)
await wait({ waitTime: 30 + Math.floor(Math.random() * 30) })
break
case "linkedin_comment":
await linkedinPage.goto({ url: action.postUrl })
await linkedinPage.wait({ waitTime: 5 })
console.log("Commented on " + action.contact + "'s post")
await wait({ waitTime: 90 + Math.floor(Math.random() * 90) })
break
case "crm_update":
await crmPage.goto({ url: action.dealUrl })
console.log("Updated " + action.dealName + " to " + action.newStage)
await wait({ waitTime: 5 })
break
}
}
Phase 7: Log Everything
var logEntries = approvedActions.map(a => [
new Date().toISOString().slice(0, 10),
new Date().toLocaleTimeString(),
a.type,
a.contact,
a.company,
a.deal || "",
a.summary,
"Completed"
])
await google.sheets.appendValues({
spreadsheetId: trackingSheetId,
range: "'Activity Log'!A1",
values: logEntries
})
console.log("Activity log updated: " + logEntries.length + " entries")
Workflow B: New Lead - Full Cycle
Trigger: "New lead: Jane Doe from Acme Corp" or "Process this inbound lead"
Total time: 10-15 minutes
What it does: Research -> Add to CRM -> Draft multi-channel outreach -> Schedule follow-ups -> Track
Step 1: Research (5 min)
Step 2: Add to CRM (2 min)
await requestApproval({
reason: "Create new contact and deal in CRM for " + leadName + " at " + companyName
})
var crmPage = await browser.newtab(userCrmUrl)
await crmPage.wait({ waitTime: 3 })
Step 3: Draft Multi-Channel Outreach (2 min)
var emailDraft = await google.gmail.createDraft({
to: leadEmail,
subject: personalizedSubject,
body: personalizedEmailBody
})
var linkedinNote = generateConnectionNote(dossier)
console.log("Email draft saved. LinkedIn note ready.")
console.log("Email: " + emailDraft.subject)
console.log("LinkedIn note (" + linkedinNote.length + "/300 chars): " + linkedinNote)
Step 4: Schedule Follow-Up Sequence
var touchpoints = [
{ day: 0, action: "Send initial email + LinkedIn connection request" },
{ day: 3, action: "If no email reply: send LinkedIn DM (if connected)" },
{ day: 5, action: "Send email follow-up #1 (different angle)" },
{ day: 10, action: "Send email follow-up #2 (value-add or break-up)" },
{ day: 14, action: "If no response anywhere: mark as cold in CRM" }
]
for (var tp of touchpoints) {
var reminderDate = new Date(Date.now() + tp.day * 24 * 60 * 60 * 1000)
await google.calendar.createEvent({
summary: "Follow-up: " + leadName + " - Touch " + (touchpoints.indexOf(tp) + 1),
start: reminderDate.toISOString(),
end: new Date(reminderDate.getTime() + 30 * 60 * 1000).toISOString(),
description: tp.action + "\n\nCompany: " + companyName +
"\nEmail: " + leadEmail + "\nLinkedIn: " + leadLinkedIn
})
}
Step 5: Log to Tracker
await google.sheets.appendValues({
spreadsheetId: trackingSheetId,
range: "'Pipeline'!A1",
values: [[
new Date().toISOString().slice(0, 10),
leadName,
companyName,
"Inbound",
leadEmail,
leadLinkedIn,
"New Lead",
"Pending",
"",
"",
"Active",
dossier.outreachHooks[0].hook
]]
})
Workflow C: Deal Stage Progression Automation
Trigger: User says "My deal with [Company] moved to [stage]" or CRM stage change detected
When a deal moves stages, automatically trigger the appropriate next actions:
Stage: New Lead -> Qualified
var stageActions = {
"qualified": [
"Research prospect (call lead-enrichment-engine)",
"Draft intro email with personalized hooks",
"Send LinkedIn connection request",
"Create 'Schedule Demo' task in CRM"
]
}
Stage: Qualified -> Demo Scheduled
stageActions["demo_scheduled"] = [
"Create calendar event with meeting link",
"Send confirmation email with proposed agenda",
"Generate pre-demo brief (meeting-scheduler-followup)",
"Set reminder: send follow-up 2 hours after demo"
]
Stage: Demo -> Proposal Sent
stageActions["proposal_sent"] = [
"Draft proposal follow-up email (send 3 days after demo)",
"Create 'Check proposal status' task for day 5",
"Set follow-up reminder for day 7 if no response"
]
Stage: Proposal -> Negotiation
stageActions["negotiation"] = [
"Flag deal as high priority in tracker",
"Draft 'next steps' email with clear timeline",
"Schedule check-in call within 3 days",
"Notify user: 'Deal entering negotiation - personal attention recommended'"
]
Stage: Closed Won
stageActions["closed_won"] = [
"Send welcome/congratulations email",
"Create onboarding checklist task in CRM",
"Update pipeline tracker (won amount, close date)",
"Log win in activity tracker"
]
Stage: Closed Lost
stageActions["closed_lost"] = [
"Send graceful close email (door is always open)",
"Log loss reason in CRM and tracker",
"Set 90-day re-engagement reminder on calendar",
"Update pipeline tracker (lost, reason)"
]
Tracking Sheet Structure
When creating a new tracking sheet, use this structure:
Sheet 1: Pipeline
Columns: Date Added | Name | Company | Source | Email | LinkedIn URL |
Deal Stage | Deal Value | Touch 1 Date | Touch 1 Status | Touch 2 Date |
Touch 2 Status | Touch 3 Date | Touch 3 Status | Overall Status | Notes
Sheet 2: Activity Log
Columns: Date | Time | Action Type | Contact | Company | Deal |
Description | Status
Sheet 3: Weekly Summary
Columns: Week | New Leads | Demos | Proposals | Won | Lost |
Pipeline Total | Weighted Total | Notes
Cron Setup (Scheduled Daily Routine)
This workflow is ideal for a scheduled daily cron:
- Schedule: "0 8 * * 1-5" (Every weekday at 8am)
- Goal: "Run morning sales routine: scan CRM pipeline, check email replies,
prep for today's meetings, check LinkedIn feed for deal contacts,
generate action plan, and present for approval"
Error Handling
- CRM not accessible: Skip pipeline scan, proceed with email + calendar
- LinkedIn rate limited: Skip LinkedIn phase, note in action plan
- Gmail error: Log error, continue with other phases
- Any CAPTCHA: Stop entire workflow, report which phase completed
- Partial completion: Always save what's been done to activity log, even on error