Skip to main content

Scheduling in BotGami

Learn how to schedule messages, set reminders, and create time-based automation in your bots.


Overview

BotGami provides three types of scheduling:

TypeNodeBest For
One-time (Delay)flow.scheduleReminders, follow-ups
One-time (DateTime)flow.scheduleAppointments, deadlines
Recurring (Cron)sys.cron_triggerDaily reports, weekly summaries
Quick Messageflow.schedule_messageSimple delayed messages

Quick Message Scheduling

flow.schedule_message

The easiest way to schedule a single message.

Example: Welcome Drip Campaign

User completes signup

[flow.schedule_message]
Message: "👋 Welcome! Day 1: Getting started..."
DelayMs: 0 (send immediately)

[flow.schedule_message]
Message: "💡 Day 2: Pro tips for success..."
DelayMs: 86400000 (24 hours)

[flow.schedule_message]
Message: "🚀 Day 3: Advanced features..."
DelayMs: 172800000 (48 hours)

[Screenshot: Three schedule_message nodes showing drip campaign setup]

Time Conversion:

  • 1 second = 1,000ms
  • 1 minute = 60,000ms
  • 1 hour = 3,600,000ms
  • 1 day = 86,400,000ms
  • 1 week = 604,800,000ms

Full Task Scheduling

flow.schedule + sys.scheduled_trigger

For complex flows that need to run later, use the schedule + trigger pattern:

Step 1: Create the Trigger

[sys.scheduled_trigger]
Name: "reminder_trigger"

Outputs:
NEXT → [Flow to execute]
Params → [Data passed from scheduler]
UserID → [Target user]

Step 2: Schedule the Task

[flow.schedule]
TriggerName: "reminder_trigger"
Mode: delay OR datetime
Params: { ...data to pass }
↓ TaskID
[Save TaskID to var.reminder_id]

Complete Reminder System Example

Scenario: User sets a reminder for any future time

Implementation:

--- Set Reminder Flow ---

[Command: /remind]

[Parse input: "in 2 hours: Call mom"]

[Calculate DelayMs: 2 * 3600000 = 7200000]

[flow.schedule]
TriggerName: "send_reminder"
Mode: delay
DelayMs: 7200000
Params: {
"message": "Call mom",
"user_id": {{user.id}},
"set_at": "{{$now()}}"
}
UserID: {{user.id}}
↓ TaskID
[data.set_variable]
Scope: var
Key: active_reminder_id
Value: {{TaskID}}

[Send: "✅ Reminder set for 2 hours from now"]

--- Trigger Flow (runs later) ---

[sys.scheduled_trigger]
Name: "send_reminder"
↓ Params, UserID
[action.send]
ChatID: {{UserID}}
Text: "🔔 Reminder: {{Params.message}}"

[data.set_variable]
Scope: var
Key: active_reminder_id
Value: null // Clear the reminder

[Screenshot: Complete reminder flow showing both setup and trigger parts]


Canceling Schedules

flow.cancel_schedule

Users can cancel pending tasks:

Command: /cancel

[data.get_variable]
Scope: var
Key: active_reminder_id
↓ Found → TaskID
[flow.cancel_schedule]
TaskID: {{TaskID}}
↓ Success
[Send: "✅ Reminder cancelled"]
↓ NotFound
[Send: "No active reminder found"]]

Recurring Schedules (Cron)

sys.cron_trigger

For recurring tasks like daily reports or weekly summaries.

Cron Expression Format:

* * * * *
│ │ │ │ │
│ │ │ │ └─ Day of week (0-7, 0=Sunday)
│ │ │ └─── Month (1-12)
│ │ └───── Day of month (1-31)
│ └─────── Hour (0-23)
└───────── Minute (0-59)

Common Patterns:

ScheduleExpressionDescription
Every day at 9 AM0 9 * * *Morning reports
Every Monday at 10 AM0 10 * * 1Weekly summary
Every hour0 * * * *Hourly checks
Every 30 minutes*/30 * * * *Frequent updates
Weekdays at 5 PM0 17 * * 1-5End of workday
First day of month0 9 1 * *Monthly reports

Example: Daily Stats Report

[sys.cron_trigger]
Name: "daily_stats"
Expression: "0 9 * * *" // Every day at 9 AM
Timezone: "America/New_York"

[db.search_users]
Filter: signup_date > "yesterday"
↓ Count
[db.search_users]
Filter: last_active > "today"
↓ Count as active_count

[action.send]
ChatID: [ADMIN_CHAT_ID]
Text: "📊 Daily Report for {{$now()}}:

New signups: {{Count}}
Active users today: {{active_count}}"

[Screenshot: sys.cron_trigger node showing daily 9 AM schedule]


DateTime Scheduling

Schedule for exact date/time instead of delay:

