@candoa/workflows
Version:
Type-safe workflow SDK for Candoa with Copilot-friendly syntax. Define chat workflows with triggers, actions, and type safety.
344 lines (289 loc) • 10.1 kB
text/typescript
// Complete integration examples for Candoa workflows
// These examples show how workflows integrate with existing systems:
// - Conversation management
// - Contact creation and updates
// - Automated handoff system
// - Project usage tracking
import {
workflow,
collectFirstName,
collectEmail,
saveToContact,
sendMessage,
handoffToHuman,
createTask,
addTags,
wait,
sendEmail,
conditional,
} from '@candoa/workflows'
// 🎯 INTELLIGENT HANDOFF WORKFLOW
// Integrates with your existing automated handoff system
export const intelligentHandoff = workflow('intelligent-handoff', {
description: 'Smart handoff based on conversation patterns and sentiment',
})
.on('sentiment.negative')
.use(
// First try to de-escalate
sendMessage({
message:
"I understand you're having some difficulties. Let me try to help resolve this for you.",
}),
// Give user one more chance with personalized help
conditional({
condition: '{{conversation_history_count}} > 5',
trueAction: handoffToHuman({
reason: 'Extended conversation with negative sentiment',
}),
falseAction: sendMessage({
message:
"Could you tell me more specifically what issue you're facing?",
}),
}),
// Create internal task for follow-up
createTask({
title: 'Review negative sentiment conversation: {{conversationId}}',
description: 'User expressed frustration - needs attention',
}),
// Tag for analytics
addTags({
tags: ['negative-sentiment', 'needs-review'],
target: 'conversation',
}),
)
// 🚀 COMPREHENSIVE ONBOARDING
// Uses your contact schema fields effectively
export const comprehensiveOnboarding = workflow('comprehensive-onboarding', {
description: 'Complete user onboarding with contact creation and follow-up',
})
.on('chat.started')
.use(
sendMessage({
message:
"Welcome! I'm Eli, your AI assistant. Let me get you set up quickly.",
}),
collectFirstName({
prompt: "What's your first name?",
errorMessage:
"I didn't catch that. Could you please tell me your first name?",
maxRetries: 2,
}),
// Save to contact with vector embeddings support
saveToContact({ field: 'firstName', value: '{{firstName}}' }),
sendMessage({
message: "Nice to meet you, {{firstName}}! What's your email address?",
}),
collectEmail({
prompt: 'Please provide your email address for updates and support.',
errorMessage: 'Please provide a valid email address.',
maxRetries: 3,
}),
saveToContact({ field: 'email', value: '{{email}}' }),
// Set last active timestamp
sendMessage({
message:
"Perfect! I've saved your information. How can I assist you today, {{firstName}}?",
}),
// Add to onboarded contacts for analytics
addTags({
tags: ['onboarded', 'new-user'],
target: 'contact',
}),
// Create follow-up task
createTask({
title: 'Welcome follow-up for {{firstName}}',
description: 'Send welcome materials and check in after 24 hours',
assignee: 'onboarding-team',
}),
)
// 💰 BILLING SUPPORT WORKFLOW
// Handles billing issues with proper escalation
export const billingSupport = workflow('billing-support', {
description: 'Handle billing inquiries with appropriate routing',
})
.on('intent.detected')
.use(
sendMessage({
message:
'I can help you with billing questions. Let me gather some information.',
}),
collectEmail({
prompt: 'What email address is associated with your account?',
}),
saveToContact({ field: 'email', value: '{{email}}' }),
// Always escalate billing to human for security
sendMessage({
message:
"For security reasons, I'll connect you with our billing specialist who can access your account safely.",
}),
handoffToHuman({
reason: 'Billing inquiry - requires account access',
}),
// Create billing task
createTask({
title: 'Billing inquiry from {{email}}',
description: 'Customer needs billing assistance - verify account access',
}),
addTags({
tags: ['billing', 'escalated'],
target: 'conversation',
}),
)
// 🔄 CONVERSATION RECOVERY
// Handles cases where AI becomes uncertain (integrates with your automated handoff)
export const conversationRecovery = workflow('conversation-recovery', {
description: 'Recover conversations when AI shows uncertainty',
})
.on('intent.detected') // When AI_UNCERTAINTY is detected
.use(
sendMessage({
message: 'Let me make sure I understand your question correctly.',
}),
// Try to collect more context
collectFirstName({
prompt: "First, what's your name so I can personalize my help?",
}),
saveToContact({ field: 'firstName', value: '{{firstName}}' }),
sendMessage({
message:
'Thanks {{firstName}}! Could you rephrase your question in a different way?',
}),
// Wait for user response, then check if we need human help
conditional({
condition: '{{user_questions_count}} >= 3',
trueAction: handoffToHuman({
reason: 'Multiple failed attempts to understand user question',
}),
falseAction: sendMessage({
message: "I'll do my best to help with that.",
}),
}),
addTags({
tags: ['ai-uncertainty', 'conversation-recovery'],
target: 'conversation',
}),
)
// 📊 LEAD QUALIFICATION
// Optimized for your contact schema with vector search support
export const leadQualification = workflow('lead-qualification', {
description: 'Qualify and enrich leads with contact data',
})
.on('message.received')
.use(
sendMessage({
message: "I'd love to learn more about how we can help you!",
}),
collectFirstName({
prompt: "What's your name?",
}),
collectEmail({
prompt: "What's your email address?",
}),
// Save all contact data
saveToContact({ field: 'firstName', value: '{{firstName}}' }),
saveToContact({ field: 'email', value: '{{email}}' }),
sendMessage({
message: "Thanks {{firstName}}! What's your company name?",
}),
saveToContact({ field: 'company', value: '{{company}}' }),
// Send personalized follow-up
sendMessage({
message:
"Great! I've noted that you're with {{company}}. Someone from our team will reach out to {{firstName}} at {{email}} within 24 hours.",
}),
// Create qualified lead task
createTask({
title: 'New qualified lead: {{firstName}} from {{company}}',
description: 'High-intent lead collected via chat - needs follow-up',
}),
// Send internal notification email
sendEmail({
to: 'sales@company.com',
subject: 'New Qualified Lead: {{firstName}} from {{company}}',
body: 'Lead Details:\nName: {{firstName}}\nEmail: {{email}}\nCompany: {{company}}\n\nPlease follow up within 24 hours.',
}),
addTags({
tags: ['qualified-lead', 'high-intent', 'needs-follow-up'],
target: 'contact',
}),
)
// 🎯 FEATURE REQUEST WORKFLOW
// Handles feature requests with proper categorization
export const featureRequest = workflow('feature-request', {
description: 'Collect and categorize feature requests',
})
.on('intent.detected')
.use(
sendMessage({
message: 'I love hearing feature ideas! Let me collect some details.',
}),
collectFirstName({
prompt: "What's your name?",
}),
collectEmail({
prompt: "What's your email so we can follow up?",
}),
saveToContact({ field: 'firstName', value: '{{firstName}}' }),
saveToContact({ field: 'email', value: '{{email}}' }),
sendMessage({
message:
"Thanks {{firstName}}! I've created a feature request and our product team will review it.",
}),
createTask({
title: 'Feature request from {{firstName}}',
description:
'Review and categorize feature request - respond to {{email}}',
assignee: 'product-team',
}),
addTags({
tags: ['feature-request', 'product-feedback'],
target: 'conversation',
}),
// Wait 1 week then send follow-up
wait({ duration: 168, unit: 'hours' }), // 7 days = 168 hours
sendEmail({
to: '{{email}}',
subject: 'Update on your feature request',
body: "Hi {{firstName}},\n\nThanks for your feature suggestion! Our product team has reviewed it and we'll keep you updated on our progress.\n\nBest regards,\nThe Product Team",
}),
)
// 💔 CHURN PREVENTION
// Handles users showing signs of leaving
export const churnPrevention = workflow('churn-prevention', {
description: 'Prevent churn with proactive engagement',
})
.on('intent.detected') // When "cancel" or "delete account" is detected
.use(
sendMessage({
message:
"I'd hate to see you go! Can you tell me what's not working for you?",
}),
collectFirstName({
prompt: "What's your name so I can help personally?",
}),
saveToContact({ field: 'firstName', value: '{{firstName}}' }),
sendMessage({
message:
'{{firstName}}, I want to make sure we address your concerns. Let me connect you with our customer success team.',
}),
// Always escalate churn risk to humans
handoffToHuman({
reason: 'Potential churn - user wants to cancel/delete account',
}),
createTask({
title: 'URGENT: Churn risk - {{firstName}}',
description:
'User indicated intent to cancel - immediate intervention needed',
assignee: 'customer-success',
}),
addTags({
tags: ['churn-risk', 'urgent', 'needs-intervention'],
target: 'contact',
}),
// Send internal alert
sendEmail({
to: 'customer-success@company.com',
subject: 'URGENT: Churn Risk Alert - {{firstName}}',
body: 'A user has indicated intent to cancel their account. Please intervene immediately.\n\nContact: {{firstName}}\nConversation ID: {{conversationId}}',
}),
)