Gmail Interview Scheduler: It Sends Nothing Alone

Abstract tech illustration: Gmail Interview Scheduler: It Sends Nothing Alone

An interview scheduler that sends emails by itself is a hiring risk, not an automation. If candidate availability is stuck in Gmail threads while you, your hiring manager, and the candidate trade times back and forth, you don't need an ATS migration — you need a narrow workflow that reads a labeled email, checks real calendar availability, drafts valid options, and waits for you to tap "Approve."

I've built this exact flow for clients who hire in small teams. Here's the full breakdown — the trigger, the extraction logic, the calendar check, the approval boundary, and the edge cases most agent demos skip entirely.

The One Rule That Keeps It Safe

An AI agent can prepare a scheduling decision. It cannot make a hiring decision, and it cannot send an email without a person confirming it. That single boundary is the entire safety model.

Interview scheduling looks small until you count the handoffs. A candidate replies with three possible windows. The founder has a client call. The hiring manager works in another timezone. Someone opens the calendar, checks availability, writes a polite reply, then discovers the slot disappeared before they pressed send. None of that helps you evaluate whether the candidate is right for the role — it's repetitive coordination work sitting between people and an actual conversation.

Small teams typically solve this in one of two bad ways:

  • Manual in Gmail. You lose attention across dozens of threads. A candidate waits two days for a reply that takes 90 seconds to write.
  • Buy an ATS. Another dashboard, another migration, another process your team has to remember. For a 4-person company hiring twice a quarter, that's overhead with no payoff.

Then they try ChatGPT. It writes a nice email, but it can't reliably see the right inbox, check the live calendar, or route the result to the person accountable for hitting send.

The useful middle ground is a small, controlled workflow built around the tools you already use:

Layer Tool Role
Intake Gmail Where candidates already email you
Source of truth Google Calendar Free/busy data, nothing invented
Approval surface Telegram One-tap confirm on your phone
Outbound Gmail (API) Reply in the original thread

No new dashboard. No data migration. No AI making hiring decisions.

The Trigger Is Deliberately Boring

The workflow does not scan every email in your company inbox and guess which messages matter. That's where most agent demos go wrong — they try to be clever about intent detection and end up processing a vendor invoice as a candidate reply.

The trigger is a Gmail label: Interview Scheduling.

A founder, recruiter, or assistant applies that label to an active candidate thread. Or you set up a Gmail filter rule that auto-applies it when an email arrives at a dedicated hiring address like hiring@yourcompany.com. The label is the instruction. Everything else flows from that explicit human action.

Here's the watcher logic in Python:

def check_labeled_threads(service, label_id, processed_thread_ids):
    """Poll Gmail for threads labeled 'Interview Scheduling'."""
    results = service.users().threads().list(
        userId='me',
        labelIds=[label_id]
    ).execute()

    threads = results.get('threads', [])
    new_threads = [
        t for t in threads
        if t['id'] not in processed_thread_ids
    ]
    return new_threads

This runs on a polling interval — every 60 seconds is fine for a small team. No webhooks, no push subscriptions, no fragile event-driven setup. A labeled thread appears, the watcher picks it up, and the workflow begins.

Extraction: Structured Facts, Not AI Summaries

When the workflow sees the labeled thread, it reads it and extracts only what it needs. Not a giant AI summary — a small, structured record.

Field Example Required
Candidate name Maya Yes
Role Operations Coordinator If known
Stated availability "Tuesday afternoon or Wednesday morning" Yes
Timezone "Berlin" / CET / Unknown Critical
Reply-to address maya@example.com Yes

That timezone field is the most important part of the extraction. An agent must not turn vague language into a confident booking. If the candidate says "Tuesday afternoon" without specifying their timezone, the workflow does not guess.

Here's the extraction prompt, kept deliberately narrow:

EXTRACTION_PROMPT = """You are extracting scheduling information from an email thread.

Read the thread and return a JSON object with these fields ONLY:
- candidate_name: string
- role: string or null
- availability_raw: the candidate's exact words about when they're free
- timezone: string or null (ONLY if explicitly stated)
- reply_to: the candidate's email address

Rules:
- Do NOT interpret or normalize availability. Keep the original words.
- If timezone is not explicitly mentioned, return null. Do NOT infer it.
- Do NOT suggest, score, or evaluate the candidate.
"""

The model's job is to parse, not to decide. If Maya wrote "I'm in Berlin," the extraction captures timezone: "Europe/Berlin". If she wrote "Tuesday afternoon or Wednesday morning" with no location, the extraction returns timezone: null — and the workflow stops right there.

Calendar Check: The Model Never Invents Slots