User books appointment for Dec 25, 2024 at 2 PM

[flow.schedule]
Mode: datetime
DateTime: "2024-12-25T14:00:00Z" // ISO format
TriggerName: "appointment_reminder"
Params: {
"appointment_type": "Dentist",
"location": "Main Street Clinic"
}

--- Day Before Reminder ---

[flow.schedule]
Mode: datetime
DateTime: "2024-12-24T14:00:00Z" // 24h before
TriggerName: "appointment_reminder_24h"

ISO DateTime Format:

YYYY-MM-DDTHH:MM:SSZ

2024-12-25T14:30:00Z
│ │ │ │ │ │ └─ UTC timezone
│ │ │ │ │ └──── Seconds
│ │ │ │ └─────── Minutes
│ │ │ └────────── Hours (24h)
│ │ └───────────── Day
│ └──────────────── Month
└───────────────────── Year

Helper: Use data.transform to format dates:

Expression: $now() + 86400000  // +1 day in ms
Then convert to ISO string

Use Case: Trial Expiration

User starts 7-day trial

[flow.schedule]
Mode: delay
DelayMs: 604800000 // 7 days
TriggerName: "trial_expired"
Params: {
"user_id": {{user.id}},
"trial_start": "{{$now()}}"
}
↓ TaskID
[Save to var.trial_expiry_task]

--- 7 Days Later ---

[sys.scheduled_trigger]
Name: "trial_expired"

[db.get_user]
UserID: {{Params.user_id}}

[Condition: User.metadata.subscribed == false]
↓ True
[Send: "⏰ Your trial has ended. Upgrade to continue!"]
↓ False
[Send: "✅ Thanks for subscribing!"]

Use Case: Appointment Booking System

Complete flow:

--- Booking Flow ---

User selects date/time from menu wizard

[Save to var.appointment_date]

[flow.schedule - Main reminder]
DateTime: {{var.appointment_date}}
TriggerName: "appointment"
Params: {{appointment_details}}

[flow.schedule - 24h reminder]
DateTime: {{var.appointment_date - 24 hours}}
TriggerName: "appointment_reminder_24h"

[flow.schedule - 1h reminder]
DateTime: {{var.appointment_date - 1 hour}}
TriggerName: "appointment_reminder_1h"

[Confirm: "✅ Appointment booked! You'll get reminders."]

--- Reminders ---

[sys.scheduled_trigger: appointment_reminder_24h]

[Send: "📅 Tomorrow: {{Params.service}} at {{Params.time}}"]

[sys.scheduled_trigger: appointment_reminder_1h]

[Send: "⏰ In 1 hour: {{Params.service}}"]

[sys.scheduled_trigger: appointment]

[Send: "It's time for your {{Params.service}} appointment!"]

Best Practices

1. Store Task IDs for Cancellation

✅ Save TaskID to var.*
✅ Allow users to cancel with /cancel command

2. Handle Failed Schedules

[flow.schedule]
↓ NEXT
[Success path]
↓ Error
[Log + notify admin]

3. Timezone Awareness

[sys.cron_trigger]
Timezone: "America/New_York" // Specify user's timezone

4. Repeat Counts

[flow.schedule]
RepeatCount: 0 // One-time
RepeatCount: 3 // Repeat 3 times
RepeatCount: -1 // Infinite (use with cron instead)

5. Clean Up Expired Tasks

Store all TaskIDs in array
On completion, remove from array
Periodically check and cancel stale tasks

Common Patterns

Pattern 1: Nudge Sequence

User doesn't Complete action after 3 days

[Schedule +3 days] "Hey, still interested?"
[Schedule +7 days] "Last chance! 50% off"
[Schedule +14 days] "We miss you!"

Pattern 2: Daily Digest

[sys.cron_trigger: "0 8 * * *"]  // Daily 8 AM

[db.search_users with tags contains "subscribed"]

[For each user]

[Generate personalized digest]

[Send to each subscribed user]

Pattern 3: Event Countdown

Event in 7 days
[Schedule +0d]: "Event in 7 days!"
[Schedule +4d]: "Event in 3 days!"
[Schedule +6d]: "Event tomorrow!"
[Schedule +7d]: "Event starting now!"

Troubleshooting

Issue: Scheduled task didn't fire
Check:

  • Trigger name matches exactly
  • DateTime is in future
  • Bot is running/active

Issue: Can't cancel task
Check:

  • TaskID stored correctly
  • Task hasn't already executed
  • Task wasn't manually canceled

Issue: Wrong timezone
Fix: Always specify timezone in cron triggers


Quick Reference

NeedUse
Simple delayed messageflow.schedule_message
Complex delayed flowflow.schedule + sys.scheduled_trigger
Recurring (daily/weekly)sys.cron_trigger
Cancel taskflow.cancel_schedule

Next Steps