Integrations
Google Calendar — Commitments, Not Just Events
Sync Google Calendar to power commitment graph, daily briefing, and “What should I do now?” — with OAuth, linking, and planning logic explained for beginners.
Calendar as Commitment Intelligence
Beginner: Why “Commitment”
Your calendar is promises to people. DLRS treats each event as a commitment: Who, What, When, What tasks depend on it, What files you need. Not just “Meeting 4pm”.
UI: /w/[workspace]/calendar (month/week/day + Today). Backend: calendar_events per workspace, synced via Google Calendar API.
OAuth & Sync Flow
Setup
Same as Gmail/Drive. Redirect:
http://localhost:3000/api/integrations/calendar/callback
Scope: .../auth/calendar.readonly
Env: GOOGLE_CALENDAR_CLIENT_ID, SECRET_ENCRYPTION_KEYConnect in Settings → Integrations → Calendar.
Initial Sync
POST /api/integrations/calendar/sync
- google.calendar.events.list(calendarId: primary, maxResults: 250, timeMin: now, timeMax: +30d)
- For each event: calendar_events {
id, workspace_id, external_id, title, description,
starts_at, ends_at, all_day, attendees: json, location, status
}Incremental (Job)
Job: calendar_sync every 15m
- Use syncToken (Google's incremental token) → only new/updated/deleted
- Update or create rows, delete removed
- Trigger: calendar.event_created → notify if linked to urgent taskCommitment Graph in Action
Event: "Website Redesign — Client Call" 2025-12-03 16:00, attendees: [email protected], description: "Review pricing.pdf"
Linked automatically:
- Project: Website Redesign (title match)
- Client: Acme (attendee email [email protected] → clients.contact_email)
- Tasks: 3 outstanding for that project (Update pricing, Review copy, SEO)
- Files: pricing.pdf in Drive
- Action: Assistant 1h before: "You have 3 tasks for this client. Review pricing.pdf before call."
Keywords: commitment graph = event ↔ project ↔ task ↔ file ↔ personDaily Briefing & Planning
Cron: 0 8 * * 1-5 (weekdays 8am) → Reminder Agent:
"Good morning!
Today:
🔴 Due today: GB reel (export pending) — 2 tasks
🟠 Due soon: Tanniaqua post (Friday)
🟡 Waiting: GB — waiting for photos (3 days)
🟢 Completed: 2 tasks yesterday
Calendar: 2 events (10am standup, 4pm client call)
What's your focus today?"
Generation: lib/agents/orchestrator + lib/domain/planning
- Queries tasks where due_date = today AND calendar_events today
- No LLM math, just counts and priority sortNext-Best-Action
Ask “What should I do now?” in Assistant:
Scoring (same as Task priority + time):
- Due today + assets available + 45m estimate + no blocks → score 88
- Calendar: you have 2h free before 4pm call → fits 45m task
Answer: "Do GB Reel now (45m, due today, assets ready, no dependencies). Why? Client waiting, 2h free."
Code: lib/domain/planning.ts → nextBestAction(workspaceId)Tables & Keywords
calendar_events {
id, workspace_id, external_id (Google's id), title, description,
starts_at, ends_at, all_day, attendees: jsonb, location, status, created_at
}
Indexes: workspace_id, starts_at (for Today queries)
Keywords:
- external_id: Google's id, used for delta sync
- syncToken: Google's incremental token, stored per workspace
- commitment: event as promise, not just time block
- attendees: array of emails, linked to clients