# AI Voice Agents for Education

> Build intelligent voice agents for educational institutions - handle admission inquiries, fee reminders, attendance notifications, parent communication, and exam result announcements with multi-language support.

Source: https://edesy.in/docs/voice-agent/industries/education

Comprehensive guide to deploying voice agents in educational institutions for automating admission inquiries, fee collection, attendance tracking, parent communication, and result announcements.

## Use Cases

| Use Case | Type | Description |
|----------|------|-------------|
| Admission Inquiries | Inbound | Answer questions about courses, eligibility, fees, and admission process |
| Fee Reminders | Outbound | Automated calls for fee payment reminders and confirmations |
| Attendance Notifications | Outbound | Alert parents about student absence or late arrivals |
| Parent Communication | Both | General updates, PTM reminders, event notifications |
| Exam Results | Outbound | Announce results with grades and performance summary |
| Transport Updates | Outbound | Bus delay notifications, route changes |

## Agent Configuration

### Admission Inquiry Agent

```json
{
  "agent": {
    "name": "Campus Admissions",
    "language": "en-IN",

    "llmProvider": "gemini-2.5",
    "llmModel": "gemini-2.5-flash-lite",
    "llmTemperature": 0.6,

    "sttProvider": "deepgram",
    "sttModel": "nova-3",
    "sttConfig": {
      "endpointing": 350,
      "interimResults": true,
      "keywords": ["admission:2", "fees:2", "scholarship:2", "hostel:2"]
    },

    "ttsProvider": "azure",
    "ttsVoice": "en-IN-NeerjaNeural",
    "ttsConfig": {
      "rate": "0%",
      "pitch": "0%"
    },

    "greetingMessage": "Thank you for calling ABC School admissions. I'm here to help you with information about our programs, admission process, and fees. How may I assist you today?",

    "allowInterruptions": true,

    "prompt": "...",

    "tools": [],

    "webhooks": {
      "url": "https://your-server.com/webhooks/education",
      "events": ["call.ended", "call.analyzed"]
    }
  }
}
```

### Fee Reminder Agent (Outbound)

```json
{
  "agent": {
    "name": "Fee Reminder",
    "language": "hi-IN",
    "type": "outbound",

    "llmProvider": "gemini-2.5",
    "llmModel": "gemini-2.5-flash-lite",
    "llmTemperature": 0.5,

    "sttProvider": "deepgram",
    "sttModel": "nova-3",
    "sttConfig": {
      "language": "hi",
      "endpointing": 400
    },

    "ttsProvider": "azure",
    "ttsVoice": "hi-IN-SwaraNeural",

    "greetingMessage": "Namaste {{parentName}} ji. Main ABC School se bol raha/rahi hoon. {{studentName}} ki {{feeType}} fees ke baare mein baat karni thi.",

    "prompt": "...",

    "variables": {
      "parentName": "Parent Name",
      "studentName": "Student Name",
      "studentClass": "Class/Grade",
      "feeType": "Fee Type",
      "feeAmount": "Amount Due",
      "dueDate": "Due Date",
      "paymentLink": "Payment URL"
    }
  }
}
```

## System Prompts

### Admission Inquiry Agent

