AI Voice Agents for 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
{
"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", "transcript.updated", "tool.executed"]
}
}
}
Fee Reminder Agent (Outbound)
{
"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
{
"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
{
"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
{
"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
{
"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
{
"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
{
"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
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
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
{
"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
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
curl -X POST https://api.edesy.in/v1/campaigns \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "Q1 Fee Reminder - January 2025",
"agent_id": "fee_reminder_hindi",
"type": "outbound",
"schedule": {
"start_date": "2025-01-05",
"end_date": "2025-01-15",
"call_window": {
"start": "10:00",
"end": "18:00"
},
"timezone": "Asia/Kolkata",
"exclude_days": ["sunday"]
},
"retry_config": {
"max_attempts": 3,
"retry_interval": "4h",
"retry_on": ["no_answer", "busy"]
},
"contacts": [
{
"phone": "+919876543210",
"variables": {
"parentName": "Sharma",
"studentName": "Rahul",
"studentClass": "8-A",
"feeType": "Quarterly",
"feeAmount": "15000",
"dueDate": "15 January 2025"
}
}
]
}'
Exam Results Announcement
curl -X POST https://api.edesy.in/v1/campaigns \
-H "Authorization: Bearer YOUR_API_KEY" \
-d '{
"name": "Mid-Term Results - Class 10",
"agent_id": "result_announcement",
"contacts_csv_url": "https://school-data.example.com/results/class10.csv",
"variables_mapping": {
"parentName": "parent_name",
"studentName": "student_name",
"percentage": "total_percentage",
"rank": "class_rank",
"subjects": "subject_grades"
}
}'
Analytics and Metrics
Key Performance Indicators
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
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
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
// 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
// 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
// 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
// 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
// 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
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 - Multi-language configuration
- Function Calling - Tool integration
- Outbound Sales - Campaign management
- Webhooks - SIS integration