Skip to content

Latest commit

 

History

History
345 lines (269 loc) · 17.4 KB

README.md

File metadata and controls

345 lines (269 loc) · 17.4 KB

📅 ContextCal — Agentic Meeting Scheduler

No calendar sharing. Any language. Any timezone. AI finds the slot.

Python Streamlit LangGraph Nebius AI License


Why ContextCal?

The problem every product company faces:

A software company serves customers across 6 countries. Scheduling a cross-team meeting means each side must:

  1. Export their calendar availability manually
  2. Share it via email (violating calendar privacy)
  3. Someone laboriously cross-references timezones in a spreadsheet
  4. Multiple back-and-forth rounds as people reply "actually Tuesday doesn't work for me"

This costs 2–3 hours per meeting and still produces errors.

ContextCal eliminates this entirely. The organizer sends a link. Participants reply in their own words — in Hindi, French, English, Chinese, whatever — and the AI agent handles the rest.


The Primer

My agent helps a product company organizer schedule a multi-party meeting in a Streamlit web app (configurable to email/Slack/API), replacing the 2–3 hours of back-and-forth emails, calendar exports, and manual timezone math it takes to coordinate across customers in different countries today. It parses free-text availability in any language, normalizes all timezones to UTC, and computes meeting overlap on its own using 4 tools (LLM parser, timezone normalizer, interval overlap engine, iCal generator), hands off to a human when the organizer reviews the best slots before any calendar action is taken, and I'll know it works when an organizer can go from "need to schedule a 6-person cross-timezone meeting" to a downloadable .ics calendar file in under 5 minutes, with participants responding naturally in their own language, 8 times out of 10.


Key Features

Feature Detail
🌍 Multilingual parsing English, Hinglish, French, Chinese, Spanish, any language — no translation step
🔒 Zero calendar access No OAuth, no Google Calendar, no Outlook — participants share words, not data
🤖 LangGraph agent 5-node stateful graph: parse → normalize → overlap → summarize → iCal
⏱️ Deterministic math Python interval math for overlap — LLM never touches time calculations
🎙️ Voice input faster-whisper (local CPU) for spoken availability responses
📅 iCal export RFC 5545 compliant .ics file with VTIMEZONE, works with all calendar clients
🔄 Human-in-the-loop Organizer confirms before any invite is sent — agent never acts autonomously on writes
📧 Configurable surface Streamlit (demo) · Email parser · Slack bot · REST API — same agent core

Workflow

Workflow Diagram


Architecture

Architecture Diagram


Component Details

Component File Role
Streamlit App app.py Single-page UI with query-param routing (?token, ?view)
LangGraph Graph agents/graph.py 5-node stateful agent with MemorySaver checkpointing and error routing
LLM Parser agents/parser.py Calls Nebius AI (Llama-3.3-70B) to extract structured JSON from free-text
TZ Normalizer agents/normalizer.py Pure Python: resolves weekday names → dates, converts all windows to UTC
Overlap Engine agents/overlap.py Pure Python: event-sweep interval intersection across N participants
Summarizer agents/summarizer.py Calls Nebius AI to generate human-friendly meeting announcement
iCal Generator tools/ical_generator.py Produces RFC 5545 .ics with VTIMEZONE blocks
Whisper STT tools/whisper_stt.py faster-whisper (local, CPU, base model) — voice → text
Database db/database.py SQLite: sessions, participants (raw + parsed), consolidated results
Token Gen utils/token_gen.py SHA-256 secure participant tokens + UUID session IDs

Screenshots

Admin — Create Meeting Participant Response
Admin Create Participant
Admin — Manage & Consolidate Results & .ics Download
Manage Sessions Results

Pages

Page 1 — Admin: Create Meeting

The organizer sets the meeting title, date range, and participant names. One click generates unique secure links for each participant.