```
You are a friendly and knowledgeable admissions counselor for {{institutionName}}, a {{institutionType}}.

## Your Role
- Answer questions about courses, programs, and eligibility criteria
- Explain the admission process and required documents
- Provide fee structure and scholarship information
- Schedule campus visits and counseling sessions
- Collect prospective student information for follow-up

## Institution Information
- Name: {{institutionName}}
- Type: {{institutionType}} (School/College/University)
- Courses: {{coursesList}}
- Admission Open: {{admissionPeriod}}
- Website: {{websiteUrl}}

## Response Guidelines

### Style
- Be warm, professional, and encouraging
- Keep responses concise (2-3 sentences max)
- Use simple language, avoid jargon
- Be patient with parents who may not speak English fluently

### Information Flow
1. Greet and understand their query
2. Identify the program/class they're interested in
3. Provide relevant information
4. Collect contact details for follow-up
5. Offer to schedule a campus visit

### Common Questions

**Admission Process:**
"Our admission process has three steps: First, you submit an online application with documents. Then, there's an entrance test on {{testDate}}. Finally, we conduct a personal interview."

**Fees:**
"For {{className}}, the annual fee is {{feeAmount}}. This includes tuition, books, and uniform. We also offer EMI payment options and scholarships for meritorious students."

**Eligibility:**
"For {{programName}}, you need {{eligibilityCriteria}}. The minimum marks requirement is {{minMarks}}%."

## Scholarship Information
Mention these scholarships when relevant:
- Merit Scholarship: 25% off for 90%+ in previous class
- Sibling Discount: 10% for second child
- EWS Quota: As per government norms

## What NOT to Do
- Don't confirm admission without proper process
- Don't commit to specific scholarship amounts
- Don't share other students' information
- Don't criticize other institutions
```

### Fee Reminder Agent (Hindi)

```
Aap {{institutionName}} ke fee reminder assistant hain.

## Aapka Kaam
- Parents ko fees ki yaad dilaana
- Payment options batana
- Payment confirmation lena
- Zaroorat ho toh installment plan discuss karna

## Call Flow

### 1. Introduction
"Namaste {{parentName}} ji. Main {{institutionName}} se bol raha/rahi hoon. {{studentName}}, class {{studentClass}} ki {{feeType}} fees ke baare mein baat karni thi."

### 2. Fee Details
"Aapki pending fees ₹{{feeAmount}} hai, jiska due date {{dueDate}} hai."

### 3. Payment Options
"Aap online payment kar sakte hain ya school office mein bhi payment kar sakte hain. Kya aapko payment link SMS kar doon?"

### 4. If Payment Difficulty
"Main samajh sakta/sakti hoon. Hum installment option bhi de sakte hain. Kya aap accountant se baat karna chahenge?"

## Guidelines
- Samman se baat karein (aap/ji ka istemaal)
- Pressure na dein, samjhdaari se baat karein
- Payment link bhejne ki offer karein
- Zaroorat ho toh human agent ko transfer karein

## Handling Common Responses

"Payment kar diya hai":
→ "Dhanyavaad! Kya aap mujhe transaction number bata sakte hain taaki main verify kar sakoon?"

"Abhi nahi kar sakta":
→ "Koi baat nahi. Kya aap mujhe bata sakte hain kab tak payment ho paayega?"

"Installment chahiye":
→ "Bilkul. Main aapko accountant se connect kar deta/deti hoon jo aapko best plan bata sakenge."
```

### Attendance Notification Agent

```
You are an automated attendance notification system for {{institutionName}}.

## Purpose
Inform parents when their child is absent or arrives late.

## Call Script

### Absent Notification
"Good morning {{parentName}}. This is an automated call from {{institutionName}}. We noticed that {{studentName}} from class {{studentClass}} is not present in school today, {{currentDate}}. If this is planned, no action is needed. Otherwise, please contact the school office. Thank you."

### Late Arrival
"Good morning {{parentName}}. This is {{institutionName}} calling. {{studentName}} arrived at school late today at {{arrivalTime}}. This is for your information. Thank you."

## Guidelines
- Keep the message brief and factual
- Don't alarm parents unnecessarily
- Provide school contact number for questions
- End call politely if no response needed
```

## Tools

### Get Student Information

```json
{
  "type": "function",
  "function": {
    "name": "get_student_info",
    "description": "Retrieve student details including class, section, fee status, and attendance",
    "parameters": {
      "type": "object",
      "properties": {
        "student_id": {
          "type": "string",
          "description": "Student ID or enrollment number"
        },
        "parent_phone": {
          "type": "string",
          "description": "Parent's registered phone number"
        }
      },
      "required": []
    }
  }
}
```

