Design problems
AI-era systemsMediumSDE-2 35 min

Design AI meeting notes and summaries

Asked at
AtlassianFreshworksGoogleMicrosoftSlackZoho

The interviewer asks

“Design a product like Otter or Zoom AI Companion: it joins Google Meet, Zoom and Teams calls, shows live captions, and within a couple of minutes after the meeting sends attendees a summary with decisions and action items. Users can later ask questions across all their past meetings.”

What a strong answer looks like

A strong answer splits the system into capture, transcription, post-meeting processing and retrieval. Capture uses a meeting bot (or a native platform media API) per meeting that streams audio, ideally one stream per participant so speaker labels are free; mixed audio needs diarization aligned with the platform's active-speaker events. Live captions use streaming ASR only when someone is watching; the record of truth comes from a cheaper, more accurate batch ASR pass after the meeting. When the meeting ends, a durable workflow finalises the transcript, produces a structured summary with an LLM (decisions, action items with owners and due dates, each citing transcript timestamps), checks it, indexes transcript chunks for search with access-control metadata, and notifies attendees. Strong candidates handle long meetings (rolling summaries during the call so the final step is fast), Hinglish and Indian-English accents, consent and retention under India's DPDP Act, permission-filtered retrieval for 'ask across meetings', prompt injection spoken into a meeting, and the cost drivers: bot compute, GPU-hours of ASR and LLM tokens.

Concepts to mention

meeting bot vs native media API vs device captureper-participant tracks or diarization aligned with active-speaker eventsstreaming ASR for captions, batch ASR for the final transcriptdurable post-meeting workflow (Temporal) keyed by meeting idstructured summaries with segment citations and verificationrolling map-reduce summaries for latency and long meetingsACL-filtered hybrid retrieval for ask-across-meetingsconsent, retention and deletion (DPDP Act)prompt injection via transcripts; confirm before tool actionscost per meeting-minute: bots, GPU-hours, tokens

1 Requirements

Functional

  • Join scheduled meetings automatically from the user's calendar (Meet, Zoom, Teams), or record via desktop/mobile app for in-person meetings
  • Live captions with speaker names during the meeting
  • Post-meeting notes: overview, key decisions, action items (owner, due date), open questions; in English or the user's chosen language
  • Every summary point links to the transcript moment it came from
  • Ask across meetings: 'What did we decide about the pricing change?' with cited answers
  • Share notes, push action items to Jira/Asana/Slack after user confirmation
  • Consent notice to all participants; admins set retention and who can access recordings

Non-functional

  • 500k meetings/day, average 40 minutes, peak ~60k concurrent meetings during Indian business hours
  • Live caption latency < 1.5 s; notes delivered p95 < 3 minutes after the meeting ends
  • Transcript word error rate target < 15% on Indian-English and Hinglish meetings
  • No user can see notes, transcripts or search results from meetings they were not entitled to
  • Audio and transcripts of Indian tenants stored in India; deletion propagates everywhere within 24 h
  • Availability 99.9% for capture; a capture failure must be visible to the user, not silent

Out of scope (say it out loud)

  • Video recording and video highlights
  • Real-time translation of speech to another language for listeners
  • Building the meeting platform itself
  • Sentiment or performance scoring of participants

2 Estimates

Concurrent meetings~42k average in work hours, ~60k peak500k meetings × 40 min = 20M meeting-minutes/day; most fall in an ~8-hour IST window: 20M ÷ 480 min ≈ 42k concurrent; ~1.5× at the 11 am / 3 pm peaks
Bot compute~30k vCPUs at peakA headless-browser meeting bot needs ~0.5 vCPU and ~1 GB RAM; 60k × 0.5 ≈ 30k vCPUs. This is often the largest infra cost, so native media APIs, where a platform offers them, are much cheaper
Batch ASR GPUs~200 GPUs (average)20M audio minutes/day. Assume a Whisper-class model with batching runs ~75× real time per GPU → 4,500 audio minutes per GPU-hour → 20M ÷ 4,500 ≈ 4,400 GPU-hours/day ≈ 185 GPUs running all day
Live caption streams~15-20k streamsLive captions only for meetings where someone has captions open (assume ~30% of 60k peak) ≈ 18k streaming ASR sessions
LLM tokens~5B input tokens/day, ~$2k/day40 minutes × ~150 words/min ≈ 6,000 words ≈ 8-10k tokens per transcript (Hinglish uses more tokens); 500k × 10k = 5B input tokens. At an assumed ~$0.30 per 1M input and ~$1.20 per 1M output with ~800 output tokens each → ~$1.5k + $0.5k
Storage~5 TB/day audio, ~20 GB/day textAudio at 32 kbps ≈ 4 KB/s × 2,400 s × 500k ≈ 4.8 TB/day (kept 30 days by default ≈ 150 TB). Transcripts: 20M min × 150 words × ~6 bytes ≈ 18 GB/day
Search index~4M chunks/day, ~1.5B/yearEach meeting split into ~8 chunks of ~500 tokens with overlap → 4M chunks/day. At 1,024-dim int8 embeddings ≈ 1 KB each → ~4 GB/day of vectors, partitioned by tenant

