Calendar Voice Reminders
In a busy week, it’s easy to forget a meeting. Let Rose watch your calendar and speak to you before important moments — like having a thoughtful assistant sitting next to you.
Scenario
Where This Fits
| Scenario | Trigger | Delivery |
|---|---|---|
| Customer meeting | 15 minutes before | Voice + text |
| Team meeting | 10 minutes before | Voice |
| Major deadline | 1 day out | Voice + details |
| Business travel | 2 hours before departure | Voice + weather |
| Daily check-in | Fixed daily time | Short voice |
Expected Results
- No more missed meetings — early, with time to prep
- Voice stands out — harder to ignore than a text notification
- Works on the go — listen in the car
- Layered alerts — one day, one hour, fifteen minutes
Calendar Integration
Supported Sources
| Source | Method | Difficulty |
|---|---|---|
| Google Calendar | Google API | Medium |
| Microsoft Outlook | Microsoft Graph API | Medium |
| CalDAV | Standard protocol | High |
| Local calendar files | Read .ics files | Low |
Google Calendar Setup
{`1. Open Google Cloud Console
https://console.cloud.google.com/
2. Create or pick a project
3. Enable the Google Calendar API
- APIs and Services → Library
- Search "Google Calendar API"
- Click Enable
4. Create credentials
- APIs and Services → Credentials
- Create credentials → OAuth 2.0 Client ID
- Application type: Desktop app
- Download the JSON file
5. Store the file at:
~/.config/realvco/google-credentials.json`}
Calendar Sync Script
{`// Calendar sync
const { google } = require('googleapis');
const fs = require('fs');
async function getUpcomingEvents() {
const credentials = JSON.parse(
fs.readFileSync(process.env.GOOGLE_CREDENTIALS_PATH)
);
const { client_secret, client_id, redirect_uris } = credentials.installed;
const oAuth2Client = new google.auth.OAuth2(
client_id, client_secret, redirect_uris[0]
);
oAuth2Client.setCredentials({
access_token: process.env.GOOGLE_ACCESS_TOKEN,
refresh_token: process.env.GOOGLE_REFRESH_TOKEN
});
const calendar = google.calendar({ version: 'v3', auth: oAuth2Client });
const now = new Date();
const tomorrow = new Date(now);
tomorrow.setDate(tomorrow.getDate() + 1);
const response = await calendar.events.list({
calendarId: 'primary',
timeMin: now.toISOString(),
timeMax: tomorrow.toISOString(),
singleEvents: true,
orderBy: 'startTime'
});
return response.data.items;
}
module.exports = { getUpcomingEvents };`}
Voice Reminder Configuration
Reminder Flow
┌──────────────┐ ┌──────────────┐ ┌──────────────┐
│ Check calendar│ → │ Decide timing │ → │ Compose voice │
├──────────────┤ ├──────────────┤ ├──────────────┤
│ Every 5 min │ │ • 15 min out │ │ • Meeting │
│ Read events │ │ • 1 hour out │ │ • Start time │
│ │ │ • 1 day out │ │ • Location │
└──────────────┘ └──────────────┘ └──────┬───────┘
│
▼
┌──────────────┐
│ Deliver │
├──────────────┤
│ • Text │
│ • Voice │
│ • Push │
└──────────────┘
Templates
{`# 15-Minute Reminder
⏰ Meeting starts in 15 minutes
"Hey, your meeting starts in 15 minutes.
Meeting: {meeting_title}
Time: {start_time}
Location: {location}
Ready?"
---
# 1-Hour Reminder
📅 Meeting reminder
"In 1 hour you have a meeting.
{meeting_title}, starting at {start_time}.
{description}
Don't forget the prep materials."
---
# Morning Briefing
📋 Today's schedule
"Good morning. You have {count} items today:
{for each event}
- {time}: {title}
{/for}
Have a good one."`}
Voice Delivery Settings
{`# Voice reminder configuration
tts:
provider: elevenlabs # or google, azure
voice_id: nova
language: en
reminders:
- name: meeting_15min
trigger: "event.start - 15 minutes"
message_template: "meeting_15min"
channels:
- telegram_voice
- telegram_text
- name: meeting_1hour
trigger: "event.start - 1 hour"
message_template: "meeting_1hour"
channels:
- telegram_text
- name: daily_briefing
trigger: "08:00 daily"
message_template: "daily_morning"
channels:
- telegram_voice
- name: deadline_alert
trigger: "deadline - 1 day"
message_template: "deadline_reminder"
channels:
- telegram_voice
- telegram_text`}
Scheduling
Heartbeat Checks
{`// Heartbeat reminder check
const { getUpcomingEvents } = require('./calendar-sync');
const { sendVoiceMessage } = require('./telegram-bot');
const { generateTTS } = require('./tts-service');
async function checkReminders() {
const now = new Date();
const events = await getUpcomingEvents();
for (const event of events) {
const startTime = new Date(event.start.dateTime);
const diffMinutes = (startTime - now) / (1000 * 60);
if (diffMinutes > 14 && diffMinutes < 15) {
await sendMeetingReminder(event, '15min');
}
if (diffMinutes > 59 && diffMinutes < 60) {
await sendMeetingReminder(event, '1hour');
}
}
}
async function sendMeetingReminder(event, timing) {
const templates = {
'15min': \`Hey, your meeting starts in 15 minutes. Meeting: \${event.summary}. Time: \${formatTime(event.start.dateTime)}.\`,
'1hour': \`In 1 hour you have a meeting. \${event.summary}, starting at \${formatTime(event.start.dateTime)}.\`
};
const message = templates[timing];
const voiceBuffer = await generateTTS(message);
await sendVoiceMessage({
chat_id: process.env.ADMIN_CHAT_ID,
voice: voiceBuffer,
caption: message
});
console.log(\`✅ Sent \${timing} reminder: \${event.summary}\`);
}
// Check every 5 minutes
setInterval(checkReminders, 5 * 60 * 1000);
module.exports = { checkReminders };`}
Cron Schedule
{`# Send today's agenda at 8 AM
0 8 * * * cd /home/node/.openclaw/workspace && node scripts/daily-briefing.js
# Check upcoming meetings every 5 minutes
*/5 * * * * cd /home/node/.openclaw/workspace && node scripts/check-reminders.js
# Preview tomorrow's schedule at 9 PM
0 21 * * * cd /home/node/.openclaw/workspace && node scripts/tomorrow-preview.js`}
Advanced
Smart Reminders
{`# Context-aware reminders
## Travel
"Heads up — your airport departure is in 2 hours.
Flight: {flight_number}
Destination: {destination}
Local weather: {weather}
Passport and chargers are packed?"
## Customer meeting prep
"In 30 minutes you meet with {client_name}.
Last conversation summary:
{last_conversation_summary}
Open items:
{pending_items}
Relevant documents:
{relevant_documents}"`}
Layered Reminders
Important meeting (marked as high priority):
├── 1 day out: detailed prep reminder + relevant docs
├── 1 hour out: departure reminder + transit info
├── 15 min out: get-ready reminder
└── 1 min out: final check
Regular meeting:
└── 15 min out: standard reminder
Deadlines:
├── 3 days out: early-prep reminder
├── 1 day out: due-tomorrow reminder
└── Morning of: due-today reminder
Integrations
{`# Weather API
For offsite meetings, append:
"Rain tomorrow in San Francisco — bring an umbrella."
# Transit API
For external meetings, suggest:
"Estimated 30-minute drive — suggest leaving at 2:30."
# CRM
Before a customer meeting:
"This is your third meeting with XX Corp.
Last time you discussed {previous_topic}.
Today's focus is {meeting_goal}."`}
FAQ
The Voice Is Hard to Hear
- Pick a clearer voice model
- Adjust speech rate (0.9–1.1x works best)
- Send a text backup alongside
- Test in both quiet and noisy environments
Can I Change the Reminder Timing?
Yes — edit the config:
reminders:
- trigger: "event.start - 30 minutes" # now 30 minutes before
How Do I Skip a Reminder?
Tag the calendar event:
#no-reminder: skip entirely#silent: text only, no voice
Which Voice Providers Are Supported?
Currently:
- ElevenLabs (highest quality)
- Google Cloud Text-to-Speech
- Azure Cognitive Services
- System TTS (free, lower quality)
Summary
Calendar voice reminders keep important moments from slipping:
- Connect the calendar — Google / Outlook auto-sync
- Layered alerts — one day, one hour, fifteen minutes
- Voice notifications — louder than text, usable hands-free
- Smarter with context — weather, transit, CRM all inline