Build an AI Meeting Note-Taker in an Afternoon

LLazare Rossillon

The architecture behind every AI meeting assistant: a meeting bot records the call, webhooks deliver the transcript, an LLM writes the summary. Here's the whole pipeline with code.

Build an AI Meeting Note-Taker in an Afternoon
August 13, 2026

Every AI meeting assistant — the note-takers, the sales-call analyzers, the compliance recorders — is built on the same three-stage pipeline:

  1. Capture: a bot joins the meeting and records it
  2. Transcribe: speech becomes speaker-attributed text
  3. Reason: an LLM turns the transcript into summaries, action items, or CRM updates

Stages 1 and 2 are infrastructure. Stage 3 is your product. This guide shows how to get stages 1 and 2 down to one API call so you can spend your time on stage 3.

The capture layer is the hard part — bots that survive waiting rooms, layout changes and four-hour calls across Zoom, Google Meet and Microsoft Teams. That's the part you should buy, not build.

The capture layer: one POST request

import { createBaasClient } from "@meeting-baas/sdk";

const client = createBaasClient({
  api_key: process.env.MEETING_BAAS_API_KEY,
  api_version: "v2"
});

const { success, data, error } = await client.createBot({
  bot_name: "Acme Notetaker",
  meeting_url: meetingUrl // Zoom, Google Meet or Microsoft Teams
});

The same request works for all three platforms. With calendar integration enabled, you skip even this step — bots are scheduled automatically for your users' upcoming meetings.

The transcript arrives by webhook

When the meeting ends, your webhook receives the transcript with speaker attribution, the participant list, and the recording URL. A minimal handler:

export async function POST(req: Request) {
  const rawBody = await req.text();

  // Verify the webhook signature over the raw body before parsing —
  // see the webhooks documentation for the signing scheme
  if (!verifySignature(req.headers, rawBody)) {
    return new Response("invalid signature", { status: 401 });
  }

  const event = JSON.parse(rawBody);

  if (event.event === "complete") {
    const { bot_id, transcript, participants } = event.data;
    // Deduplicate on bot_id so replayed deliveries don't re-run the LLM
    if (await alreadyProcessed(bot_id)) return new Response("ok");
    await summarize(bot_id, transcript, participants);
  }

  return new Response("ok");
}

Speaker diarization is included with every recording, and segments are aligned to real participant names — your LLM prompt gets "Sarah: we'll ship Friday" instead of "Speaker 2: we'll ship Friday". That difference is what makes action-item extraction actually work.

The reasoning layer: your product

With a clean speaker-attributed transcript, the LLM step is a prompt, not a project:

async function summarize(botId: string, transcript: Segment[], participants: Participant[]) {
  const text = transcript
    .map((segment) => `${segment.speaker}: ${segment.text}`)
    .join("\n");

  const summary = await llm.complete({
    prompt: `Summarize this meeting. Extract decisions and action items with owners.\n\n${text}`
  });

  await saveNotes(botId, summary);
}

From here, differentiation is product work: per-participant follow-up emails, CRM enrichment, topic tracking across recurring meetings, or a speaking bot that answers questions live — the speaking bots API covers that last one.

What this costs to run

Recording costs 1 token per hour with diarization included; transcription adds 0.25 tokens per hour. With token packs at $0.35–0.50 per token, a fully transcribed meeting hour costs $0.44–0.63 — before your LLM costs, which on a transcript of a one-hour meeting are typically a cent or two.

Next steps

Similar blogstutorial