Once the workflow has structured data, it checks the calendar using free/busy data. It does not ask the model to invent slots. The calendar answers what is available, and the workflow applies rules you define.

For a first interview, a typical configuration looks like this:

SCHEDULING_RULES = {
    "interview_length_minutes": 30,
    "buffer_minutes": 15,
    "working_hours": {"start": "09:00", "end": "17:00"},
    "calendars_to_check": ["primary", "founder@company.com"],
    "max_options": 2,
    "lookahead_business_days": 5,
    "min_notice_hours": 24,
}

The workflow calls the Google Calendar FreeBusy API with those constraints and gets back concrete available windows. Then it filters by working hours, applies the buffer, and picks the first two slots that satisfy every rule.

def find_available_slots(calendar_service, rules, candidate_tz):
    """Query FreeBusy API and return valid interview slots."""
    time_min = datetime.now(timezone.utc) + timedelta(hours=rules["min_notice_hours"])
    time_max = time_min + timedelta(days=rules["lookahead_business_days"] + 4)

    freebusy = calendar_service.freebusy().query(body={
        "timeMin": time_min.isoformat(),
        "timeMax": time_max.isoformat(),
        "items": [{"id": cal} for cal in rules["calendars_to_check"]]
    }).execute()

    raw_busy = freebusy["calendars"]
    # Invert busy blocks to free blocks, filter by working hours,
    # apply buffer, convert to candidate timezone, return top N
    return filter_and_rank_slots(raw_busy, rules, candidate_tz)

If Maya gave a timezone — say, Europe/Berlin — the system converts the available slots to her local time before drafting the email. Tuesday at 2:00 PM CET. Wednesday at 10:30 AM CET. Clear, unambiguous options.

If she did not give a timezone, the workflow stops. It sends a Telegram message saying the candidate's timezone is missing and gives you a ready-to-send clarification email draft. That's not a failure of the workflow — that's the workflow refusing to guess.

Edge cases the workflow handles

  • Candidate gives a city name, not a timezone string. A simple lookup table maps "Berlin" → Europe/Berlin, "NYC" → America/New_York. If the city isn't in the table, it asks for clarification.
  • No slots available within the lookahead window. The workflow notifies you in Telegram with the next available date, so you can extend the window manually.
  • Candidate's timezone has a >12-hour offset from yours. The workflow flags it and converts to both timezones in the draft to prevent confusion.

The Approval Boundary: Three Buttons, Nothing Else

Before any draft reaches Gmail, it arrives in Telegram as one compact approval card. You see:

  • Candidate name and role
  • Detected timezone
  • The slots checked against the calendar
  • The proposed email reply in full

Then you have three actions: Approve, Edit, or Stop.

Approve runs one final calendar check — because someone could have booked the slot while you were reading the message. If the slot is still free, the workflow sends the reply in the original Gmail thread and removes the Interview Scheduling label. If the slot was taken, it goes back to find new options without sending anything.

Edit opens the draft for a human change before sending. Maybe you want to add a line about the interview format or mention who will be on the call.

Stop closes the task with no email sent. No explanation needed. The label is removed, and the thread is logged as processed.

One required approval before an interview email goes out. That is the whole safety model. The AI prepares. A human decides.

Here's what the Telegram approval card looks like in code:

def send_approval_card(bot, chat_id, extraction, slots, draft_email):
    """Send a compact approval card to Telegram."""
    message = (
        f"📋 *Interview Scheduling*\n\n"
        f"*Candidate:* {extraction['candidate_name']}\n"
        f"*Role:* {extraction['role'] or 'Not specified'}\n"
        f"*Timezone:* {extraction['timezone']}\n"
        f"*Available slots:*\n"
    )
    for slot in slots:
        message += f"  • {slot['day']} {slot['time']} ({slot['tz']})\n"

    message += f"\n*Draft reply:*\n```\n{draft_email}\n```"

    keyboard = InlineKeyboardMarkup([
        [
            InlineKeyboardButton("✅ Approve", callback_data="approve"),
            InlineKeyboardButton("✏️ Edit", callback_data="edit"),
            InlineKeyboardButton("🛑 Stop", callback_data="stop"),
        ]
    ])
    bot.send_message(chat_id, message, reply_markup=keyboard,
                     parse_mode='Markdown')

The End-to-End Flow With Real Timing

Here's what happens when a candidate replies, from label to sent email:

  1. You apply the label. Takes 2 seconds in Gmail.
  2. Watcher picks up the thread. Within 60 seconds, the polling cycle catches it.
  3. Extraction runs. 2-4 seconds for the model call. Returns a structured record.
  4. Calendar FreeBusy check. 1-2 seconds. Returns concrete available windows.
  5. Draft generation. 3-5 seconds. Model turns structured facts into a readable email.
  6. Telegram approval card arrives. You see everything in one message.
  7. You tap Approve. Final calendar re-check (1 second). If clear, Gmail sends the reply in the original thread.
  8. Label removed. Thread is logged as processed. Telegram gets a confirmation with the Gmail thread link.