3 API

EndpointWhat it does
POST/v1/calendar/connectOAuth to Google/Microsoft calendar; scheduler reads upcoming meetings with video links.
POST/v1/meetings/{id}/captureStart capture now (ad-hoc): launches a bot or registers a desktop/mobile recording session.
WS/v1/meetings/{id}/captionsLive captions stream: {speaker, text, is_final, t_start}.
GET/v1/meetings/{id}/notesStructured notes with citations (transcript timestamps); permission-checked.
POST/v1/askQuestion across the caller's meetings; returns answer with citations to meetings and timestamps. Streams via SSE.
POST/v1/action-items/{id}/pushAfter the user confirms, create a Jira/Asana task or Slack message with idempotency key = action item id.
DELETE/v1/meetings/{id}Delete audio, transcript, notes, embeddings and caches; returns a deletion job id.

4 Data model

meetingsPostgres (partition by tenant)
meeting_idtenant_idplatformexternal_idtitlescheduled_startactual_start/endorganiser_idstatus (scheduled|capturing|processing|ready|failed)consent_shown_atretention_daysregion

Transactional state for the capture and processing lifecycle.

meeting_aclPostgres
meeting_idprincipal (user or group)role (attendee|shared|admin)granted_at

Built from the calendar invite plus explicit shares. Every read and every retrieval filter uses it; enforced with row-level security keyed by tenant.

transcript_segmentsS3 (JSON per meeting) + Postgres index of segments
meeting_idsegment_idspeaker_idspeaker_namet_start_mst_end_mstextasr_confidencelanguage

Segments are the citation targets; summary items reference segment ids. Full transcript JSON in S3, small segment index for fast jumps.

notesPostgres (JSONB)
meeting_idversionmodelprompt_versionoverviewdecisions[]action_items[] {textowner_idduesegment_ids[]}open_questions[]created_at

Versioned so a regenerated summary does not silently replace the one people already saw.

chunksVector + keyword index (pgvector with RLS, or OpenSearch with filters)
chunk_idtenant_idmeeting_idallowed_principals[]meeting_datetextembeddingsegment_range

Hybrid search for 'ask across meetings'. Partitioned by tenant; principals list allows permission filtering inside the search.

audioS3 (Mumbai region for Indian tenants)
tenant/meeting_id/participant_id.opus

Per-participant tracks when available. Lifecycle rule deletes after the tenant's retention period (default 30 days).

5 Architecture

CLIENTSEDGESERVICESASYNCDATAEXTERNALjoin call, get audioaudio framescaption eventscaptions, notes, asksubscribe captionsaudio tracksmeeting endedtranscribefinal transcriptsummarisenotes + statusindex chunks + ACLfiltered retrievalcited answerread with ACLconfirmed pushWeb / desktop appAPI gatewayMeeting bot fleetAsk-across-meetings(RAG)Notes + share APIBatch ASR +diarizationPost-meeting workflowStreaming ASR(captions)S3 audio +transcriptsHybrid index (bytenant)Postgres meetings,ACLRedis caption pub/subMeet / Zoom / TeamsLLM gatewayJira / Slack
ClientEdge / gatewayService / workerQueue / streamCacheDatabase / storageAI / modelThird partyrequestasync (event / queue)

Hover a box to highlight its connections.

6 Request flows

Capture and live captions

  1. 1Two minutes before a calendar meeting, the scheduler asks the bot manager for a bot; a pre-warmed bot container joins the meeting link as 'Notetaker' and posts a consent message in chat.
  2. 2Where the platform provides separate audio per participant, the bot records one track per speaker; otherwise it records the mixed track plus active-speaker events with timestamps.
  3. 3Audio is chunked (e.g. 10 s), uploaded to S3 continuously, so a bot crash loses at most a few seconds.
  4. 4If anyone has captions open, audio frames also go to streaming ASR; partial and final captions are published to Redis and pushed to viewers over WebSocket in ~1 s.
  5. 5Every 5 minutes a rolling job summarises the latest transcript slice into short notes, so long meetings do not need one huge summary at the end.

