4 Files Into One Human-Reviewed Interview Brief

Abstract tech illustration: 4 Files Into One Human-Reviewed Interview Brief

Your hiring manager opens the CV in one tab, hunts through Gmail for the application thread in another, digs up the role scorecard in a shared drive, and joins the call three minutes late still not sure what to ask. That is 15 minutes of tab-switching before a 30-minute interview. This post walks through the exact bot I build for clients that turns those four scattered inputs into a single evidence-linked briefing packet — without letting the model touch a hiring decision.

The one rule that keeps this safe: the bot preps humans, it does not judge them

This bot prepares the interviewer. It does not score, rank, reject, advance, or message the candidate. That boundary is the entire reason the workflow is worth building first. Every automation vendor demo I have seen starts at the riskiest step — resume scoring — which is exactly where bias, EEOC exposure, and bad candidate experience live. Flip the order. Automate the boring information-gathering that your hiring manager is doing badly at 8:57 AM, and leave the judgment where it belongs.

Practically, that means the bot has three hard "no" rules baked into the system prompt and the workflow logic itself:

  • No numeric fit score, no "recommend hire / no hire" language, no ranked comparison across candidates.
  • No candidate-facing output. The bot writes to the interviewer only.
  • No stage changes in the ATS. If you use Greenhouse, Ashby, or a spreadsheet, the bot reads. A human writes.

If you skip this framing, the same code becomes a compliance problem the moment a rejected candidate asks how the decision was made.

The 4 inputs, and the boring identifier problem that breaks most builds

The four inputs are: calendar event, candidate CV, application form response, and role scorecard. The one people skip is the scorecard, and without it the model produces a fluent summary that has nothing to do with what you are hiring for.

Keep the scorecard to five fields so a hiring manager will actually maintain it:

Field Example (customer support role)
Role title Senior Support Specialist, SaaS
Must-have Fluent written English, 2+ yrs ticketing (Zendesk/Intercom), B2B SaaS exposure
Nice-to-have SQL basics, technical writing samples
Concerns to verify US timezone overlap, availability start date, examples of angry-customer handling
Interview areas Written comms sample, live triage exercise, escalation judgment

The second boring problem: one clean identifier per candidate. Email is the only reliable one. Names collide, LinkedIn URLs get edited, phone numbers are missing half the time. If your calendar event only has a name, matching becomes a guessing game the moment you interview two people named David Chen in the same quarter.

The fix is a title convention, not code:

Interview — Jane Doe — jane.doe@gmail.com — Support Specialist

Or put the email in the event description field. Not glamorous. But every reliable automation I have shipped starts with a boring, consistent input format.

The trigger, the extractor, and the "do not guess" rule

The trigger is a scheduled job that runs every 10 minutes and looks for calendar events with an Interview label starting in the next 30-60 minutes. When it finds one, it pulls: candidate email, candidate name, interviewer name, role title, event start time, meeting link.

If any critical field is missing, the bot does not guess. It sends the interviewer a short exception notice and stops.

# pseudo-code, n8n / Make / Python all map to this shape
def handle_event(event):
    ctx = extract_calendar_fields(event)
    missing = [k for k in ("candidate_email", "role_title", "interviewer") if not ctx.get(k)]
    if missing:
        notify_interviewer(
            to=ctx.get("interviewer_email"),
            subject=f"Briefing skipped: {event['summary']}",
            body=f"Missing fields: {', '.join(missing)}. "
                 f"Fix the event and I will regenerate on next run.\n{event['htmlLink']}"
        )
        return
    build_briefing(ctx)

Silent guessing is how automations create embarrassing failures — the wrong candidate summary sent to the wrong interviewer, or a briefing about "David Chen" that mixes two people's CVs. An exception notice takes 20 seconds for a human to fix. A hallucinated brief takes a week of trust to rebuild.

Fields the trigger must always confirm before proceeding

  • candidate_email — the join key for every downstream lookup
  • role_title — required to load the correct scorecard
  • interviewer — required to send the brief to the right person
  • event_start — required to schedule delivery 30 min before

Gmail search, CV extraction, and keeping the payload small

Once the trigger has the candidate email, the bot searches Gmail with a narrow query. Broad searches ("everything from this person, ever") are how you end up with a 40,000-token context window full of scheduling back-and-forth.

from:jane.doe@gmail.com OR to:jane.doe@gmail.com
label:Applications OR label:Recruiting OR label:Interviews
newer_than:120d
has:attachment OR subject:(application OR interview OR resume OR cv)

Then apply three filters:

  1. Newest CV wins. If the candidate sent three versions, use the most recent. List older files as source links, do not blend them into the extracted text.
  2. Extract with page references. For PDFs, keep page_number metadata alongside every text chunk. pdfplumber or pypdf both work. This is what lets the final brief cite "CV page 2" instead of a vague summary.
  3. Pull only the fields the interviewer needs from the application form. Work history, key open-ended answers, portfolio links, stated availability. Skip the "how did you hear about us" field.
import pdfplumber

def extract_cv(path):
    pages = []
    with pdfplumber.open(path) as pdf:
        for i, page in enumerate(pdf.pages, start=1):
            text = page.extract_text() or ""
            pages.append({"page": i, "text": text.strip()})
    return pages  # keep structure, do not join into one blob

The payload going into the model should be small and labeled. For a typical candidate this is roughly:

Source Size
Calendar event ~200 tokens
CV (extracted, page-labeled) 1,500-3,000 tokens
Application form (filtered) 400-800 tokens
Selected email threads (max 3) 500-1,500 tokens
Role scorecard 200-400 tokens
Total input ~3,000-6,000 tokens