┌─────────────────────────────────────────────────────────┐
│  📅 ContextCal                          [hero banner]   │
│  Agentic Meeting Scheduler                               │
│  🌍 Any Language  🔒 No Calendar  🤖 LangGraph  🎙️ Voice │
├─────────────────────────────────────────────────────────┤
│  [ Create Meeting ] [ Manage Sessions ]                  │
│                                                          │
│  App Base URL: http://localhost:8501                     │
│                                                          │
│  Meeting Title: [Q3 Planning Sync        ]               │
│  Date Range:   [2026-06-17] → [2026-06-23]              │
│  Participants: 6                                         │
│  Name 1: Alice Chen    Name 2: Raj Sharma  ...          │
│                                                          │
│  ┌────────────────────────────────────────────────────┐ │
│  │ ✅ Session Created — Q3 Planning Sync              │ │
│  │ Session ID: a1b2c3d4-...                           │ │
│  │                                                    │ │
│  │ 👥 Participant Links                               │ │
│  │ Alice Chen    [🔗 Open response page]  token:...   │ │
│  │ Raj Sharma    [🔗 Open response page]  token:...   │ │
│  │ Sophie Dubois [🔗 Open response page]  token:...   │ │
│  │ ...                                                │ │
│  │ [📊 Open Results Page]                             │ │
│  └────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────┘

Page 2 — Participant Response

Each participant opens their unique link. Text is pre-populated for the demo. They can type or speak their availability in any language.

┌─────────────────────────────────────────────────────────┐
│  📅 Q3 Planning Sync                    [hero banner]   │
│  Availability window: 2026-06-17 to 2026-06-23          │
│  🔒 No calendar access  🌍 Any language  🎙️ Voice input  │
├─────────────────────────────────────────────────────────┤
│  Hi Raj Sharma 👋                                        │
│  Tell us when you're available...                        │
│                                                          │
│  ┌──────────────────────────────┐  ┌──────────────────┐ │
│  │ Wednesday raat ko 9:30 baje  │  │   🎙️ Or speak it  │ │
│  │ se 11:30 baje tak available  │  │   [Record audio]  │ │
│  │ hun. Thursday bhi chal...    │  │                   │ │
│  └──────────────────────────────┘  └──────────────────┘ │
│                                                          │
│  🔒 Privacy note: only your text is stored               │
│                                                          │
│           [ Submit Availability ]                        │
└─────────────────────────────────────────────────────────┘

Page 3 — Admin: Manage & Consolidate

After responses come in, the organizer triggers the LangGraph agent. The step log shows each node executing in real time.

┌─────────────────────────────────────────────────────────┐
│  [ Create Meeting ] [ Manage Sessions ]                  │
│                                                          │
│  Session ID: [a1b2c3d4-...              ]                │
│                                                          │
│  Title: Q3 Planning Sync   Status: open                 │
│  Responses: ████████████░░ 5 / 6                        │
│                                                          │
│  ✅ Alice Chen     [🔗 Open link]                        │
│  ✅ Raj Sharma     [🔗 Open link]                        │
│  ✅ Sophie Dubois  [🔗 Open link]                        │
│  ✅ James Walker   [🔗 Open link]                        │
│  ✅ Priya Nair     [🔗 Open link]                        │
│  ⏳ Chen Wei       [🔗 Open link]                        │
│                                                          │
│  [Run Consolidation]       [View Results]                │
│                                                          │
│  ▼ Agent Step Log                                        │
│  Parsing participant responses with LLM...               │
│    ✓ Parsed: Alice Chen                                  │
│    ✓ Parsed: Raj Sharma (Hinglish → JSON)                │
│    ✓ Parsed: Sophie Dubois (French → JSON)               │
│  Normalizing timezones to UTC...                         │
│  Computing availability overlap (deterministic math)...  │
│    ✓ Full overlap found: 2 slot(s)                       │
│  Generating summary...   ✓ iCal generated               │
└─────────────────────────────────────────────────────────┘

Page 4 — Results

Shows the overlap matrix in multiple timezones, the AI-generated summary, parsed JSON per participant, and the .ics download button.

┌─────────────────────────────────────────────────────────┐
│  📊 Q3 Planning Sync              [5/6 responded ████░] │
├─────────────────────────────────────────────────────────┤
│  AI Summary                                             │
│  "Great news! A common slot was found for 5 of your 6  │
│   participants on Wednesday..."                          │
│                                                          │
│  ✅ Full Overlap Slots                                   │
│  ┌──────────────────────────────────────────────────┐   │
│  │ Slot 1: Wednesday Jun 17 · 4:00 PM – 6:00 PM UTC │   │
│  │ PST: 9:00 AM – 11:00 AM                          │   │
│  │ IST: 9:30 PM – 11:30 PM                          │   │
│  │ CET: 5:00 PM – 7:00 PM                           │   │
│  │ Duration: 120 min  Coverage: 83%                  │   │
│  │ ✓ Alice  ✓ Raj  ✓ Sophie  ✓ James  ✓ Priya        │   │
│  └──────────────────────────────────────────────────┘   │
│                                                          │
│  ▼ Participant Parsed Responses (expandable)            │
│                                                          │
│           [ ⬇ Download .ics Calendar Invite ]           │
└─────────────────────────────────────────────────────────┘

