Extract calendar events, deadlines, action items, and follow-ups from emails. Works with any calendar provider (Google, Outlook, Apple, Notion, etc.). No external dependencies — pure agent intelligence. Use when the user forwards an email, asks to check inbox for events, or wants to extract structured scheduling data from any text.
Turn emails into structured calendar events with zero missed deadlines.
When you receive an email (forwarded, pasted, or from inbox):
Scan every email for ALL of these categories:
| Category | Signals | Priority |
|---|
| Hard Events | "meeting at", "call on", "event on", specific date+time | 🔴 High |
| Deadlines | "due by", "submit before", "RSVP by", "register by", "expires" | 🔴 High |
| Soft Events | "sometime next week", "let's meet soon", "planning for March" | 🟡 Medium |
| Recurring | "every Monday", "weekly", "monthly", "standing meeting" | 🟡 Medium |
| Action Items | "please review", "can you send", "follow up on", "action required" | 🟡 Medium |
| Travel/Logistics | Flight numbers, hotel confirmations, check-in times, gate info | 🔴 High |
| Implicit Deadlines | Event is Feb 20 → ticket deadline is likely 1-2 weeks before | 🟡 Medium |
For each item found, extract:
- title: "Descriptive name (max 80 chars)"
type: event | deadline | action_item | travel | recurring
date: "YYYY-MM-DD"
day_of_week: "Monday" # Always include for verification
time_start: "14:00" # 24h format, default 09:00 if unclear
time_end: "15:00" # Default: start + 1h for meetings, all-day for deadlines
timezone: "America/New_York" # Extract from email headers or content
is_all_day: false
is_multi_day: false # If true, include end_date
end_date: null
recurrence: null # "weekly" | "biweekly" | "monthly" | "MWF" | custom RRULE
location: null # Physical address or video link
url: null # Registration link, event page, or action URL
attendees: [] # Names/emails mentioned
confidence: high | medium | low
source_quote: "exact text from email that indicates this event"
notes: "any context the user should know"
deadline_action: null # "RSVP" | "register" | "buy tickets" | "submit"
deadline_url: null # Direct link to take action
reminder_minutes: 30 # Suggested reminder (15 for calls, 60 for travel, 1440 for deadlines)
| Confidence | Criteria |
|---|---|
| High | Explicit date + time + clear event type. E.g. "Meeting on Feb 15 at 2pm" |
| Medium | Date but no time, or time but approximate date. E.g. "next Tuesday afternoon" |
| Low | Vague reference. E.g. "we should catch up soon", "sometime in March" |
Before extracting, classify the email:
| Email Type | How to Handle |
|---|---|
| Calendar notification (from [email protected], outlook, etc.) | SKIP — these are responses to existing events |
| Newsletter/marketing | Extract only if contains relevant event dates |
| Personal/work email | Full extraction |
| Travel confirmation | Extract ALL logistics: flights, hotels, car rentals, check-ins |
| Meeting invite (ICS attachment or structured invite) | Extract directly, high confidence |
| Thread/reply | Only extract NEW events, not ones from quoted text |
| Forwarded email | Process the forwarded content, note original sender |
Always present extracted items in this format:
📧 From: [sender] | Subject: [subject] | Date: [received date]
Found [N] calendar items:
1. 🔴 **Team Standup** — Mon Feb 17, 9:00-9:30 AM EST
📍 Zoom (link in email) | 👥 Alice, Bob, Charlie
🔁 Recurring: Every weekday
✅ Confidence: High
2. 🔴 **Project Deadline: Q1 Report** — Fri Feb 28, EOD
⚠️ ACTION REQUIRED: Submit report
🔗 [Submission portal](url)
⏰ Suggested reminder: 3 days before
✅ Confidence: High
3. 🟡 **Team Lunch** — "sometime next week"
📍 TBD
⚠️ Confidence: Medium — date needs confirmation
---
Reply with numbers to create (e.g. "1, 2"), "all", or "none".
Type "edit 3" to modify before creating.
After user confirms, create events using their calendar tool:
gog or API)gog calendar create \
--title "Event Title" \
--start "2026-02-17T09:00:00-05:00" \
--end "2026-02-17T10:00:00-05:00" \
--description "Extracted from email: [subject]" \
--location "Zoom link or address"
osascript)osascript -e 'tell application "Calendar"
tell calendar "Work"
make new event with properties {summary:"Event Title", start date:date "Monday, February 17, 2026 at 9:00:00 AM", end date:date "Monday, February 17, 2026 at 10:00:00 AM", description:"Extracted from email", location:"Zoom"}
end tell
end tell'
BEGIN:VCALENDAR
VERSION:2.0
BEGIN:VEVENT
DTSTART:20260217T090000
DTEND:20260217T100000
SUMMARY:Event Title
DESCRIPTION:Extracted from email
LOCATION:Zoom link
END:VEVENT
END:VCALENDAR
Before creating any event, check for duplicates:
// memory/email-calendar-log.json
{
"created_events": [
{
"email_id": "msg-123",
"email_subject": "Team Offsite",
"event_title": "Team Offsite",
"event_date": "2026-02-17",
"calendar_event_id": "cal-456",
"created_at": "2026-02-13T10:00:00Z"
}
]
}
| Pattern | Example | Action |
|---|---|---|
| RSVP deadline | "RSVP by Feb 10" | Create reminder 3 days before |
| Registration | "Register by March 1" | Create reminder 1 week before |
| Early bird | "Early bird ends Feb 15" | Create reminder 2 days before |
| Ticket sales | "Tickets on sale until..." | Create reminder + calendar event |
| Submission | "Submit proposal by..." | Create reminder 3 days before |
| Expiration | "Offer expires..." | Create reminder 1 day before |
Travel confirmations get special treatment:
When scanning an inbox for events:
📬 Inbox Scan: 47 unread → 12 with calendar items → 18 events found
THIS WEEK (Feb 13-19):
1. 🔴 Sprint Review — Thu Feb 13, 3:00 PM
2. 🔴 1:1 with Manager — Fri Feb 14, 10:00 AM
...
NEXT WEEK (Feb 20-26):
5. 🟡 Team Lunch — date TBD (mentioned in 2 emails)
...
DEADLINES:
⚠️ Q1 Report — Due Feb 28 (15 days) → [Submit here](url)
⚠️ Conference RSVP — Due Feb 20 (7 days) → [RSVP](url)
| Situation | How to Handle |
|---|---|
| Multiple timezones in one email | Extract each event in its stated timezone, convert to user's TZ for display |
| "TBD" or "TBA" times | Create all-day event, flag for follow-up |
| Cancelled events | Check if already in calendar → offer to delete |
| Rescheduled events | Find original → offer to update (not create new) |
| Recurring with exceptions | Note specific exception dates in description |
| Date ambiguity (02/03 = Feb 3 or Mar 2?) | Use email's locale/origin for MM/DD vs DD/MM, ask if unclear |
| Events in quoted/forwarded text | Only process if user explicitly forwarded it |
| Attachments with .ics files | Parse ICS directly — highest confidence source |
| "Save the date" emails | Create tentative event, mark as placeholder |
| Conference with multiple sessions | Extract all sessions as separate events with shared description |
Track user preferences across sessions:
# memory/email-calendar-prefs.yaml
default_timezone: "America/New_York"
default_calendar: "Work"
default_reminder_minutes: 30
auto_create_patterns:
- "standup"
- "1:1"
ignore_patterns:
- "newsletter"
- "marketing"
preferred_format: "12h" # or "24h"
travel_reminder_hours: 3
Update preferences when user corrects you or states a preference.