diff --git a/.github/workflows/pr-review.yml b/.github/workflows/pr-review.yml index afe8d909..1b8f8d5d 100644 --- a/.github/workflows/pr-review.yml +++ b/.github/workflows/pr-review.yml @@ -4,17 +4,18 @@ on: pull_request: types: [opened, synchronize, reopened] paths: - - 'fern/**/*.mdx' - - 'fern/**/*.yml' - - 'fern/**/*.yaml' + - "fern/**/*.mdx" + - "fern/**/*.yml" + - "fern/**/*.yaml" jobs: review: runs-on: ubuntu-latest + if: false permissions: contents: read pull-requests: write - + steps: - uses: actions/checkout@v4 @@ -30,7 +31,7 @@ jobs: - name: ⚙️ Setup Node.js uses: actions/setup-node@v4 with: - node-version: '18' + node-version: "18" - name: 🤖 Install Claude Code run: npm install -g @anthropic-ai/claude-code @@ -44,7 +45,7 @@ jobs: echo "" >> review.md echo "Hey there! 👋 I've reviewed your documentation changes against our style guidelines. Here's what I found:" >> review.md echo "" >> review.md - + for file in ${{ steps.changed-files.outputs.all_changed_files }}; do echo "🔍 Reviewing $file..." @@ -137,7 +138,7 @@ jobs: echo "---" >> review.md echo "" >> review.md done - + echo "📖 [Style Guidelines](.cursorrules) | Thanks for contributing! 🙏✨" >> review.md - name: 💬 Comment on PR @@ -147,10 +148,10 @@ jobs: script: | const fs = require('fs'); const review = fs.readFileSync('review.md', 'utf8'); - + await github.rest.issues.createComment({ owner: context.repo.owner, repo: context.repo.repo, issue_number: context.issue.number, body: review - }); \ No newline at end of file + }); diff --git a/fern/docs.yml b/fern/docs.yml index f0e30cf6..6c465217 100644 --- a/fern/docs.yml +++ b/fern/docs.yml @@ -125,7 +125,7 @@ navigation: - section: Assistant customization contents: - - section: Conversation behaviour + - section: Conversation behavior icon: fa-light fa-comments contents: - page: Variables @@ -213,11 +213,10 @@ navigation: path: customization/custom-llm/tool-calling-integration.mdx - section: Workflows - icon: fa-light fa-diagram-project contents: - page: Quickstart path: workflows/quickstart.mdx - icon: fa-light fa-bolt-lightning + icon: fa-light fa-rocket - page: Overview path: workflows/overview.mdx icon: fa-light fa-eye @@ -227,15 +226,15 @@ navigation: - page: Appointment scheduling path: workflows/examples/appointment-scheduling.mdx icon: fa-light fa-calendar-check - - page: Outbound sales - path: workflows/examples/outbound-sales.mdx + - page: Lead qualification + path: workflows/examples/lead-qualification.mdx icon: fa-light fa-money-bill-wave - page: Medical triage path: workflows/examples/clinic-triage-scheduling.mdx icon: fa-light fa-stethoscope - page: Order management path: workflows/examples/ecommerce-order-management.mdx - icon: fa-light fa-shopping-cart + icon: fa-light fa-shopping-cart - section: Best practices contents: @@ -800,3 +799,5 @@ redirects: destination: /api-reference/assistants/create - source: /examples/voice-widget.mdx destination: /sdk/web + - source: /workflows/examples/outbound-sales.mdx + destination: /workflows/examples/lead-qualification.mdx diff --git a/fern/examples/voice-widget.mdx b/fern/examples/voice-widget.mdx index 12f51161..61c78b45 100644 --- a/fern/examples/voice-widget.mdx +++ b/fern/examples/voice-widget.mdx @@ -97,7 +97,7 @@ Improve your website's user interaction with the Vapi Voice Widget. This robust - You can use the `vapiInstance` returned from the run function in the snippet to further customize the behaviour. For instance, you might want to listen to various EventSource, or even send some messages to the bot programmatically. + You can use the `vapiInstance` returned from the run function in the snippet to further customize the behavior. For instance, you might want to listen to various EventSource, or even send some messages to the bot programmatically. ```js vapiInstance.on('speech-start', () => { diff --git a/fern/quickstart/dashboard.mdx b/fern/quickstart/dashboard.mdx index e48f875c..d705b83d 100644 --- a/fern/quickstart/dashboard.mdx +++ b/fern/quickstart/dashboard.mdx @@ -135,7 +135,7 @@ Vapi makes it easy to build end-to-end voice agents, which we call ***assistants When you click on the outbound call button, your assistant will make an outbound call to the phone number. Your assistant won't yet be able to hang-up the phone at the end of the call. - You will learn more about configuring call end behaviour in later guides. + You will learn more about configuring call end behavior in later guides. - \ No newline at end of file + diff --git a/fern/snippets/quickstart/dashboard/assistant-setup-inbound.mdx b/fern/snippets/quickstart/dashboard/assistant-setup-inbound.mdx index b444737a..9ba48581 100644 --- a/fern/snippets/quickstart/dashboard/assistant-setup-inbound.mdx +++ b/fern/snippets/quickstart/dashboard/assistant-setup-inbound.mdx @@ -93,7 +93,7 @@ spoken letter by letter "V. A. P. I." Some aspects of configuring your voice pipeline will require tweaks like this to get the target - behaviour you want. + behavior you want. @@ -102,7 +102,7 @@ We will now set the `System Prompt` for our assistant. If you're familiar with OpenAI's API, this is the first prompt in the message list that we feed our LLM (learn more about prompt engineering on the [OpenAI docs](https://platform.openai.com/docs/guides/prompt-engineering)). - The system prompt can be used to configure the context, role, personality, instructions and so on for the assistant. In our case, a system prompt like this will give us the behaviour we want: + The system prompt can be used to configure the context, role, personality, instructions and so on for the assistant. In our case, a system prompt like this will give us the behavior we want: ```text You are a voice assistant for Vappy’s Pizzeria, diff --git a/fern/static/images/workflows/examples/appointment-scheduling.png b/fern/static/images/workflows/examples/appointment-scheduling.png new file mode 100644 index 00000000..43c587b2 Binary files /dev/null and b/fern/static/images/workflows/examples/appointment-scheduling.png differ diff --git a/fern/static/images/workflows/examples/clinic-triage-scheduling.png b/fern/static/images/workflows/examples/clinic-triage-scheduling.png new file mode 100644 index 00000000..c9757649 Binary files /dev/null and b/fern/static/images/workflows/examples/clinic-triage-scheduling.png differ diff --git a/fern/static/images/workflows/examples/ecommerce-order-management.png b/fern/static/images/workflows/examples/ecommerce-order-management.png new file mode 100644 index 00000000..f34cdd5c Binary files /dev/null and b/fern/static/images/workflows/examples/ecommerce-order-management.png differ diff --git a/fern/static/images/workflows/examples/lead-qualification.png b/fern/static/images/workflows/examples/lead-qualification.png new file mode 100644 index 00000000..f34cdd5c Binary files /dev/null and b/fern/static/images/workflows/examples/lead-qualification.png differ diff --git a/fern/static/videos/inbound-support/create-assistant.mp4 b/fern/static/videos/inbound-support/create-assistant.mp4 index 5117d785..5ecac008 100644 Binary files a/fern/static/videos/inbound-support/create-assistant.mp4 and b/fern/static/videos/inbound-support/create-assistant.mp4 differ diff --git a/fern/static/videos/inbound-support/upload-files.mp4 b/fern/static/videos/inbound-support/upload-files.mp4 index bf1d43dd..cb5c0a90 100644 Binary files a/fern/static/videos/inbound-support/upload-files.mp4 and b/fern/static/videos/inbound-support/upload-files.mp4 differ diff --git a/fern/static/videos/upload-files.mp4 b/fern/static/videos/upload-files.mp4 index bf1d43dd..cb5c0a90 100644 Binary files a/fern/static/videos/upload-files.mp4 and b/fern/static/videos/upload-files.mp4 differ diff --git a/fern/static/videos/workflows/create-workflow.mp4 b/fern/static/videos/workflows/create-workflow.mp4 index 21fc7045..b8146c1e 100644 Binary files a/fern/static/videos/workflows/create-workflow.mp4 and b/fern/static/videos/workflows/create-workflow.mp4 differ diff --git a/fern/workflows/examples/appointment-scheduling.mdx b/fern/workflows/examples/appointment-scheduling.mdx index 2b159bd1..b400f898 100644 --- a/fern/workflows/examples/appointment-scheduling.mdx +++ b/fern/workflows/examples/appointment-scheduling.mdx @@ -88,13 +88,11 @@ You'll start with a default template that includes a "Call Start" node. We'll mo The default template includes a conversation node. Click on it and configure: - **First Message**: - ```txt + ```txt title="First Message" Hello! Thank you for calling Tony's Barbershop. This is Sarah, your booking assistant. I can help you schedule, reschedule, or cancel appointments. How can I help you today? ``` - **Prompt**: - ```txt + ```txt title="Prompt" You are Sarah, the friendly booking assistant for Tony's Barbershop. Listen to the customer's response and determine their intent: @@ -117,18 +115,27 @@ You'll start with a default template that includes a "Call Start" node. We'll mo Click the + button below the greeting node and add a new **Conversation** node: - **Prompt**: - ```txt + ```txt title="Condition" + Intent identified + ``` + + ```txt title="First Message" Now I need to verify your information. Can you please provide your phone number or full name so I can look up your account? + ``` + + ```txt title="Prompt" + You are collecting customer identification information to look them up in the system. - If they provide a phone number, extract it. If they provide a name, extract it. - Be friendly and reassuring about privacy. + If they provide a phone number, extract it in a clean format (numbers only). + If they provide a name, extract their full name. + Be friendly and reassuring about privacy. Keep responses under 25 words. ``` **Extract Variables**: - Variable: `phone_number` - Type: `String` - Description: `Customer's phone number if provided` +
- Variable: `customer_name` - Type: `String` - Description: `Customer's full name if provided` @@ -137,6 +144,10 @@ You'll start with a default template that includes a "Call Start" node. We'll mo Add a **Tool** node: + ```txt title="Condition" + Customer information collected + ``` + **Select Tool**: Choose your pre-configured customer lookup tool from the dropdown. This tool will use the extracted `phone_number` and `customer_name` variables to find the customer in your database. @@ -144,29 +155,56 @@ You'll start with a default template that includes a "Call Start" node. We'll mo Create branching paths based on the customer's intent. Add multiple conversation nodes: **Schedule New Appointment Node**: - - **Prompt**: `Great! I can help you schedule a new appointment. What type of service would you like? We offer haircuts, beard trims, shampoo and styling, and full grooming packages.` + + ```txt title="Condition" + Customer verified and intent is schedule + ``` + + ```txt title="First Message" + Great! I can help you schedule a new appointment. What type of service would you like? We offer haircuts, beard trims, shampoo and styling, and full grooming packages. + ``` + + ```txt title="Prompt" + You are helping the customer schedule a new appointment. + + Listen for the service they want and any preferred dates/times they mention. + Be enthusiastic and helpful. Keep responses under 30 words. + If they're unsure about services, briefly describe each option. + ``` **Reschedule Appointment Node**: - - **Prompt**: `I can help you reschedule your appointment. Let me first look up your current booking details.` + + ```txt title="Condition" + Customer verified and intent is reschedule + ``` + + ```txt title="First Message" + I can help you reschedule your appointment. Let me first look up your current booking details. + ``` + + ```txt title="Prompt" + You are helping the customer reschedule an existing appointment. + + Be understanding and accommodating. Look up their current appointment first. + Keep responses under 25 words while being empathetic. + ``` **Cancel Appointment Node**: - - **Prompt**: `I can help you cancel your appointment. Let me look up your current booking to confirm the details.` -
- - - Connect the nodes with conditional edges: - - **To Schedule Appointment Node**: - - Condition: `if the user said yes` (AI condition) - - Alternative: `{{ intent == "schedule" }}` (Logic condition) - - **To Reschedule Appointment Node**: - - Condition: `if the user said yes` (AI condition) - - Alternative: `{{ intent == "reschedule" }}` (Logic condition) - - **To Cancel Appointment Node**: - - Condition: `if the user said yes` (AI condition) - - Alternative: `{{ intent == "cancel" }}` (Logic condition) + + ```txt title="Condition" + Customer verified and intent is cancel + ``` + + ```txt title="First Message" + I can help you cancel your appointment. Let me look up your current booking to confirm the details. + ``` + + ```txt title="Prompt" + You are helping the customer cancel their appointment. + + Be understanding and offer to reschedule instead if appropriate. + Confirm cancellation details before proceeding. Keep responses under 25 words. + ``` @@ -174,11 +212,21 @@ You'll start with a default template that includes a "Call Start" node. We'll mo **Enable Global Node**: Toggle this on to make the node available from any point in the conversation - **Prompt**: - ```txt + ```txt title="Condition" + Customer confused or error detected + ``` + + ```txt title="First Message" I apologize for any confusion. Let me transfer you to one of our human staff members who can better assist you. Please hold for just a moment. ``` + ```txt title="Prompt" + You are handling an error or confused customer situation. + + Be apologetic and professional. Prepare them for transfer to human staff. + Keep the message brief and reassuring. + ``` + This global node will activate whenever there's an error or the customer becomes frustrated, regardless of where they are in the workflow. @@ -186,42 +234,141 @@ You'll start with a default template that includes a "Call Start" node. We'll mo For the schedule appointment flow, add these nodes: **Service Selection Node** (Conversation): - - **Prompt**: `What type of service would you like to book? Also, do you have a preferred date and time?` - - **Extract Variables**: `service_type`, `preferred_date`, `preferred_time` + + ```txt title="Condition" + Service type mentioned or requested + ``` + + ```txt title="First Message" + Perfect! And when would you prefer to come in? What date and time work best for you? + ``` + + ```txt title="Prompt" + You are collecting appointment preferences for scheduling. + + Listen for specific dates, times, or general preferences like "morning" or "next week". + Be flexible and offer to check availability. Keep responses under 25 words. + ``` + + **Extract Variables**: + - Variable: `service_type` + - Type: `String` + - Description: `Type of service requested` +
+ - Variable: `preferred_date` + - Type: `String` + - Description: `Customer's preferred date` +
+ - Variable: `preferred_time` + - Type: `String` + - Description: `Customer's preferred time` **Availability Check Tool Node**: - - **Select Tool**: Choose "Check Availability" from the pre-defined calendar tools + + ```txt title="Condition" + Preferences collected + ``` + + **Select Tool**: Choose "Check Availability" from the pre-defined calendar tools - This will automatically check available slots based on the extracted preferences **Availability Results Node** (Conversation): - - **Prompt**: `Based on your preferences, here are the available time slots. Which one works best for you?` - - Use conditional logic to offer alternatives if preferred time unavailable + + ```txt title="Condition" + Availability checked + ``` + + ```txt title="First Message" + Based on your preferences, here are the available time slots. Which one works best for you? + ``` + + ```txt title="Prompt" + You are presenting available appointment times to the customer. + + Present 2-3 options clearly with dates and times. + If their preferred time isn't available, offer the closest alternatives. + Be helpful and accommodating. Keep responses under 35 words. + ```
**Booking Confirmation Node** (Conversation): - - **Prompt**: `Perfect! Let me confirm your appointment details: [service] on [date] at [time]. Is this correct?` - - **Extract Variables**: `confirmation_status` + + ```txt title="Condition" + Time slot selected + ``` + + ```txt title="First Message" + Perfect! Let me confirm your appointment details: [service] on [date] at [time]. Is this correct? + ``` + + ```txt title="Prompt" + You are confirming appointment details before booking. + + Read back the service type, date, and time clearly. + Wait for their confirmation before proceeding. + Be thorough but concise. Keep responses under 30 words. + ``` + + **Extract Variables**: + - Variable: `confirmation_status` + - Type: `String` + - Description: `Whether customer confirms the appointment details` **Create Appointment Tool Node**: - - **Select Tool**: Choose "Schedule Event" from the pre-defined calendar tools + + ```txt title="Condition" + Appointment details confirmed + ``` + + **Select Tool**: Choose "Schedule Event" from the pre-defined calendar tools - This will book the appointment in your calendar system **Send Confirmation Node** (Tool): - - **Select Tool**: Choose your pre-configured SMS/email confirmation tool + + ```txt title="Condition" + Appointment created successfully + ``` + + **Select Tool**: Choose your pre-configured SMS/email confirmation tool **Completion Node** (Conversation): - - **Prompt**: `Great! Your appointment is confirmed. You'll receive a confirmation message shortly. Is there anything else I can help you with today?` + + ```txt title="Condition" + Confirmation sent + ``` + + ```txt title="First Message" + Great! Your appointment is confirmed. You'll receive a confirmation message shortly. Is there anything else I can help you with today? + ``` + + ```txt title="Prompt" + You are wrapping up a successful appointment booking. + + Be friendly and offer additional assistance. + If they say no, prepare to end the call politely. + Keep responses under 25 words. + ``` **Transfer to Human Node**: - - **Node Type**: `Transfer Call` - - **Phone to transfer to**: `+1-555-BARBER-1` (your barbershop number) + + ```txt title="Condition" + Customer requests human assistance + ``` + + **Node Type**: `Transfer Call` + **Phone to transfer to**: `+1-555-BARBER-1` (your barbershop number) **End Call Node**: - - **Node Type**: `End Call` - - **First Message**: `Thank you for calling Tony's Barbershop. Have a great day!` + + ```txt title="Condition" + Customer satisfied and no further assistance needed + ``` + + **Node Type**: `End Call` + **First Message**: `Thank you for calling Tony's Barbershop. Have a great day!` - Use when customer is satisfied and no further assistance needed @@ -255,6 +402,12 @@ You'll start with a default template that includes a "Call Start" node. We'll mo +## Final Workflow + + + Barbershop appointment scheduling workflow showing conversation nodes, tool integrations, and conditional routing + + ## Next Steps Just like that, you've built an automated appointment scheduling workflow that can handle inbound calls, manage bookings, and provide 24/7 availability for your barbershop. diff --git a/fern/workflows/examples/clinic-triage-scheduling.mdx b/fern/workflows/examples/clinic-triage-scheduling.mdx index 5d3f972e..846813b0 100644 --- a/fern/workflows/examples/clinic-triage-scheduling.mdx +++ b/fern/workflows/examples/clinic-triage-scheduling.mdx @@ -144,13 +144,11 @@ You'll start with a default template that includes a "Call Start" node. We'll mo The default template includes a conversation node. Click on it and configure: - **First Message**: - ```txt + ```txt title="First Message" Hello, you've reached Riverside Family Clinic. This is Nurse Kelly, your medical assistant. I can help you schedule appointments, assess your symptoms, or direct you to appropriate care. How may I assist you today? ``` - **Prompt**: - ```txt + ```txt title="Prompt" You are Nurse Kelly, a licensed medical assistant for Riverside Family Clinic. Listen to the patient's response and determine their primary need: @@ -160,7 +158,7 @@ You'll start with a default template that includes a "Call Start" node. We'll mo - "emergency" for urgent medical situations - "general" for other inquiries - Keep responses professional and under 30 words. + Keep responses professional and under 30 words. Always prioritize patient safety. ``` **Extract Variables**: @@ -173,13 +171,22 @@ You'll start with a default template that includes a "Call Start" node. We'll mo Add a **Conversation** node: + ```txt title="Condition" + Patient purpose identified + ``` + **Node Name**: `patient_identification` - **Prompt**: - ```txt + ```txt title="First Message" I'll need to verify your information first. Can you please provide your full name and phone number so I can look up your patient record? - - If this is for someone else, please let me know your relationship to the patient. + ``` + + ```txt title="Prompt" + You are collecting patient identification for medical record lookup. + + Be professional and reassuring about privacy. Extract their full name and phone number clearly. + If calling for someone else, get the relationship to the patient. + Keep responses under 25 words and maintain medical professionalism. ``` **Variable Extraction**: @@ -187,10 +194,12 @@ You'll start with a default template that includes a "Call Start" node. We'll mo - Type: `string` - Description: `Patient's full name` - Required: `true` +
- Variable: `phone_number` - Type: `string` - Description: `Patient's phone number` - Required: `true` +
- Variable: `caller_relationship` - Type: `string` - Description: `Relationship to patient if calling for someone else` @@ -200,6 +209,10 @@ You'll start with a default template that includes a "Call Start" node. We'll mo Add a **Tool** node: + ```txt title="Condition" + Patient information collected + ``` + **Tool**: Select your pre-configured "Patient Lookup" tool from the dropdown. This tool should be created in the **Tools** section of your dashboard with: - **Function Name**: `lookup_patient` - **Description**: "Look up patient record by ID" @@ -212,50 +225,124 @@ You'll start with a default template that includes a "Call Start" node. We'll mo Create branching paths based on the patient's needs. Add multiple conversation nodes: **Medical Triage Node**: - - **Node Name**: `medical_triage_assessment` - - **Prompt**: `I understand you're having some medical concerns. Let me ask you some questions to better assess your situation. What symptoms are you experiencing, and when did they start?` + + ```txt title="Condition" + Patient verified and purpose is symptoms + ``` + + **Node Name**: `medical_triage_assessment` + + ```txt title="First Message" + I understand you're having some medical concerns. Let me ask you some questions to better assess your situation. What symptoms are you experiencing, and when did they start? + ``` + + ```txt title="Prompt" + You are conducting a medical triage assessment following clinical protocols. + + Ask about symptoms, onset, severity, and any concerning signs. + Be thorough but compassionate. Look for emergency red flags. + Keep responses under 35 words while gathering critical information. + ``` **Routine Appointment Node**: - - **Node Name**: `routine_appointment_scheduling` - - **Prompt**: `I can help you schedule an appointment. What type of visit do you need - routine check-up, follow-up, or something specific?` + + ```txt title="Condition" + Patient verified and purpose is appointment + ``` + + **Node Name**: `routine_appointment_scheduling` + + ```txt title="First Message" + I can help you schedule an appointment. What type of visit do you need - routine check-up, follow-up, or something specific? + ``` + + ```txt title="Prompt" + You are helping schedule a routine medical appointment. + + Determine the type of visit needed and any provider preferences. + Be efficient while ensuring they get appropriate care scheduling. + Keep responses under 30 words. + ``` **Prescription Refill Node**: - - **Node Name**: `prescription_refill_request` - - **Prompt**: `I can help with your prescription refill. Which medication do you need refilled, and what's the name of the prescribing provider?` + + ```txt title="Condition" + Patient verified and purpose is prescription + ``` + + **Node Name**: `prescription_refill_request` + + ```txt title="First Message" + I can help with your prescription refill. Which medication do you need refilled, and what's the name of the prescribing provider? + ``` + + ```txt title="Prompt" + You are processing a prescription refill request. + + Get the exact medication name, dosage, and prescribing provider. + Follow pharmacy safety protocols. Keep responses under 25 words. + ``` **Emergency Assessment Node**: - - **Node Name**: `emergency_assessment` - - **Prompt**: `I understand this may be urgent. Can you describe what's happening right now? Are you experiencing any chest pain, difficulty breathing, or severe bleeding?` + + ```txt title="Condition" + Patient verified and purpose is emergency + ``` + + **Node Name**: `emergency_assessment` + + ```txt title="First Message" + I understand this may be urgent. Can you describe what's happening right now? Are you experiencing any chest pain, difficulty breathing, or severe bleeding? + ``` + + ```txt title="Prompt" + You are assessing a potential medical emergency. + + Ask direct questions about life-threatening symptoms. + Be calm but urgent. Prepare for immediate 911 routing if needed. + Keep responses under 30 words and prioritize safety. + ``` Connect the nodes with conditions for the LLM to interpret: - **From greeting_and_purpose to medical_triage_assessment**: - - Condition: `{{ call_purpose == "symptoms" }}` + **To Medical Triage Node**: + - Condition: `Patient verified and purpose is symptoms` - **From greeting_and_purpose to routine_appointment_scheduling**: - - Condition: `{{ call_purpose == "appointment" }}` + **To Routine Appointment Node**: + - Condition: `Patient verified and purpose is appointment` - **From greeting_and_purpose to prescription_refill_request**: - - Condition: `{{ call_purpose == "prescription" }}` + **To Prescription Refill Node**: + - Condition: `Patient verified and purpose is prescription` - **From greeting_and_purpose to emergency_assessment**: - - Condition: `{{ call_purpose == "emergency" }}` + **To Emergency Assessment Node**: + - Condition: `Patient verified and purpose is emergency` Create a global node that monitors for emergency keywords throughout the call: + ```txt title="Condition" + Emergency keywords detected or life-threatening symptoms mentioned + ``` + **Node Name**: `emergency_detector` **Global Node**: `enabled = true` **Enter Condition**: `{{ emergency_keywords_detected == true or red_flag_symptoms == true }}` - **Prompt**: - ```txt + ```txt title="First Message" I'm hearing some concerning symptoms. For your safety, I need to direct you to immediate medical care. Please call 911 or go to your nearest emergency room right away. Do not drive yourself - have someone else drive you or call an ambulance. ``` + ```txt title="Prompt" + You are handling a medical emergency situation. + + Direct them to emergency services immediately. Be clear and calm. + Do not provide medical advice beyond directing to emergency care. + Keep the message brief but urgent. + ``` + This global node will activate whenever emergency keywords are detected, regardless of where they are in the workflow. @@ -263,48 +350,159 @@ You'll start with a default template that includes a "Call Start" node. We'll mo For the medical triage path, add these nodes: **Symptom Collection Node**: - - **Node Name**: `collect_symptoms` - - Extract detailed symptom information, onset, severity + + ```txt title="Condition" + Initial symptoms described + ``` + + **Node Name**: `collect_symptoms` + + ```txt title="First Message" + Thank you for that information. On a scale of 1 to 10, how would you rate your pain or discomfort? And have you tried anything to help with these symptoms? + ``` + + ```txt title="Prompt" + You are collecting detailed symptom information for medical triage. + + Get pain scale, duration, what makes it better/worse, and any self-treatment. + Follow medical assessment protocols. Keep responses under 30 words. + ``` + + **Extract Variables**: + - Variable: `symptom_details` + - Type: `String` + - Description: `Detailed symptom description` +
+ - Variable: `pain_scale` + - Type: `String` + - Description: `Pain level 1-10` +
+ - Variable: `symptom_duration` + - Type: `String` + - Description: `How long symptoms have been present` **Triage Protocol Tool Node**: + + ```txt title="Condition" + Comprehensive symptoms collected + ``` + - Add a **Tool** node that calls triage protocol API with symptom data **Urgency Classification Node**: - - **Node Name**: `classify_urgency` + + ```txt title="Condition" + Triage assessment completed + ``` + + **Node Name**: `classify_urgency` + + ```txt title="First Message" + Based on your symptoms, I'm going to classify this as [urgency level] and connect you with the appropriate care level. + ``` + + ```txt title="Prompt" + You are communicating the triage classification results to the patient. + + Explain the urgency level and next steps clearly. + Be reassuring while maintaining clinical accuracy. + Keep responses under 35 words. + ``` + - Determine urgency level: emergency, urgent, semi-urgent, routine - Route to appropriate care level
**Provider Lookup Tool Node**: + + ```txt title="Condition" + Urgency level determined and provider needed + ``` + - Add a **Tool** node that checks available appointments based on urgency and specialty **Appointment Options Node**: - - **Node Name**: `present_appointment_options` + + ```txt title="Condition" + Provider availability checked + ``` + + **Node Name**: `present_appointment_options` + + ```txt title="First Message" + Based on your needs, I have these available appointment times with Dr. [Provider Name]. Which option works best for your schedule? + ``` + + ```txt title="Prompt" + You are presenting available medical appointments to the patient. + + Present 2-3 time options clearly with provider names. + Consider urgency when offering times. Keep responses under 35 words. + ``` + - Present available time slots to patient - Use conditional logic based on urgency level **Appointment Confirmation Node**: - - **Node Name**: `confirm_appointment` + + ```txt title="Condition" + Appointment time selected + ``` + + **Node Name**: `confirm_appointment` + + ```txt title="First Message" + Perfect! Let me confirm your appointment with Dr. [Provider] on [date] at [time]. Please arrive 15 minutes early for check-in. + ``` + + ```txt title="Prompt" + You are confirming medical appointment details. + + Confirm provider, date, time, and location. + Provide pre-appointment instructions if needed. + Keep responses under 30 words. + ``` + - Confirm appointment details and provide instructions **911 Routing Node**: - - **Node Type**: `Transfer` - - **Destination**: `911` + + ```txt title="Condition" + Life-threatening emergency detected + ``` + + **Node Type**: `Transfer` + **Destination**: `911` - Use for life-threatening emergencies **Urgent Care Transfer Node**: - - **Node Type**: `Transfer` - - **Destination**: `+1-555-URGENT-1` (urgent care line) + + ```txt title="Condition" + Urgent but not life-threatening situation + ``` + + **Node Type**: `Transfer` + **Destination**: `+1-555-URGENT-1` (urgent care line) **Nurse Line Transfer Node**: - - **Node Type**: `Transfer` - - **Destination**: `+1-555-NURSE-1` (triage nurse line) + + ```txt title="Condition" + Clinical consultation needed + ``` + + **Node Type**: `Transfer` + **Destination**: `+1-555-NURSE-1` (triage nurse line) **End Call Node**: - - **Node Type**: `Hangup` + + ```txt title="Condition" + Patient needs resolved or transferred appropriately + ``` + + **Node Type**: `Hangup` - Use when patient needs are resolved @@ -340,6 +538,12 @@ You'll start with a default template that includes a "Call Start" node. We'll mo
+## Final Workflow + + + Clinic triage workflow showing patient verification, medical assessment nodes, emergency routing, and appointment scheduling + + ## Integrating with Real Systems This example uses JSONPlaceholder for demonstration purposes. To integrate with your actual healthcare systems: diff --git a/fern/workflows/examples/ecommerce-order-management.mdx b/fern/workflows/examples/ecommerce-order-management.mdx index f2b94079..92106f82 100644 --- a/fern/workflows/examples/ecommerce-order-management.mdx +++ b/fern/workflows/examples/ecommerce-order-management.mdx @@ -143,12 +143,13 @@ You'll start with a default template that includes a "Call Start" node. We'll mo **Node Name**: `greeting_and_inquiry_type` - **Prompt**: - ```txt + ```txt title="First Message" + Hello! Thank you for calling TechGear Online customer service. This is Emma, your virtual assistant. I can help you track orders, process returns, answer product questions, or resolve any issues. How can I assist you today? + ``` + + ```txt title="Prompt" You are Emma, the friendly customer service representative for TechGear Online. - Start with: "Hello! Thank you for calling TechGear Online customer service. This is Emma, your virtual assistant. I can help you track orders, process returns, answer product questions, or resolve any issues. How can I assist you today?" - Listen to the customer's response and determine their inquiry type: - "order_tracking" for checking order status or shipping - "return_exchange" for returns, exchanges, or refunds @@ -157,7 +158,7 @@ You'll start with a default template that includes a "Call Start" node. We'll mo - "complaint" for problems or complaints - "general" for other inquiries - Keep responses friendly and under 35 words. + Keep responses friendly and under 35 words. Be helpful and professional. ``` **Extract Variables**: @@ -170,13 +171,22 @@ You'll start with a default template that includes a "Call Start" node. We'll mo Add a **Conversation** node: + ```txt title="Condition" + Inquiry type identified + ``` + **Node Name**: `customer_identification` - **Prompt**: - ```txt + ```txt title="First Message" I'll be happy to help you with that. To look up your account, can you please provide your phone number or email address associated with your TechGear Online account? + ``` + + ```txt title="Prompt" + You are collecting customer information to look up their account. If you don't have an account, that's okay - I can still help you with general product questions. + Be patient and helpful. Extract phone number or email clearly. + Keep responses under 25 words. ``` **Variable Extraction**: @@ -184,6 +194,7 @@ You'll start with a default template that includes a "Call Start" node. We'll mo - Type: `string` - Description: `Customer's phone number` - Required: `false` +
- Variable: `customer_email` - Type: `string` - Description: `Customer's email address` @@ -193,6 +204,10 @@ You'll start with a default template that includes a "Call Start" node. We'll mo Add a **Tool** node: + ```txt title="Condition" + Customer information provided + ``` + **Tool**: Select your pre-configured "Customer Lookup" tool from the dropdown. This tool should be created in the **Tools** section of your dashboard with: - **Function Name**: `lookup_customer` - **Description**: "Look up customer account and order history" @@ -205,57 +220,148 @@ You'll start with a default template that includes a "Call Start" node. We'll mo Create branching paths based on the customer's inquiry type. Add multiple conversation nodes: **Order Tracking Node**: - - **Node Name**: `order_tracking_flow` - - **Prompt**: `I can help you track your order. Do you have your order number, or would you like me to look up your recent orders?` + + ```txt title="Condition" + Customer verified and inquiry is order tracking + ``` + + **Node Name**: `order_tracking_flow` + + ```txt title="First Message" + I can help you track your order. Do you have your order number, or would you like me to look up your recent orders? + ``` + + ```txt title="Prompt" + You are helping the customer track their order. + + Be proactive in finding their order information. + If they don't have the order number, offer to look up recent orders. + Keep responses under 30 words. + ``` **Return/Exchange Node**: - - **Node Name**: `return_exchange_flow` - - **Prompt**: `I can help you with returns and exchanges. Can you tell me which item you'd like to return and the reason for the return?` + + ```txt title="Condition" + Customer verified and inquiry is return or exchange + ``` + + **Node Name**: `return_exchange_flow` + + ```txt title="First Message" + I can help you with returns and exchanges. Can you tell me which item you'd like to return and the reason for the return? + ``` + + ```txt title="Prompt" + You are helping the customer with a return or exchange. + + Get the specific item and reason for return clearly. + Be understanding and helpful about their concerns. + Keep responses under 30 words. + ``` **Product Inquiry Node**: - - **Node Name**: `product_inquiry_flow` - - **Prompt**: `I'd be happy to help with product information. What specific product are you interested in, or what type of device are you looking for?` + + ```txt title="Condition" + Customer verified and inquiry is product related + ``` + + **Node Name**: `product_inquiry_flow` + + ```txt title="First Message" + I'd be happy to help with product information. What specific product are you interested in, or what type of device are you looking for? + ``` + + ```txt title="Prompt" + You are helping the customer with product information and recommendations. + + Be knowledgeable about TechGear products and helpful in making recommendations. + Ask clarifying questions to better assist them. + Keep responses under 35 words. + ``` **Billing/Payment Node**: - - **Node Name**: `billing_payment_flow` - - **Prompt**: `I can help with billing and payment questions. Are you looking to update payment information, dispute a charge, or have questions about a specific order?` + + ```txt title="Condition" + Customer verified and inquiry is billing or payment + ``` + + **Node Name**: `billing_payment_flow` + + ```txt title="First Message" + I can help with billing and payment questions. Are you looking to update payment information, dispute a charge, or have questions about a specific order? + ``` + + ```txt title="Prompt" + You are helping the customer with billing and payment issues. + + Be careful with sensitive financial information. + Determine the specific billing concern clearly. + Keep responses under 30 words. + ``` **Complaint Resolution Node**: - - **Node Name**: `complaint_resolution_flow` - - **Prompt**: `I'm sorry to hear you're having an issue. I want to make this right for you. Can you tell me what happened so I can help resolve this?` + + ```txt title="Condition" + Customer verified and inquiry is a complaint + ``` + + **Node Name**: `complaint_resolution_flow` + + ```txt title="First Message" + I'm sorry to hear you're having an issue. I want to make this right for you. Can you tell me what happened so I can help resolve this? + ``` + + ```txt title="Prompt" + You are handling a customer complaint and working toward resolution. + + Be empathetic and solution-focused. Listen carefully to their concern. + Show that you care about resolving their issue. + Keep responses under 35 words. + ``` Connect the nodes with conditions for the LLM to interpret: - **From greeting_and_inquiry_type to order_tracking_flow**: - - Condition: `{{ inquiry_type == "order_tracking" }}` + **To Order Tracking Node**: + - Condition: `Customer verified and inquiry is order tracking` - **From greeting_and_inquiry_type to return_exchange_flow**: - - Condition: `{{ inquiry_type == "return_exchange" }}` + **To Return/Exchange Node**: + - Condition: `Customer verified and inquiry is return or exchange` - **From greeting_and_inquiry_type to product_inquiry_flow**: - - Condition: `{{ inquiry_type == "product_inquiry" }}` + **To Product Inquiry Node**: + - Condition: `Customer verified and inquiry is product related` - **From greeting_and_inquiry_type to billing_payment_flow**: - - Condition: `{{ inquiry_type == "billing_payment" }}` + **To Billing/Payment Node**: + - Condition: `Customer verified and inquiry is billing or payment` - **From greeting_and_inquiry_type to complaint_resolution_flow**: - - Condition: `{{ inquiry_type == "complaint" }}` + **To Complaint Resolution Node**: + - Condition: `Customer verified and inquiry is a complaint` Create a global node that provides special handling for VIP customers: + ```txt title="Condition" + VIP customer detected + ``` + **Node Name**: `vip_customer_handler` **Global Node**: `enabled = true` **Enter Condition**: `{{ customer_tier == "VIP" or total_orders > 50 or lifetime_value > 5000 }}` - **Prompt**: - ```txt + ```txt title="First Message" I see you're one of our valued VIP customers. I want to make sure you receive our highest level of service today. Let me prioritize your request and see what I can do to exceed your expectations. ``` + ```txt title="Prompt" + You are providing VIP-level customer service to a high-value customer. + + Be extra attentive and go above and beyond normal service. + Offer premium solutions and expedited handling. + Keep responses under 35 words but show special attention. + ``` + This global node will activate for high-value customers, regardless of their inquiry type. @@ -263,41 +369,156 @@ You'll start with a default template that includes a "Call Start" node. We'll mo For the order tracking path, add these nodes: **Order Number Collection Node**: - - **Node Name**: `collect_order_number` - - Extract order number or use recent orders from customer history + + ```txt title="Condition" + Order tracking requested + ``` + + **Node Name**: `collect_order_number` + + ```txt title="First Message" + I can look that up for you. What's your order number? It usually starts with TG followed by numbers. + ``` + + ```txt title="Prompt" + You are collecting the customer's order number for tracking. + + If they don't have it, offer to look up recent orders by date. + Be patient and helpful in locating their order. + Keep responses under 25 words. + ``` + + **Extract Variables**: + - Variable: `order_number` + - Type: `String` + - Description: `Customer's order number` **Order Status Tool Node**: + + ```txt title="Condition" + Order number provided + ``` + - Add a **Tool** node that calls your order tracking API with order information **Shipping Information Node**: - - **Node Name**: `provide_shipping_info` + + ```txt title="Condition" + Order status retrieved + ``` + + **Node Name**: `provide_shipping_info` + + ```txt title="First Message" + Great news! Your order is [status] and should arrive [delivery date]. Here's your tracking number: [tracking]. Is there anything else about this order? + ``` + + ```txt title="Prompt" + You are providing order status and shipping information to the customer. + + Give clear updates on order status, tracking, and delivery estimates. + Be positive and informative. Keep responses under 35 words. + ``` + - Present tracking details, delivery estimates, and shipping updates
**Return Eligibility Check Node**: - - **Node Name**: `check_return_eligibility` - - Verify return policy compliance and item condition + + ```txt title="Condition" + Return request initiated + ``` + + **Node Name**: `check_return_eligibility` + + ```txt title="First Message" + Let me check if this item is eligible for return. What's the reason for the return - defective, wrong item, or just not what you expected? + ``` + + ```txt title="Prompt" + You are checking return eligibility and gathering return details. + + Verify return policy compliance and item condition. + Be understanding about their return reason. + Keep responses under 30 words. + ``` + + **Extract Variables**: + - Variable: `return_reason` + - Type: `String` + - Description: `Reason for return` **Return Authorization Tool Node**: + + ```txt title="Condition" + Return eligibility confirmed + ``` + - Add a **Tool** node that creates return label and authorization number **Refund Processing Node**: - - **Node Name**: `process_refund` + + ```txt title="Condition" + Return authorized + ``` + + **Node Name**: `process_refund` + + ```txt title="First Message" + Perfect! I've processed your return authorization. You'll receive a return label via email, and your refund will be processed within 3-5 business days once we receive the item. + ``` + + ```txt title="Prompt" + You are confirming the return process and refund timeline. + + Provide clear instructions for returning the item. + Set proper expectations for refund timing. + Keep responses under 35 words. + ``` + - Handle refund calculations and payment processing **Human Agent Transfer Node**: - - **Node Type**: `Transfer` - - **Destination**: `+1-555-SUPPORT` (customer service team) + + ```txt title="Condition" + Customer requests human agent or complex issue + ``` + + **Node Type**: `Transfer` + **Destination**: `+1-555-SUPPORT` (customer service team) **Issue Resolution Node**: - - **Node Name**: `resolve_issue` + + ```txt title="Condition" + Resolution offered or compensation provided + ``` + + **Node Name**: `resolve_issue` + + ```txt title="First Message" + I want to make this right for you. Let me offer you [solution/compensation] for the trouble you've experienced. + ``` + + ```txt title="Prompt" + You are providing a resolution or compensation for the customer's issue. + + Be generous and solution-focused. Make the customer feel valued. + Offer specific solutions or compensation when appropriate. + Keep responses under 30 words. + ``` + - Provide solutions, credits, or compensations **End Call Node**: - - **Node Type**: `Hangup` + + ```txt title="Condition" + Customer issue resolved and satisfied + ``` + + **Node Type**: `Hangup` - Use when customer issue is resolved @@ -333,6 +554,12 @@ You'll start with a default template that includes a "Call Start" node. We'll mo +## Final Workflow + + + E-commerce support workflow showing customer identification, inquiry routing, order tracking, and return processing flows + + ## Integrating with Real Systems This example uses JSONPlaceholder for demonstration purposes. To integrate with your actual e-commerce systems: diff --git a/fern/workflows/examples/outbound-sales.mdx b/fern/workflows/examples/lead-qualification.mdx similarity index 53% rename from fern/workflows/examples/outbound-sales.mdx rename to fern/workflows/examples/lead-qualification.mdx index 08a1e792..6ed4ea4f 100644 --- a/fern/workflows/examples/outbound-sales.mdx +++ b/fern/workflows/examples/lead-qualification.mdx @@ -1,7 +1,7 @@ --- -title: Outbound sales workflow +title: Lead qualification workflow subtitle: Build an AI sales workflow that qualifies leads and schedules appointments using Vapi workflows. -slug: workflows/examples/outbound-sales +slug: workflows/examples/lead-qualification description: Build a voice AI outbound sales workflow with lead qualification, CRM integration, and automated follow-up using Vapi's visual workflow builder. --- @@ -144,12 +144,13 @@ You'll start with a default template that includes a "Call Start" node. We'll mo **Node Name**: `opening_and_permission` - **Prompt**: - ```txt + ```txt title="First Message" + Hi, this is Alex calling from TechFlow Solutions. I hope I'm catching you at a good time. I'm reaching out because I noticed your company might benefit from our workflow automation platform. Do you have just 2 minutes to chat? + ``` + + ```txt title="Prompt" You are Alex, a professional outbound sales representative for TechFlow Solutions. - Start with: "Hi, this is Alex calling from TechFlow Solutions. I hope I'm catching you at a good time. I'm reaching out because I noticed your company might benefit from our workflow automation platform. Do you have just 2 minutes to chat?" - Listen for their response and determine: - "permission_granted" if they agree to talk - "busy_reschedule" if they're busy but open to rescheduling @@ -169,6 +170,10 @@ You'll start with a default template that includes a "Call Start" node. We'll mo Add a **Tool** node that runs before the opening: + ```txt title="Condition" + Call initiated + ``` + **Tool**: Select your pre-configured "Lead Lookup" tool from the dropdown. This tool should be created in the **Tools** section of your dashboard with: - **Function Name**: `lookup_lead` - **Description**: "Retrieve lead information and call history" @@ -181,50 +186,125 @@ You'll start with a default template that includes a "Call Start" node. We'll mo Create branching paths based on the prospect's response. Add multiple conversation nodes: **Discovery Questions Node**: - - **Node Name**: `discovery_questions` - - **Prompt**: `Great! I appreciate your time. To better understand how we might help, can you tell me about your current workflow challenges? Specifically, what manual processes are taking up most of your team's time?` + + ```txt title="Condition" + Permission granted to continue conversation + ``` + + **Node Name**: `discovery_questions` + + ```txt title="First Message" + Great! I appreciate your time. To better understand how we might help, can you tell me about your current workflow challenges? Specifically, what manual processes are taking up most of your team's time? + ``` + + ```txt title="Prompt" + You are conducting discovery to understand their business challenges. + + Ask open-ended questions about their pain points and workflows. + Listen for automation opportunities and budget indicators. + Keep responses under 35 words and be genuinely curious. + ``` **Reschedule Node**: - - **Node Name**: `schedule_callback` - - **Prompt**: `I completely understand. When would be a better time for a quick 5-minute conversation? I have availability tomorrow morning or afternoon.` + + ```txt title="Condition" + Prospect is busy but willing to reschedule + ``` + + **Node Name**: `schedule_callback` + + ```txt title="First Message" + I completely understand. When would be a better time for a quick 5-minute conversation? I have availability tomorrow morning or afternoon. + ``` + + ```txt title="Prompt" + You are scheduling a callback with a busy prospect. + + Be flexible with their schedule and offer specific time options. + Confirm the callback time and set a reminder. + Keep responses under 25 words. + ``` **Objection Handling Node**: - - **Node Name**: `handle_initial_objection` - - **Prompt**: `I understand you might not be looking for new solutions right now. Can I ask what you're currently using for workflow automation? I might have some insights that could be valuable.` + + ```txt title="Condition" + Prospect shows initial resistance or not interested + ``` + + **Node Name**: `handle_initial_objection` + + ```txt title="First Message" + I understand you might not be looking for new solutions right now. Can I ask what you're currently using for workflow automation? I might have some insights that could be valuable. + ``` + + ```txt title="Prompt" + You are handling initial objections with curiosity and value. + + Don't be pushy. Ask questions to understand their current situation. + Offer insights rather than pushing for a sale. + Keep responses under 30 words. + ``` **Gatekeeper Node**: - - **Node Name**: `gatekeeper_routing` - - **Prompt**: `I appreciate you taking the call. I'm looking to speak with whoever handles software decisions or operations. Would that be you, or could you point me in the right direction?` + + ```txt title="Condition" + Speaking with gatekeeper or non-decision maker + ``` + + **Node Name**: `gatekeeper_routing` + + ```txt title="First Message" + I appreciate you taking the call. I'm looking to speak with whoever handles software decisions or operations. Would that be you, or could you point me in the right direction? + ``` + + ```txt title="Prompt" + You are working with a gatekeeper to reach the decision maker. + + Be respectful and professional. Get the right contact or decision maker. + Build rapport with the gatekeeper as they can help or hinder. + Keep responses under 30 words. + ``` Connect the nodes with conditions for the LLM to interpret: - **From opening_and_permission to discovery_questions**: - - Condition: `{{ permission_status == "permission_granted" }}` + **To Discovery Questions Node**: + - Condition: `Permission granted to continue conversation` - **From opening_and_permission to schedule_callback**: - - Condition: `{{ permission_status == "busy_reschedule" }}` + **To Reschedule Node**: + - Condition: `Prospect is busy but willing to reschedule` - **From opening_and_permission to handle_initial_objection**: - - Condition: `{{ permission_status == "not_interested" }}` + **To Objection Handling Node**: + - Condition: `Prospect shows initial resistance or not interested` - **From opening_and_permission to gatekeeper_routing**: - - Condition: `{{ permission_status == "gatekeeper" }}` + **To Gatekeeper Node**: + - Condition: `Speaking with gatekeeper or non-decision maker` Create a global node that handles objections throughout the call: + ```txt title="Condition" + Objection detected or negative sentiment + ``` + **Node Name**: `objection_handler` **Global Node**: `enabled = true` **Enter Condition**: `{{ objection_detected == true or negative_sentiment == true }}` - **Prompt**: - ```txt + ```txt title="First Message" I hear your concern, and that's completely valid. Many of our clients had similar thoughts initially. Let me address that specific point and see if we can find a solution that makes sense for your situation. ``` + ```txt title="Prompt" + You are handling an objection with empathy and understanding. + + Acknowledge their concern as valid. Use social proof. + Address the specific objection with relevant information. + Keep responses under 35 words. + ``` + This global node will activate whenever an objection is detected, regardless of where they are in the sales conversation. @@ -232,96 +312,226 @@ You'll start with a default template that includes a "Call Start" node. We'll mo For prospects who engage, add these qualification nodes: **BANT Qualification Node**: - - **Node Name**: `bant_qualification` - - Extract budget, authority, need, and timeline information + + ```txt title="Condition" + Prospect engaged and willing to discuss needs + ``` + + **Node Name**: `bant_qualification` + + ```txt title="First Message" + That's helpful context. To better understand if we're a fit, can you tell me about your budget range for workflow automation tools? Also, who typically makes software purchasing decisions at your company? + ``` + + ```txt title="Prompt" + You are qualifying the prospect using BANT criteria (Budget, Authority, Need, Timeline). + + Ask about budget, decision-making process, specific needs, and timeline. + Be natural - don't make it feel like an interrogation. + Keep responses under 35 words. + ``` + + **Extract Variables**: + - Variable: `budget_range` + - Type: `String` + - Description: `Budget information provided` +
+ - Variable: `decision_authority` + - Type: `String` + - Description: `Decision-making authority level` +
+ - Variable: `timeline` + - Type: `String` + - Description: `Purchase timeline or urgency` **Lead Scoring Tool Node**: + + ```txt title="Condition" + BANT qualification completed + ``` + - Add a **Tool** node that calls lead scoring API based on qualification responses **Qualification Results Node**: - - **Node Name**: `route_by_score` + + ```txt title="Condition" + Lead score calculated + ``` + + **Node Name**: `route_by_score` + + ```txt title="First Message" + Based on what you've shared, it sounds like there could be a great fit here. Let me show you how we've helped similar companies in your industry. + ``` + + ```txt title="Prompt" + You are routing the conversation based on lead qualification score. + + High scores get immediate demo offers. + Medium scores get value proposition and nurturing. + Low scores get educational content and future follow-up. + Keep responses under 30 words. + ``` + - Route based on lead score (hot, warm, cold) **Industry-Specific Pitch Node**: - - **Node Name**: `tailored_pitch` + + ```txt title="Condition" + Qualified prospect ready for value proposition + ``` + + **Node Name**: `tailored_pitch` + + ```txt title="First Message" + Given your challenges with [specific pain point], let me share how we helped [similar company] reduce their manual processes by 60% and save 15 hours per week. + ``` + + ```txt title="Prompt" + You are presenting a tailored value proposition based on their specific situation. + + Use relevant case studies and specific benefits. + Connect features to their stated pain points. + Keep responses under 40 words. + ``` + - Present value proposition based on their industry and pain points **ROI Demonstration Node**: - - **Node Name**: `show_roi` + + ```txt title="Condition" + Interest shown in value proposition + ``` + + **Node Name**: `show_roi` + + ```txt title="First Message" + Here's what that looks like in real numbers: if your team spends 20 hours a week on manual processes, our platform could save you $50,000 annually in productivity gains. + ``` + + ```txt title="Prompt" + You are demonstrating concrete ROI with specific numbers. + + Use their company size and situation to calculate relevant savings. + Make the ROI tangible and compelling. + Keep responses under 35 words. + ``` + - Provide specific ROI examples and case studies **Demo Offer Node**: - - **Node Name**: `offer_demo` + + ```txt title="Condition" + Strong interest and ROI demonstrated + ``` + + **Node Name**: `offer_demo` + + ```txt title="First Message" + I'd love to show you exactly how this would work for your specific workflow. Could we schedule a 15-minute demo where I can walk you through a custom setup for your team? + ``` + + ```txt title="Prompt" + You are proposing a product demonstration meeting. + + Make the demo offer specific and time-bounded. + Emphasize the custom/personalized aspect. + Be confident but not pushy. Keep responses under 30 words. + ``` + - Propose a product demonstration meeting **Calendar Check Tool Node**: + + ```txt title="Condition" + Demo requested and prospect interested + ``` + - Add a **Tool** node that checks sales team calendar for available demo slots **Appointment Confirmation Node**: - - **Node Name**: `confirm_appointment` + + ```txt title="Condition" + Demo slot available + ``` + + **Node Name**: `confirm_appointment` + + ```txt title="First Message" + Perfect! I have availability for a demo on [date] at [time]. I'll send you a calendar invite with a Zoom link. Should I include anyone else from your team? + ``` + + ```txt title="Prompt" + You are confirming the demo appointment details. + + Confirm date, time, and attendees. Offer to include other stakeholders. + Set expectations for what they'll see in the demo. + Keep responses under 35 words. + ``` + - Confirm meeting details and send calendar invite **CRM Update Tool Node**: + + ```txt title="Condition" + Appointment confirmed + ``` + - Add a **Tool** node that records call outcome and next steps in CRM **Transfer to Sales Rep Node**: - - **Node Type**: `Transfer` - - **Destination**: `+1-555-SALES-1` (your sales team number) + + ```txt title="Condition" + High-value prospect requests immediate consultation + ``` + + **Node Type**: `Transfer` + **Destination**: `+1-555-SALES-1` (your sales team number) **Schedule Follow-up Node**: - - **Node Name**: `schedule_followup` + + ```txt title="Condition" + Prospect interested but not ready for demo + ``` + + **Node Name**: `schedule_followup` + + ```txt title="First Message" + I understand you need some time to think it over. When would be a good time for me to follow up? I can also send you some relevant case studies in the meantime. + ``` + + ```txt title="Prompt" + You are scheduling a follow-up call for future nurturing. + + Be patient and respectful of their timeline. + Offer valuable content to keep them engaged. + Keep responses under 30 words. + ``` + - Set automated follow-up call for future date **End Call Node**: - - **Node Type**: `Hangup` + + ```txt title="Condition" + Prospect not qualified or requests no further contact + ``` + + **Node Type**: `Hangup` - Use when prospect is not qualified or requests no further contact ---- - -## 5. Configure Phone Number for Outbound Calls +## Final Workflow - - - Click `Phone Numbers` in the left sidebar of your dashboard. - - - - Click `Create Phone Number` for a new Vapi number, or - - Click `Import Phone Number` to use your existing number from Twilio/Telnyx - - - **Assistant**: Select your `Alex - Sales Agent` assistant - **Workflow**: Ensure it's linked to your `TechFlow Sales Qualification Workflow` - - **Outbound Configuration**: - - Enable outbound calling capabilities - - Set caller ID name to "TechFlow Solutions" - - Configure voicemail detection and handling - - Set maximum call duration (e.g., 10 minutes) - - - Use the Vapi API to initiate test outbound calls: - ```bash - curl -X POST https://api.vapi.ai/call \ - -H "Authorization: Bearer YOUR_API_KEY" \ - -H "Content-Type: application/json" \ - -d '{ - "phoneNumberId": "your-phone-number-id", - "customer": { - "number": "+1234567890" - }, - "assistantId": "your-assistant-id" - }' - ``` - - + + Sales qualification workflow showing lead lookup, permission-based routing, BANT qualification, demo scheduling, and CRM updates + ## Integrating with Real Systems diff --git a/fern/workflows/overview.mdx b/fern/workflows/overview.mdx index 4cdcfe67..44385ebe 100644 --- a/fern/workflows/overview.mdx +++ b/fern/workflows/overview.mdx @@ -178,6 +178,6 @@ A useful combination of features is to extract variables as enums and use them t Ready to start building? Check out these resources: * [**Workflows quickstart**](/workflows/quickstart) - Build your first workflow step-by-step -* [**Workflow examples**](/workflows/examples) - Explore pre-built workflows for common use cases +* [**Workflow examples**](/workflows/examples/appointment-scheduling) - Explore pre-built workflows for common use cases * [**Custom Tools**](/tools/custom-tools) - Integrate external APIs and services into your workflows -* [**Dynamic Variables**](/assistants/dynamic-variables) - Advanced variable usage and personalization techniques \ No newline at end of file +* [**Dynamic Variables**](/assistants/dynamic-variables) - Advanced variable usage and personalization techniques