### Check Fee Status

```json
{
  "type": "function",
  "function": {
    "name": "check_fee_status",
    "description": "Get pending fees and payment history for a student",
    "parameters": {
      "type": "object",
      "properties": {
        "student_id": {
          "type": "string",
          "description": "Student ID"
        },
        "fee_type": {
          "type": "string",
          "enum": ["tuition", "transport", "hostel", "examination", "all"],
          "description": "Type of fee to check"
        }
      },
      "required": ["student_id"]
    }
  }
}
```

### Schedule Campus Visit

```json
{
  "type": "function",
  "function": {
    "name": "schedule_campus_visit",
    "description": "Book a campus visit or counseling session for prospective students",
    "parameters": {
      "type": "object",
      "properties": {
        "parent_name": {
          "type": "string",
          "description": "Parent's name"
        },
        "phone": {
          "type": "string",
          "description": "Contact phone number"
        },
        "student_name": {
          "type": "string",
          "description": "Prospective student's name"
        },
        "current_class": {
          "type": "string",
          "description": "Student's current class"
        },
        "interested_class": {
          "type": "string",
          "description": "Class seeking admission for"
        },
        "preferred_date": {
          "type": "string",
          "description": "Preferred visit date"
        },
        "preferred_time": {
          "type": "string",
          "enum": ["morning", "afternoon"],
          "description": "Preferred time slot"
        }
      },
      "required": ["parent_name", "phone", "interested_class"]
    }
  }
}
```

### Send Payment Link

```json
{
  "type": "function",
  "function": {
    "name": "send_payment_link",
    "description": "Send fee payment link via SMS to parent",
    "parameters": {
      "type": "object",
      "properties": {
        "student_id": {
          "type": "string",
          "description": "Student ID"
        },
        "phone": {
          "type": "string",
          "description": "Phone number to send SMS"
        },
        "amount": {
          "type": "number",
          "description": "Payment amount"
        },
        "fee_type": {
          "type": "string",
          "description": "Type of fee"
        }
      },
      "required": ["student_id", "phone", "amount"]
    }
  }
}
```

### Record Payment Promise

```json
{
  "type": "function",
  "function": {
    "name": "record_payment_promise",
    "description": "Record when parent promises to pay by a certain date",
    "parameters": {
      "type": "object",
      "properties": {
        "student_id": {
          "type": "string"
        },
        "promised_date": {
          "type": "string",
          "description": "Date parent promised to pay (YYYY-MM-DD)"
        },
        "promised_amount": {
          "type": "number",
          "description": "Amount promised"
        },
        "notes": {
          "type": "string",
          "description": "Any additional notes"
        }
      },
      "required": ["student_id", "promised_date"]
    }
  }
}
```

### Transfer to Counselor

```json
{
  "type": "function",
  "function": {
    "name": "transfer_to_counselor",
    "description": "Transfer call to human admission counselor or accountant",
    "parameters": {
      "type": "object",
      "properties": {
        "department": {
          "type": "string",
          "enum": ["admissions", "accounts", "principal", "transport"],
          "description": "Department to transfer to"
        },
        "reason": {
          "type": "string",
          "description": "Reason for transfer"
        },
        "priority": {
          "type": "string",
          "enum": ["normal", "urgent"],
          "description": "Call priority"
        }
      },
      "required": ["department", "reason"]
    }
  }
}
```

## Tool Handlers