At current Claude Sonnet or GPT-4-class pricing, one briefing runs about $0.03-$0.08. Dumping every email would push that past $0.50 per brief and would make the citations unverifiable.

The prompt: labels, citations, and no opinions

Every input chunk gets a source label before it hits the model. This is the single change that separates a useful brief from an AI-generated opinion.

[SOURCE: cv_page_2] "Led a support team of 4 at Acme SaaS, 2022-2024..."
[SOURCE: application_q3_dated_2026-03-04] "Available to start within 3 weeks..."
[SOURCE: email_thread_2026-03-06] "Confirmed she is US Pacific time..."
[SOURCE: scorecard_v1.3_must_have] "US timezone overlap required"

The system prompt then enforces the boundary:

You are preparing a hiring manager for an interview. You do NOT
evaluate the candidate. You do NOT recommend hire/no-hire. You do
NOT produce a score.

For every claim you make, cite the source label in brackets, e.g.
[cv_page_2]. If a scorecard requirement has no matching evidence in
the sources, say "no evidence found in provided sources" — do not
infer, do not fill in from general knowledge.

Output sections (in this order):
1. Snapshot (3 bullets, facts only)
2. Scorecard coverage (each must-have + nice-to-have, with evidence
   or "no evidence found")
3. Concerns to verify (from scorecard, phrased as questions)
4. Suggested questions (3-5, grounded in gaps or claims worth probing)
5. Source index (list of files/links used)

That "no evidence found" clause is the anti-hallucination lever. Without it, the model will happily write "Jane has strong SQL skills" because SQL is on the scorecard, even though nothing in her CV mentions it.

Delivery, review, and what a good brief looks like at 8:30 AM

The brief lands in the interviewer's inbox (or Slack DM) 30 minutes before the call, with the meeting link at the top and the source index at the bottom. Every claim has a bracketed citation the interviewer can click.

A real one looks roughly like this:

INTERVIEW BRIEFING — Jane Doe — Senior Support Specialist
Interview: 2026-04-15 09:00 PT with Marcus | [Join call]

SNAPSHOT
• 2 yrs support lead at Acme SaaS (B2B) [cv_page_2]
• Available in 3 weeks, US Pacific [application_q3, email_2026-03-06]
• Portfolio: writing samples + one incident postmortem [application_q7]

SCORECARD COVERAGE
✓ Ticketing 2+ yrs — Zendesk at Acme [cv_page_2]
✓ B2B SaaS exposure — Acme is B2B [cv_page_1]
✓ US timezone — confirmed Pacific [email_2026-03-06]
? Angry-customer example — no evidence found in provided sources

CONCERNS TO VERIFY
• Ask for a specific escalation she handled end-to-end
• Confirm start date given current notice period

SUGGESTED QUESTIONS
1. Walk me through the incident in your postmortem — what did you own?
2. Tell me about a ticket you escalated. What was the trigger?
[...]

The interviewer skims for 3 minutes, spots the "no evidence found" gap, and knows exactly what to probe. That is the whole product.

What breaks in the first two weeks of running this

  • Calendar events without the email in title or description — fix the convention, do not patch the code.
  • Gmail label drift ("Recruiting-2026" vs "Recruiting") — normalize labels once, monthly.
  • CVs sent as image-only PDFs — add an OCR fallback (Tesseract or a vision model) and flag the brief as "OCR used, verify accuracy."
  • Interviewer forwards the brief to the candidate by accident — put a visible INTERNAL — DO NOT FORWARD header on every brief.

Why bizflowai.io helps with this

This is exactly the class of workflow I ship for small teams at bizflowai.io — the boring, high-leverage pre-work that a human still owns the decision on. For hiring specifically, that means the calendar-triggered briefing bot above, plus adjacent pieces like a scorecard template your managers will actually fill in, exception routing when inputs are missing, and the source-labeled prompt structure that keeps the model from inventing evidence. Nothing in the stack scores or rejects candidates. Every decision stays with your hiring manager, and they walk into the call already prepped.


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 an AI interview briefing bot?

An AI interview briefing bot is an automation that prepares a hiring manager before an interview by pulling context from calendar events, Gmail, CVs, application forms, and a role scorecard. It does not score, reject, or message candidates. Its only job is to hand the interviewer a consolidated brief so they walk into the call informed instead of piecing information together from scattered systems.

Why does a role scorecard matter for AI interview prep?

A role scorecard grounds the AI's summary in what actually matters for the job. Without it, the model produces polished but generic output disconnected from hiring criteria. A useful scorecard lists role title, must-have requirements, nice-to-haves, concerns to verify, and interview areas. Keeping it short means hiring managers will actually use it, and the AI can align its briefing to real evaluation needs.

How do I reliably match calendar events to the right candidate?

Use email address as the unique identifier, since names can collide. Standardize calendar event titles in a format like 'Interview — Candidate Name — Candidate Email,' or include the email in the event description. Consistent, boring inputs make automation reliable. If the calendar event only contains a name, matching becomes unsafe when two candidates share it, leading to wrong briefings.

When should the briefing bot skip generating output?

The bot should skip generation whenever a critical input is missing, such as the candidate email. Instead of guessing, it should send the interviewer a short exception notice naming what is missing and linking the event to fix. Silent guessing produces embarrassing failures like briefings built on the wrong candidate. Explicit exceptions keep the human in control and preserve trust in the automation.

How do I trigger the interview briefing workflow?

Configure the system to check for upcoming calendar events tagged with an interview label, typically 30 or 60 minutes before the meeting starts. When it finds a match, it extracts the candidate email, candidate name, interviewer, role title, event time, and meeting link. It then searches Gmail narrowly using the candidate's email, prioritizing recent threads and labels like Applications, Recruiting, or Interviews.