Quick Start

Prerequisites

1. Clone & enter the project

cd <projectfolder>\ContextCal

2. Add your Nebius API key

Edit .env:

NEBIUS_API_KEY=your_key_here
NEBIUS_BASE_URL=https://api.studio.nebius.ai/v1/
NEBIUS_PARSE_MODEL=meta-llama/Llama-3.3-70B-Instruct
NEBIUS_SUMMARY_MODEL=meta-llama/Llama-3.3-70B-Instruct
DB_PATH=contextcal.db

3. Run (Windows — no venv activation needed)

.venv\Scripts\python.exe -m streamlit run app.py

4. Open in browser

http://localhost:8501

Extending to Email / Slack / API

The agent core (agents/graph.py) is surface-agnostic. Streamlit is the demo UI. To add email parsing:

# email_adapter.py
from agents.graph import run_consolidation
from agents.parser import parse_availability

def handle_email_reply(sender_email, body_text, session_id):
    parsed = parse_availability(body_text, date_start, date_end)
    # store to DB, run consolidation when all replied
    ...

The same run_consolidation() call works unchanged regardless of how responses arrive.


Project Structure

ContextCal/
├── app.py                    ← Streamlit UI (single file, query-param routing)
├── requirements.txt
├── .env                      ← API keys (not committed)
├── blog.html                 ← Standalone blog post (dark/light mode)
├── assets/
│   ├── workflow.svg          ← Agent workflow diagram
│   ├── architecture.svg      ← System architecture diagram
│   ├── react_flow.svg        ← ReAct cycle internals with sample data
│   └── screenshots/          ← App screenshots (Playwright-generated)
├── agents/
│   ├── graph.py              ← LangGraph: 5-node stateful agent
│   ├── parser.py             ← Nebius LLM → structured JSON
│   ├── normalizer.py         ← Python timezone normalization
│   ├── overlap.py            ← Python interval intersection math
│   └── summarizer.py         ← Nebius LLM → friendly summary
├── tools/
│   ├── ical_generator.py     ← RFC 5545 .ics file generation
│   └── whisper_stt.py        ← faster-whisper voice transcription
├── db/
│   └── database.py           ← SQLite: sessions, participants, results
└── utils/
    └── token_gen.py          ← Secure token + session ID generation

Tech Stack

Layer Technology Why
Frontend Streamlit 1.58 Zero-infra, multi-page via query params, fast iteration
Agent framework LangGraph 1.2 Typed state, conditional routing, MemorySaver checkpointing
LLM — Parse Llama-3.3-70B via Nebius Strong multilingual instruction following, clean JSON output
LLM — Summary Llama-3.3-70B via Nebius Natural language generation, context-aware
Voice STT faster-whisper (local) No API cost, CPU inference, multilingual Whisper model
Timezone math Python pytz + datetime Deterministic — LLMs must not compute time math
Calendar output icalendar library RFC 5545 compliant, VTIMEZONE support
Persistence SQLite Zero-infra persistent state, survives page refreshes
Package manager uv + Python 3.12 Fast dependency resolution, reproducible installs

Why Not Just Use Doodle / When2meet?

Doodle / When2meet ContextCal
Input method Click a grid Free text, any language
Multilingual ❌ English UI only ✅ Hindi, French, Chinese, etc.
Calendar access Sometimes required ❌ Never
Time format Structured slots "Wednesday raat ko 9 baje"
Voice input ❌ ✅ Whisper STT
AI parsing ❌ ✅ LLM extracts intent
Output Link to poll Downloadable .ics
Configurable surface ❌ ✅ Email · Slack · API

Blog Post

A detailed blog post covering the product fit, implementation details, and architectural decisions is available at blog.


Built with LangGraph · Nebius AI · Streamlit · faster-whisper