Total wall-clock time from you applying the label to the candidate receiving options: under 2 minutes, with the bottleneck being your response time on the Telegram approval — not the system.

What the draft email actually looks like

Hi Maya,

Thanks for sharing your availability. We can offer either of these
times for a 30-minute first interview:

  • Tuesday, August 5 at 2:00 PM (Berlin time)
  • Wednesday, August 6 at 10:30 AM (Berlin time)

Please let us know which works best, and we'll send a calendar invite.

Best,
The Hiring Team

No AI flourish. No "I hope this email finds you well." No fabricated details. Structured facts, converted to a readable message, approved by a human before it leaves the building.

What This System Refuses to Do

The constraints are the feature, not the limitation.

  • It will not guess a timezone. Missing timezone = clarification email, not a booking.
  • It will not score the candidate. The model sees scheduling data, not CV evaluation criteria.
  • It will not decide urgency. No "this candidate seems urgent, let me prioritize." Priority is a human judgment.
  • It will not send without approval. There is no bypass, no auto-approve threshold, no "if I don't respond in 4 hours, send it anyway."
  • It will not scan unrelated emails. The label is an explicit instruction. No label, no processing.

This is what makes the workflow safe to run unsupervised in the background. It's not autonomous — it's automated up to a hard stop, every single time.

How this fits into what I build at bizflowai.io

At bizflowai.io, I build these narrow, approval-gated workflows for solopreneurs and small teams who are drowning in coordination tasks — email triage, lead follow-up, invoicing reminders, interview scheduling. The pattern is always the same: Gmail or another existing tool stays the intake channel, an AI agent does the extraction and preparation work, Telegram or Slack becomes the approval surface, and nothing goes out without a human tapping a button. The interview scheduler above is one module in a system I've shipped across client operations, running daily on a practical home-server setup with WSL Ubuntu — no enterprise infrastructure required.


Want more like this?

I publish practical AI automation, GenAI engineering, and faceless content workflows on YouTube every week.

Subscribe to bizflowai.io on YouTube — never miss a new tutorial.

Planning an AI automation project or need a second opinion on your architecture?

Connect with me on LinkedIn — Lazar Milicevic, GenAI Engineer & bizflowai.io Founder.

Visit bizflowai.io for our services, case studies, and AI consulting.

Frequently asked questions

What is AI-assisted interview scheduling?

AI-assisted interview scheduling is a workflow where artificial intelligence reads an email thread, extracts candidate details like name, role, and availability, checks calendar free-busy data for open slots, and drafts a scheduling email. The AI prepares the decision but cannot send the email without a human approving it. This eliminates manual coordination work like checking timezones, cross-referencing calendars, and writing polite replies, freeing the team to focus on evaluating the candidate.

How do I set up an AI interview scheduling workflow?

Create a Gmail label called Interview Scheduling and apply it to active candidate threads. When the workflow sees the label, it extracts the candidate name, role, availability, and timezone. It checks your calendar using rules you define, such as interview length, buffer time, and working hours. It then drafts an email with available slots and sends it to you via Telegram as an approval card where you choose Approve, Edit, or Stop before it sends.

Why does human approval matter for AI scheduling workflows?

Human approval matters because AI should not be trusted to send emails or make decisions without oversight. The scheduling workflow deliberately sends a Telegram approval card showing the candidate name, detected timezone, checked slots, and proposed email before anything reaches Gmail. A person must choose Approve, Edit, or Stop. On approval, the system runs a final calendar check to confirm the slot is still free, preventing double-bookings caused by delays during the review process.

When should I use an AI scheduling workflow vs a full ATS?

Use an AI scheduling workflow when you want to automate repetitive coordination without adopting a new dashboard or migration. An ATS adds another tool your team must learn and maintain, while manual scheduling in Gmail wastes attention across dozens of threads. The workflow approach keeps Gmail as your intake channel, your calendar as the source of truth, and Telegram as the approval surface, giving small teams automation without changing their existing process.

How does the workflow handle a missing candidate timezone?

If a candidate does not include their timezone, the workflow stops and refuses to guess. It sends a Telegram message alerting you that the timezone is missing and provides a ready-to-send clarification email for the candidate. This design prevents the AI from turning vague language into a confident booking, ensuring no incorrect meeting times are proposed due to an assumption about the candidate's location.