No calendar sharing. Any language. Any timezone. AI finds the slot.
The problem every product company faces:
A software company serves customers across 6 countries. Scheduling a cross-team meeting means each side must:
- Export their calendar availability manually
- Share it via email (violating calendar privacy)
- Someone laboriously cross-references timezones in a spreadsheet
- 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.
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
.icscalendar file in under 5 minutes, with participants responding naturally in their own language, 8 times out of 10.
| 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 |
| 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 |
| Admin — Create Meeting | Participant Response |
|---|---|
![]() |
![]() |
| Admin — Manage & Consolidate | Results & .ics Download |
|---|---|
![]() |
![]() |
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] │ │
│ └────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────┘
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 ] │
└─────────────────────────────────────────────────────────┘
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 │
└─────────────────────────────────────────────────────────┘
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 ] │
└─────────────────────────────────────────────────────────┘
- Python 3.12 (managed via
uv) - Nebius AI Studio API key
cd <projectfolder>\ContextCalEdit .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.venv\Scripts\python.exe -m streamlit run app.pyhttp://localhost:8501
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.
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
| 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 |
| 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 |
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