```go
package education

import (
    "context"
    "fmt"
    "time"
)

type StudentInfo struct {
    ID           string
    Name         string
    Class        string
    Section      string
    ParentName   string
    ParentPhone  string
    FeeStatus    FeeStatus
    Attendance   float64
}

type FeeStatus struct {
    TotalDue      float64
    PendingAmount float64
    DueDate       time.Time
    LastPayment   time.Time
    FeeBreakdown  map[string]float64
}

func handleGetStudentInfo(ctx context.Context, params map[string]any) (any, error) {
    var student *StudentInfo
    var err error

    if studentID, ok := params["student_id"].(string); ok {
        student, err = studentService.GetByID(studentID)
    } else if phone, ok := params["parent_phone"].(string); ok {
        student, err = studentService.GetByParentPhone(phone)
    }

    if err != nil {
        return map[string]any{
            "found": false,
            "message": "I couldn't find the student record. Could you verify the details?",
        }, nil
    }

    return map[string]any{
        "found":       true,
        "name":        student.Name,
        "class":       student.Class,
        "section":     student.Section,
        "parent_name": student.ParentName,
        "fee_pending": student.FeeStatus.PendingAmount,
        "attendance":  fmt.Sprintf("%.1f%%", student.Attendance),
    }, nil
}

func handleCheckFeeStatus(ctx context.Context, params map[string]any) (any, error) {
    studentID := params["student_id"].(string)
    feeType := "all"
    if ft, ok := params["fee_type"].(string); ok {
        feeType = ft
    }

    fees, err := feeService.GetPendingFees(studentID, feeType)
    if err != nil {
        return nil, err
    }

    if fees.PendingAmount == 0 {
        return map[string]any{
            "status": "paid",
            "message": "All fees are paid. Thank you!",
        }, nil
    }

    return map[string]any{
        "status":     "pending",
        "amount":     fees.PendingAmount,
        "due_date":   fees.DueDate.Format("2 January 2006"),
        "breakdown":  fees.Breakdown,
        "message":    fmt.Sprintf("Pending amount is Rs. %.0f, due by %s", fees.PendingAmount, fees.DueDate.Format("2 January")),
    }, nil
}

func handleScheduleCampusVisit(ctx context.Context, params map[string]any) (any, error) {
    visit := CampusVisit{
        ParentName:      params["parent_name"].(string),
        Phone:           params["phone"].(string),
        InterestedClass: params["interested_class"].(string),
    }

    if name, ok := params["student_name"].(string); ok {
        visit.StudentName = name
    }

    // Get next available slot
    slot, err := calendarService.GetNextAvailableSlot(params["preferred_date"], params["preferred_time"])
    if err != nil {
        return map[string]any{
            "booked": false,
            "message": "I couldn't find an available slot. Let me connect you with our admissions team.",
        }, nil
    }

    // Book the visit
    booking, err := visitService.Book(visit, slot)
    if err != nil {
        return nil, err
    }

    return map[string]any{
        "booked": true,
        "date":   slot.Date.Format("Monday, 2 January"),
        "time":   slot.Time,
        "confirmation": booking.ConfirmationID,
        "message": fmt.Sprintf("Your campus visit is scheduled for %s at %s. You'll receive an SMS confirmation shortly.",
            slot.Date.Format("2 January"), slot.Time),
    }, nil
}

func handleSendPaymentLink(ctx context.Context, params map[string]any) (any, error) {
    studentID := params["student_id"].(string)
    phone := params["phone"].(string)
    amount := params["amount"].(float64)

    // Generate payment link
    link, err := paymentService.GenerateLink(studentID, amount)
    if err != nil {
        return nil, err
    }

    // Send SMS
    err = smsService.Send(phone, fmt.Sprintf(
        "Pay school fees of Rs. %.0f for your ward. Click here: %s. Valid for 24 hours.",
        amount, link.ShortURL,
    ))

    if err != nil {
        return map[string]any{
            "sent": false,
            "message": "I couldn't send the SMS right now. Let me try again.",
        }, nil
    }

    return map[string]any{
        "sent": true,
        "message": "I've sent the payment link to your registered mobile number. It's valid for 24 hours.",
    }, nil
}
```

## Multi-Language Support

Educational institutions in India need to communicate with parents in their preferred language.

### Language Configuration by Region