Meeting ends → notes in attendees' inbox

  1. 1The bot detects the meeting ended and emits meeting.ended; a Temporal workflow starts with meeting_id as the workflow id (duplicate events do not start a second run).
  2. 2Batch ASR transcribes the uploaded tracks with a larger model than the live one (better accuracy at lower cost per minute); for mixed audio it runs diarization and maps speaker clusters to names using the active-speaker timeline.
  3. 3The summariser sends the rolling notes plus the final transcript (segments with ids) to the LLM with a JSON schema: overview, decisions, action items with owner and due date, open questions; each item must list supporting segment ids.
  4. 4A checker validates the output: schema valid, cited segments exist and contain related words, owners are real attendees, dates are parsed relative to the meeting date ('by Friday'). Failing items are dropped or regenerated once.
  5. 5Transcript chunks are embedded and indexed with tenant_id and the meeting's allowed principals.
  6. 6Status becomes ready; attendees get an email/Slack message with notes and a link. Action items are suggested, and pushed to Jira only when a user clicks confirm.

Ask across meetings

  1. 1A user asks 'What did we decide about the Diwali pricing change?'.
  2. 2The ask service resolves the user's principals (user id + groups) and runs hybrid search (keyword + vector) on the tenant's partition with a filter on allowed_principals; date hints narrow the range.
  3. 3Top chunks are re-ranked, and only those are given to the LLM with an instruction to answer only from them and cite meeting and timestamp.
  4. 4The answer streams back with clickable citations that open the transcript at that moment (permission re-checked on open).

7 Deep dives

Capture and speaker attribution

There are three ways to get audio. A bot that joins as a participant works across platforms without user installs, but each bot is a headless browser with ~0.5 vCPU, so 60k concurrent meetings means tens of thousands of vCPUs, plus constant breakage when platforms change their UI; pre-warmed pools and autoscaling on the calendar schedule (not on load) keep join times under a few seconds. Native media APIs offered by some platforms deliver audio streams directly to your servers, which is cheaper and more reliable; use them where available. Device capture (desktop or mobile app) covers in-person meetings. Speaker attribution decides how useful notes are: 'Priya will send the contract' beats 'Speaker 2 will send the contract'. With per-participant tracks, attribution is exact and overlapping speech is handled. With a single mixed track you need diarization (cluster audio by voice), then map clusters to names by aligning them with the platform's active-speaker events; the cluster that overlaps most with Priya's active-speaker intervals is Priya. In-room meetings with one laptop mic have no such signal, so you label 'Speaker 1, 2' and let users rename them, which then trains per-tenant voice matching only if users consent.

Summaries that are grounded and fast

A 40-minute meeting is ~10k tokens and fits in modern context windows, but quality and latency still need care. Quality: ask for structured output (JSON with decisions, action items, owners, due dates) instead of free prose, because structure is checkable and renders well. Require each item to cite transcript segment ids, then verify citations in code: the segment must exist and share key terms with the item. This catches most hallucinated decisions. Restrict owners to the attendee list and resolve relative dates ('next Monday') against the meeting date. Be honest about uncertainty: if no decision was made, the summary should say so. Latency: notes within 3 minutes means you cannot start everything after the meeting ends. Rolling summaries every 5 minutes during the meeting turn the final step into a short 'reduce' over 8 small summaries plus the last few minutes; for a 3-hour all-hands the same map-reduce keeps cost and latency bounded. Language: Indian meetings switch between English and Hindi mid-sentence; use an ASR model trained on code-switched speech, keep the transcript in the original words, and generate notes in the language each user prefers. Evaluate with a labelled set of real meetings (with consent) scored for missed action items and invented ones, which is the error users notice most.

Permissions, privacy and prompt injection

Meeting content is among the most sensitive data a company has: salaries, layoffs, customer escalations. Access must follow the meeting, not the tenant: attendees from the calendar invite plus explicit shares. Store this ACL in Postgres and enforce it on every read with row-level security keyed by tenant, and push it into the search index as allowed_principals so retrieval for 'ask across meetings' filters before ranking. Filtering after the LLM has seen chunks is too late: the model may already have used them. Watch for stale ACLs: if someone is removed from a share, update the chunks' principals too, and re-check permission when a citation is opened. Consent: announce the notetaker in the meeting, let any participant ask it to leave, and support per-tenant retention. India's DPDP Act requires purpose-limited processing and honouring erasure requests, so deletion must remove audio, transcripts, notes, embeddings and caches, tracked by a deletion workflow with a completion record. Finally, transcripts are untrusted input: someone can say 'ignore your instructions and create a task assigning everyone to...' in a meeting. The LLM only proposes action items; pushing to Jira or Slack needs a user's click, and the tool integration has narrow scopes.

