Skip to main content

Overview

The scheduler service enables:
  • One-time scheduled calls
  • Recurring calls with cron expressions
  • Timezone support
  • Automatic execution
  • Manual trigger capability
  • Call history and logs

Creating Scheduled Calls

Single Call

curl -X POST http://localhost:8010/api/scheduled-calls \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -d '{
    "agent_id": "agent-123",
    "phone_number": "+1234567890",
    "scheduled_time": "2024-02-01 14:30:00",
    "timezone": "America/New_York",
    "name": "Follow-up call for John"
  }'

Recurring Call

curl -X POST http://localhost:8010/api/scheduled-calls/recurring \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -d '{
    "agent_id": "agent-123",
    "phone_number": "+1234567890",
    "cron_expression": "0 9 * * MON",
    "timezone": "America/New_York",
    "name": "Weekly check-in",
    "max_occurrences": 12
  }'

Cron Expression Guide

ExpressionMeaning
0 9 * * MONEvery Monday at 9:00 AM
0 9 * * MON-FRIEvery weekday at 9:00 AM
0 9,14 * * *Daily at 9:00 AM and 2:00 PM
0 9 1 * *First day of every month at 9:00 AM
0 9 * * 1,3,5Monday, Wednesday, Friday at 9:00 AM
*/15 * * * *Every 15 minutes
0 */4 * * *Every 4 hours
0 0 * * *Daily at midnight

Configuration

Basic Scheduling

from scheduler.scheduler import ScheduledCallService

service = ScheduledCallService()

# Schedule a call
scheduled_call = await service.schedule_call(
    agent_id="agent-123",
    phone_number="+1234567890",
    scheduled_time="2024-02-01 14:30:00",
    timezone="America/New_York"
)

print(f"Call scheduled: {scheduled_call.id}")

Advanced Configuration

scheduled_call = await service.schedule_call(
    agent_id="agent-123",
    phone_number="+1234567890",
    scheduled_time="2024-02-01 14:30:00",
    timezone="America/New_York",
    name="Customer Follow-up",
    description="Follow-up about order status",
    customer_context={
        "customer_id": "cust-123",
        "customer_name": "John Doe",
        "order_id": "ORD-456"
    },
    metadata={
        "campaign_id": "camp-789",
        "priority": "high"
    },
    retry_policy={
        "max_retries": 2,
        "retry_delay": 300  # 5 minutes
    }
)

Managing Scheduled Calls

List Scheduled Calls

curl -X GET http://localhost:8010/api/scheduled-calls \
  -H "Authorization: Bearer YOUR_TOKEN"

Get Scheduled Call Details

curl -X GET http://localhost:8010/api/scheduled-calls/{schedule_id} \
  -H "Authorization: Bearer YOUR_TOKEN"

Update Scheduled Call

curl -X PUT http://localhost:8010/api/scheduled-calls/{schedule_id} \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -d '{
    "scheduled_time": "2024-02-02 10:00:00",
    "customer_context": {
      "notes": "Updated context"
    }
  }'

Cancel Scheduled Call

curl -X DELETE http://localhost:8010/api/scheduled-calls/{schedule_id} \
  -H "Authorization: Bearer YOUR_TOKEN"

Pause/Resume Scheduled Call

# Pause
curl -X POST http://localhost:8010/api/scheduled-calls/{schedule_id}/pause \
  -H "Authorization: Bearer YOUR_TOKEN"

# Resume
curl -X POST http://localhost:8010/api/scheduled-calls/{schedule_id}/resume \
  -H "Authorization: Bearer YOUR_TOKEN"

Recurring Schedules

Daily Schedule

# Every day at 9 AM
await service.schedule_recurring_call(
    agent_id="agent-123",
    phone_number="+1234567890",
    cron_expression="0 9 * * *",
    timezone="America/New_York",
    max_occurrences=365  # Run for 1 year
)

Weekly Schedule

# Every Monday and Thursday at 2 PM
await service.schedule_recurring_call(
    agent_id="agent-123",
    phone_number="+1234567890",
    cron_expression="0 14 * * 1,4",
    timezone="America/New_York",
)

Monthly Schedule

# First day of every month at 9 AM
await service.schedule_recurring_call(
    agent_id="agent-123",
    phone_number="+1234567890",
    cron_expression="0 9 1 * *",
    timezone="America/New_York",
)

Business Hours Schedule

# Every weekday at 9 AM
await service.schedule_recurring_call(
    agent_id="agent-123",
    phone_number="+1234567890",
    cron_expression="0 9 * * 1-5",  # Monday-Friday
    timezone="America/New_York",
)

Timezone Handling

Supported Timezones

timezones = [
    "America/New_York",
    "America/Chicago",
    "America/Denver",
    "America/Los_Angeles",
    "America/Anchorage",
    "Pacific/Honolulu",
    "Europe/London",
    "Europe/Paris",
    "Europe/Berlin",
    "Asia/Tokyo",
    "Asia/Shanghai",
    "Asia/Hong_Kong",
    "Asia/Singapore",
    "Asia/Dubai",
    "Asia/Kolkata",
    "Australia/Sydney",
    "Australia/Melbourne",
]

Timezone Conversion

from datetime import datetime
import pytz

# Schedule for user's timezone
user_timezone = "America/Los_Angeles"
local_time = datetime(2024, 2, 1, 14, 30)