```go
var RegionalLanguageConfig = map[string]AgentConfig{
    "north_india": {
        Languages: []string{"hi-IN", "en-IN", "pa-IN"},
        DefaultLang: "hi-IN",
        STT: STTConfig{
            Provider: "deepgram",
            Model: "nova-3",
        },
        TTS: TTSConfig{
            Provider: "azure",
            Voices: map[string]string{
                "hi-IN": "hi-IN-SwaraNeural",
                "en-IN": "en-IN-NeerjaNeural",
                "pa-IN": "pa-IN-GurpreetNeural",
            },
        },
    },
    "south_india": {
        Languages: []string{"ta-IN", "te-IN", "kn-IN", "ml-IN", "en-IN"},
        DefaultLang: "en-IN",
        STT: STTConfig{
            Provider: "google",
            Model: "chirp_2",
        },
        TTS: TTSConfig{
            Provider: "azure",
            Voices: map[string]string{
                "ta-IN": "ta-IN-PallaviNeural",
                "te-IN": "te-IN-ShrutiNeural",
                "kn-IN": "kn-IN-SapnaNeural",
                "ml-IN": "ml-IN-SobhanaNeural",
                "en-IN": "en-IN-NeerjaNeural",
            },
        },
    },
    "east_india": {
        Languages: []string{"bn-IN", "as-IN", "or-IN", "en-IN"},
        DefaultLang: "bn-IN",
        STT: STTConfig{
            Provider: "elevenlabs",
            Model: "scribe",
        },
        TTS: TTSConfig{
            Provider: "azure",
            Voices: map[string]string{
                "bn-IN": "bn-IN-TanishaaNeural",
                "as-IN": "as-IN-YashicaNeural",
                "or-IN": "or-IN-SubhasiniNeural",
                "en-IN": "en-IN-NeerjaNeural",
            },
        },
    },
}
```

### Language Selection by Parent Preference

```json
{
  "agent": {
    "name": "Multilingual Fee Reminder",
    "defaultLanguage": "hi-IN",
    "supportedLanguages": ["hi-IN", "en-IN", "ta-IN", "te-IN"],

    "greetingMessage": {
      "hi-IN": "Namaste {{parentName}} ji. Main {{schoolName}} se bol raha hoon.",
      "en-IN": "Hello {{parentName}}. This is a call from {{schoolName}}.",
      "ta-IN": "Vanakkam {{parentName}}. Naan {{schoolName}} irundhu pesugireen.",
      "te-IN": "Namaskaram {{parentName}} garu. Nenu {{schoolName}} nundi call chestunnanu."
    },

    "languageDetection": {
      "enabled": true,
      "initialPrompt": "Press 1 for English, 2 for Hindi, 3 for Tamil, 4 for Telugu. English ke liye 1, Hindi ke liye 2 dabayein.",
      "dtmfMapping": {
        "1": "en-IN",
        "2": "hi-IN",
        "3": "ta-IN",
        "4": "te-IN"
      }
    }
  }
}
```

### Parent Language Preference Storage

```go
type ParentPreference struct {
    ParentID     string
    PreferredLang string
    PreferredTime string  // morning, afternoon, evening
    DoNotCall    bool
    LastContact  time.Time
}

func getAgentConfigForParent(parentID string) (*AgentConfig, error) {
    pref, err := preferenceService.Get(parentID)
    if err != nil {
        // Default to Hindi
        return getDefaultConfig("hi-IN"), nil
    }

    config := getDefaultConfig(pref.PreferredLang)
    config.CallWindow = pref.PreferredTime

    return config, nil
}
```

## Outbound Campaign Configuration

### Fee Reminder Campaign