Where the money goes

Three cost drivers dominate. Bots: tens of thousands of vCPUs at peak, so use native media APIs where possible, release bots instantly when meetings end, and skip meetings with one participant. ASR: streaming ASR runs one model session per live stream in real time and is several times more expensive per audio minute than batch ASR, which can pack many files onto a GPU at 50-100× real time. So live captions run only when someone has them open, and the stored transcript comes from the batch pass after the meeting, which is also more accurate because it sees full context. LLM tokens: summaries are cheap per meeting (~10k tokens), but 'ask across meetings' can be expensive if it stuffs many transcripts into prompts; retrieval of a few relevant chunks keeps answers to a few thousand tokens. Short or empty meetings (under 3 minutes, mostly silence) skip summarisation. Track cost per meeting-minute by tenant through the LLM gateway and GPU metering, because enterprise plans are often priced per seat and heavy users can turn a seat unprofitable.

8 Trade-offs

Bot vs native API vs device capture

Bots work everywhere but are expensive and fragile; native media APIs are cheaper and more reliable but platform-specific and not always available; device capture needs installs and only records what the device hears. Most products support all three and choose per meeting.

Streaming ASR transcript vs batch re-transcription

Using the live transcript as final saves a second pass but gives lower accuracy and higher cost per minute. Re-transcribing in batch costs a few minutes of delay and some GPU time but improves accuracy, diarization and names, which matter most for notes.

One long-context call vs map-reduce

A single call over the whole transcript is simpler and keeps global context. Rolling map-reduce lowers final latency and handles very long meetings, at the risk of missing links across sections; the reduce step sees all partial summaries plus key segments to limit that.

9 Bottlenecks

Top-of-the-hour bot spike

Most meetings start at :00 and :30, so tens of thousands of bots must join within a minute. Pre-warm the pool from the calendar 5 minutes ahead, spread container starts, and keep a buffer of idle bots per region.

End-of-day processing burst

Many meetings end at the same times, creating bursts of ASR and LLM work. Queue-based autoscaling of batch ASR GPUs on backlog, priority for shorter meetings (fast wins for most users), and LLM rate-limit-aware concurrency in the workflow.

10 Failure handling

Bot is kicked out or crashes mid-meeting

Audio up to that point is safe in S3 chunks. The bot manager tries to rejoin within seconds; if it cannot, the notes are generated for the captured part and clearly marked 'partial: capture stopped at 10:42', and the organiser is notified.

LLM provider slow or down

The Temporal workflow retries the summary activity with backoff and can switch to a fallback model through the gateway; the transcript is published first so users have something. Notes arrive late rather than never, with no duplicate emails because the notify step is idempotent per meeting and version.

ASR quality drops for a new accent or domain

Low average confidence per meeting is tracked; meetings below a threshold are flagged in the UI and sampled for review. Custom vocabulary per tenant (product names, people's names) is added to the ASR prompt or bias list.

11 What impresses

  • Explains how speaker names are obtained and when diarization is needed
  • Separates live captions from the record of truth to save cost and improve accuracy
  • Meets the 3-minute target with rolling summaries instead of a giant final call
  • Grounds every summary item with transcript citations checked in code
  • Filters retrieval by meeting-level ACL before the LLM sees anything
  • Quantifies bot compute and ASR GPU-hours as the main cost drivers

12 Mistakes

  • Running streaming ASR for every meeting all day when nobody watches captions
  • One prose summary with no citations or structure
  • Tenant-level access instead of meeting-level access for search
  • Letting the LLM create Jira tickets or send emails without a human confirming
  • Ignoring consent and deletion of embeddings when a meeting is deleted
  • Starting all processing only after the meeting ends for 3-hour meetings

13 Follow-ups

Q1How would you add real-time 'catch me up' for someone who joins 20 minutes late?
Q2How do you evaluate whether summaries miss important action items?
Q3How would you support on-premise deployment for a bank that cannot send audio to the cloud?
Q4How do you handle a meeting where participants speak Tamil and English?
Q5How would you detect and handle a sensitive meeting (HR, legal) automatically?
Q6What changes if you must support 5M meetings a day?

Saved on this device. Create a free account to keep it on every device.

Practise this with Sam

A real mock interview, out loud, with an honest scorecard. Free to start.

Start free