# Convert to UTC for storage
tz = pytz.timezone(user_timezone)
local_dt = tz.localize(local_time)
utc_dt = local_dt.astimezone(pytz.UTC)

scheduled_call = await service.schedule_call(
    agent_id="agent-123",
    phone_number="+1234567890",
    scheduled_time=utc_dt.isoformat(),
    timezone=user_timezone
)

Execution and Monitoring

Call Execution

# Scheduler automatically executes at scheduled time
# Triggers the call_service.initiate_call() method

# You can also manually trigger a scheduled call
await service.execute_now(schedule_id)

View Execution History

curl -X GET http://localhost:8010/api/scheduled-calls/{schedule_id}/history \
  -H "Authorization: Bearer YOUR_TOKEN"
Response:
{
  "schedule_id": "schedule-123",
  "executions": [
    {
      "execution_id": "exec-1",
      "scheduled_time": "2024-02-01 14:30:00",
      "actual_time": "2024-02-01 14:30:05",
      "call_id": "call-456",
      "status": "completed",
      "duration": 180,
      "error": null
    },
    {
      "execution_id": "exec-2",
      "scheduled_time": "2024-02-08 14:30:00",
      "actual_time": null,
      "call_id": null,
      "status": "pending",
      "error": null
    }
  ]
}

Error Handling

Failed Execution Handling

scheduled_call = await service.schedule_call(
    agent_id="agent-123",
    phone_number="+1234567890",
    scheduled_time="2024-02-01 14:30:00",
    timezone="America/New_York",
    retry_policy={
        "max_retries": 3,
        "retry_delay": 300,  # 5 minutes between retries
        "exponential_backoff": True,
        "retry_on": ["timeout", "no_answer", "busy"]
    }
)

Webhook Notifications

# Get notified when execution occurs
scheduled_call = await service.schedule_call(
    agent_id="agent-123",
    phone_number="+1234567890",
    scheduled_time="2024-02-01 14:30:00",
    timezone="America/New_York",
    webhook_url="https://yourapp.com/webhooks/call-executed",
    webhook_events=["started", "completed", "failed"]
)

Practical Examples

Customer Reminder System

async def schedule_appointment_reminder(customer_data):
    # Schedule reminder 24 hours before appointment
    reminder_time = customer_data['appointment_time'] - timedelta(days=1)
    
    await service.schedule_call(
        agent_id="reminder-agent",
        phone_number=customer_data['phone'],
        scheduled_time=reminder_time.isoformat(),
        timezone=customer_data['timezone'],
        customer_context={
            "customer_name": customer_data['name'],
            "appointment_time": customer_data['appointment_time'],
            "location": customer_data['location'],
            "notes": customer_data['notes']
        }
    )

Birthday/Anniversary Campaign

# Schedule birthday call for each customer
customers = await get_customers()

for customer in customers:
    # Schedule annually
    await service.schedule_recurring_call(
        agent_id="special-occasion-agent",
        phone_number=customer['phone'],
        cron_expression=f"0 10 {customer['birth_day']} {customer['birth_month']} *",
        timezone=customer['timezone'],
        customer_context={
            "customer_name": customer['name'],
            "occasion": "birthday"
        },
        max_occurrences=None  # Run indefinitely
    )

Follow-up Campaign

async def schedule_follow_ups(lead_id):
    lead = await get_lead(lead_id)
    
    # Follow-up schedule: immediately, 1 hour, 1 day, 3 days, 7 days
    follow_up_times = [
        datetime.now(),
        datetime.now() + timedelta(hours=1),
        datetime.now() + timedelta(days=1),
        datetime.now() + timedelta(days=3),
        datetime.now() + timedelta(days=7),
    ]
    
    for idx, time in enumerate(follow_up_times):
        await service.schedule_call(
            agent_id="followup-agent",
            phone_number=lead['phone'],
            scheduled_time=time.isoformat(),
            timezone=lead['timezone'],
            name=f"Follow-up #{idx + 1}",
            customer_context={
                "lead_id": lead_id,
                "attempt": idx + 1
            }
        )

Weekly Status Calls

# Schedule weekly status calls for all accounts
accounts = await get_accounts()

for account in accounts:
    # Every Monday at 9 AM their local time
    await service.schedule_recurring_call(
        agent_id="account-manager-agent",
        phone_number=account['phone'],
        cron_expression="0 9 * * 1",  # Monday
        timezone=account['timezone'],
        customer_context={
            "account_id": account['id'],
            "account_name": account['name']
        }
    )

Performance Optimization

Bulk Scheduling

# Schedule many calls efficiently
async def bulk_schedule_calls(phone_numbers, agent_id, scheduled_time):
    tasks = []
    
    for phone in phone_numbers:
        task = service.schedule_call(
            agent_id=agent_id,
            phone_number=phone,
            scheduled_time=scheduled_time
        )
        tasks.append(task)
    
    results = await asyncio.gather(*tasks)
    return results

Scheduler Health Check

curl -X GET http://localhost:8010/api/scheduler/health \
  -H "Authorization: Bearer YOUR_TOKEN"
Response:
{
  "status": "healthy",
  "scheduled_calls_pending": 245,
  "scheduled_calls_total": 1200,
  "last_execution": "2024-01-15T14:30:05Z",
  "failed_executions_today": 2
}

Next Steps

Batch Calls

Process multiple calls simultaneously.