Campaigns are created in the dashboard, not through the API. [Open the Campaigns page](https://voice-agent.edesy.in/campaigns), pick the agent, upload your contact CSV (one column per variable, e.g. `parentName`, `studentName`, `feeAmount`, `dueDate`), and set the calling window and retries. See [Creating a Campaign](https://edesy.in/docs/voice-agent/campaigns), [CSV Upload](https://edesy.in/docs/voice-agent/campaigns/csv-upload) and [Scheduling](https://edesy.in/docs/voice-agent/campaigns/scheduling).

Once it is running, read progress and per-contact outcomes through the API:

```bash
# Campaign progress
curl https://voice-agent.edesy.in/api/v1/campaigns/{campaignId} \
  -H "Authorization: Bearer YOUR_API_KEY"

# Outcome of every contact
curl https://voice-agent.edesy.in/api/v1/campaigns/{campaignId}/calls \
  -H "Authorization: Bearer YOUR_API_KEY"
```

### Exam Results Announcement

Use the same flow with a results agent and a CSV holding `parentName`, `studentName`, `percentage` and `rank`.

## Analytics and Metrics

### Key Performance Indicators

```go
type EducationMetrics struct {
    // Admission Metrics
    InquiryCalls           int
    InquiryToVisitRate     float64  // % of calls that book campus visits
    VisitToAdmissionRate   float64  // % of visits that convert
    AverageCallDuration    time.Duration

    // Fee Collection Metrics
    TotalReminderCalls     int
    SuccessfulConnects     int       // Actually spoke to parent
    PaymentPromises        int
    PromiseToPaymentRate   float64   // % of promises that result in payment
    CollectionAmount       float64   // Total collected after calls

    // Efficiency Metrics
    CostPerCall            float64
    CostPerConversion      float64
    HumanTransferRate      float64
}

func trackEducationMetrics(call *Call) {
    // Track by campaign type
    switch call.CampaignType {
    case "admission_inquiry":
        metrics.Increment("education.admission.calls")
        if call.VisitScheduled {
            metrics.Increment("education.admission.visits_scheduled")
        }

    case "fee_reminder":
        metrics.Increment("education.fees.calls")
        if call.PaymentPromise {
            metrics.Increment("education.fees.promises")
            metrics.Gauge("education.fees.promised_amount", call.PromisedAmount)
        }
        if call.PaymentLinkSent {
            metrics.Increment("education.fees.links_sent")
        }
    }

    // Common metrics
    metrics.Histogram("education.call_duration", call.Duration.Seconds())
    if call.TransferredToHuman {
        metrics.Increment("education.human_transfers")
    }
}
```

### Fee Collection Dashboard

```go
type FeeCollectionReport struct {
    Date                time.Time
    TotalCalls          int
    Connected           int
    NotAnswered         int
    Busy                int

    PaymentPromises     int
    PromisedAmount      float64
    PaymentLinksSet    int

    ActualPayments      int       // Payments received
    CollectedAmount     float64   // After 48 hours of call

    ConversionRate      float64   // Promises that paid
    ROI                 float64   // Collection / Cost
}

func generateFeeReport(campaignID string, date time.Time) FeeCollectionReport {
    calls := getCampaignCalls(campaignID, date)

    report := FeeCollectionReport{Date: date}

    for _, call := range calls {
        report.TotalCalls++

        switch call.Disposition {
        case "connected":
            report.Connected++
        case "no_answer":
            report.NotAnswered++
        case "busy":
            report.Busy++
        }

        if call.PaymentPromise {
            report.PaymentPromises++
            report.PromisedAmount += call.PromisedAmount
        }
    }

    // Check actual payments (async, after 48 hours)
    payments := paymentService.GetPaymentsForCampaign(campaignID, date)
    report.ActualPayments = len(payments)
    for _, p := range payments {
        report.CollectedAmount += p.Amount
    }

    if report.PaymentPromises > 0 {
        report.ConversionRate = float64(report.ActualPayments) / float64(report.PaymentPromises)
    }

    callCost := float64(report.TotalCalls) * 2.5 // Rs. 2.5 per call
    if callCost > 0 {
        report.ROI = report.CollectedAmount / callCost
    }

    return report
}
```

### Admission Funnel Tracking

```go
type AdmissionFunnel struct {
    Inquiries       int     // Total inquiry calls
    Qualified       int     // Interested + eligible
    VisitsScheduled int     // Campus visits booked
    VisitsCompleted int     // Actually visited
    ApplicationsFiled int   // Submitted application
    Admissions      int     // Final admissions
}

func trackAdmissionConversion(inquiry *Inquiry) {
    // Stage 1: Inquiry
    metrics.Increment("admission.funnel.inquiries")

    // Stage 2: Qualification
    if inquiry.IsQualified() {
        metrics.Increment("admission.funnel.qualified")
    }

    // Stage 3: Visit Scheduled
    if inquiry.VisitScheduled {
        metrics.Increment("admission.funnel.visits_scheduled")
    }
}

// Webhook handler for downstream events
func handleAdmissionEvent(event AdmissionEvent) {
    switch event.Type {
    case "visit_completed":
        metrics.Increment("admission.funnel.visits_completed")
    case "application_submitted":
        metrics.Increment("admission.funnel.applications")
    case "admission_confirmed":
        metrics.Increment("admission.funnel.admissions")
        metrics.Gauge("admission.conversion_value", event.FeeAmount)
    }
}
```

## Best Practices

### 1. Respectful Communication

```go
// Always use respectful honorifics
var honorifics = map[string]string{
    "hi-IN": "ji",      // Sharma ji
    "ta-IN": "avargal", // Sharma avargal
    "te-IN": "garu",    // Sharma garu
    "bn-IN": "babu",    // Sharma babu
}

// Time-appropriate greetings
func getGreeting(lang string, hour int) string {
    greetings := map[string]map[string]string{
        "hi-IN": {
            "morning":   "Suprabhat",
            "afternoon": "Namaskar",
            "evening":   "Shubh sandhya",
        },
        "en-IN": {
            "morning":   "Good morning",
            "afternoon": "Good afternoon",
            "evening":   "Good evening",
        },
    }

    period := "afternoon"
    if hour < 12 {
        period = "morning"
    } else if hour >= 17 {
        period = "evening"
    }

    return greetings[lang][period]
}
```

### 2. Optimal Call Timing

```go
// Best times to reach parents
var optimalCallWindows = map[string]TimeWindow{
    "working_parents": {
        Start: "18:00",
        End:   "20:00",
        Days:  []string{"monday", "tuesday", "wednesday", "thursday", "friday"},
    },
    "homemakers": {
        Start: "10:00",
        End:   "12:00",
        Days:  []string{"monday", "tuesday", "wednesday", "thursday", "friday"},
    },
    "weekends": {
        Start: "10:00",
        End:   "13:00",
        Days:  []string{"saturday"},
    },
}

// Avoid calling during
var blackoutPeriods = []string{
    "school_hours",     // Parents may be in meetings
    "lunch_time",       // 13:00-14:00
    "early_morning",    // Before 09:00
    "late_evening",     // After 21:00
    "exam_days",        // When students have exams
}
```

### 3. Handle Sensitive Situations

```go
// Fee defaulters - extra care needed
var feeReminderGuidelines = `
For parents with overdue fees:
- Never shame or embarrass
- Always offer payment plans
- Transfer to accounts if needed
- Note: Some families face genuine hardship

Phrases to AVOID:
- "Your fees are very late"
- "We may have to take action"
- "Other parents have paid"

Phrases to USE:
- "I'm calling to help with payment options"
- "We have flexible payment plans"
- "How can we work together on this?"
`

// Handle emotional parents
func handleEmotionalCaller(session *Session) {
    // Detect distress keywords
    distressSignals := []string{"can't afford", "lost job", "financial problem", "please understand"}

    for _, signal := range distressSignals {
        if strings.Contains(session.LastTranscript, signal) {
            // Transfer to human with context
            session.Transfer("accounts", "Parent expressing financial difficulty - handle with empathy")
            return
        }
    }
}
```

### 4. Data Privacy Compliance

```go
// Student data is sensitive - follow privacy guidelines
type PrivacyConfig struct {
    // Only call registered numbers
    VerifyCallerID     bool

    // Don't share student info without verification
    RequireVerification bool

    // Log all data access
    AuditLogging       bool

    // Data retention
    TranscriptRetention time.Duration // 90 days
    RecordingRetention  time.Duration // 30 days
}

func verifyParentIdentity(session *Session, studentID string) bool {
    student := studentService.Get(studentID)

    // Verify caller is registered parent/guardian
    if session.CallerPhone != student.ParentPhone &&
       session.CallerPhone != student.GuardianPhone {
        session.TTS.Speak("I'm sorry, I can only share student information with registered parents. Please contact the school office.")
        return false
    }

    return true
}
```

### 5. Integration with School Management System

```go
// Webhook for SIS integration
type SISWebhook struct {
    EventType    string    `json:"event_type"`
    StudentID    string    `json:"student_id"`
    CallID       string    `json:"call_id"`
    Timestamp    time.Time `json:"timestamp"`
    Data         any       `json:"data"`
}

func handleCallEnded(call *Call) {
    // Sync with SIS
    webhook := SISWebhook{
        EventType: "voice_call_completed",
        StudentID: call.StudentID,
        CallID:    call.ID,
        Timestamp: time.Now(),
        Data: map[string]any{
            "purpose":       call.Purpose,
            "duration":      call.Duration.Seconds(),
            "outcome":       call.Outcome,
            "payment_promise": call.PaymentPromise,
            "transcript_summary": call.Summary,
        },
    }

    sisClient.SendWebhook(webhook)

    // Update student communication log
    sisClient.LogCommunication(call.StudentID, CommunicationLog{
        Type:    "voice_call",
        Date:    call.StartTime,
        Purpose: call.Purpose,
        Notes:   call.Summary,
    })
}
```

## Sample Integration

### Complete Fee Reminder Flow

```go
func runFeeReminderCampaign(ctx context.Context) {
    // 1. Get pending fees from SIS
    pendingFees := sisClient.GetPendingFees(FeeQuery{
        DueBefore: time.Now().AddDate(0, 0, 7), // Due in 7 days
        MinAmount: 1000,
    })

    // 2. Prepare campaign contacts
    var contacts []CampaignContact
    for _, fee := range pendingFees {
        // Get parent preference
        pref := preferenceService.Get(fee.ParentID)
        if pref.DoNotCall {
            continue
        }

        contacts = append(contacts, CampaignContact{
            Phone: fee.ParentPhone,
            Variables: map[string]string{
                "parentName":   fee.ParentName,
                "studentName":  fee.StudentName,
                "studentClass": fee.Class,
                "feeType":      fee.FeeType,
                "feeAmount":    fmt.Sprintf("%.0f", fee.Amount),
                "dueDate":      fee.DueDate.Format("2 January"),
            },
            Language: pref.PreferredLang,
        })
    }

    // 3. Create campaign
    campaign := Campaign{
        Name:     fmt.Sprintf("Fee Reminder - %s", time.Now().Format("Jan 2006")),
        AgentID:  "fee_reminder_hindi",
        Contacts: contacts,
        Schedule: CampaignSchedule{
            CallWindow: TimeWindow{Start: "10:00", End: "18:00"},
            ExcludeDays: []string{"sunday"},
        },
    }

    campaignService.Start(ctx, campaign)

    // 4. Monitor and report
    go monitorCampaign(campaign.ID)
}
```

## Next Steps

- [Indian Languages](https://edesy.in/docs/voice-agent/languages/indian-languages) - Multi-language configuration
- [Function Calling](https://edesy.in/docs/voice-agent/features/function-calling) - Tool integration
- [Outbound Sales](https://edesy.in/docs/voice-agent/examples/outbound-sales) - Campaign management
- [Webhooks](https://edesy.in/docs/voice-agent/features/webhooks) - SIS integration
