Skip to main content
Zuko includes a standalone meeting-bot service (apps/meeting-bot) that automatically joins Google Meet meetings, records audio/video, and streams live transcripts back to the backend.

What it does

  • Joins a Google Meet URL using headless browser automation (Puppeteer)
  • Records the meeting as a WebM file and uploads it to S3
  • Streams live transcripts to the backend in real-time using Deepgram
  • Captures chat messages and responds to @zuko mentions via the AI agent
  • Emits status webhooks throughout the meeting lifecycle
  • Auto-leaves when it’s the only participant remaining

How it works

When the backend calls POST /api/google-meet/join, the meeting-bot:
  1. Launches an ephemeral Fly.io machine (in production) or runs locally (in dev)
  2. Opens Chrome via Puppeteer and navigates to the Meet URL
  3. Injects a browser script that extracts participants and chat via a local WebSocket
  4. Streams audio through FFmpeg to Deepgram for live transcription
  5. Sends transcript chunks (buffered at ~600 chars) to the backend
  6. On meeting end, uploads the recording and full transcript JSON to S3
  7. Emits a completed webhook with the S3 artifact keys

Environment variables

apps/meeting-bot reads:
  • BACKEND_URL — backend base URL (e.g. http://localhost:3001)
  • AGENT_TOKEN — shared token for authenticating requests to the backend
  • DEEPGRAM_API_KEY — Deepgram API key for live transcription
  • AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_REGION, AWS_BUCKET_NAME — S3 credentials for uploading recordings and transcripts
  • FLY_API_TOKEN, FLY_APP_NAME — Fly.io credentials for launching worker machines (production only)
  • PUPPETEER_EXECUTABLE_PATH — path to the Chrome binary
  • BOT_NAME — display name shown in the meeting (default: Zuko AI)
  • PORT — HTTP server port (default: 8000)
The backend must have the same AGENT_TOKEN configured to validate incoming transcript and callback requests.

Run locally


API

Join a meeting

POST /api/google-meet/join Triggers the bot to join a Google Meet.
Response

Status webhooks

The bot sends POST requests to callbackUrl (or BACKEND_URL/api/meetings/webhook) at each lifecycle stage.

Transcript streaming

During the meeting, the bot streams transcript chunks to the backend in real-time. POST /api/meetings/:meetingId/transcript-chunks

Headers

  • x-agent-token — must match AGENT_TOKEN
  • x-user-providergoogle-meet

Payload

Chunks are buffered at ~600 characters with 100-character overlap to preserve context across boundaries. On meeting end, any remaining buffered text is flushed.

S3 artifacts

After a meeting, two files are written to S3:

Chat and AI responses

The bot captures all chat messages from the meeting. When a participant sends a message containing @zuko, the bot queries the backend AI agent and posts the response back to the meeting chat.

Deployment

In production, each meeting runs on its own ephemeral Fly.io machine (1 CPU, 2 GB RAM). The machine is launched when a join request arrives and automatically destroyed after cleanup completes.