New Client Setup Guide - MeetingOS (Consultant-Facing)

Consultant-facing. Zero-to-working in about 60 minutes per client. Built on the shipped zoom-transcript-fetch skill - this guide productizes it.

Architecture in one paragraph. MeetingOS is a per-client digital employee: a scoped agent whose entire brain is one folder. That folder holds the client's briefing file, the transcripts it fetches, the notes it writes, and a small state file so it remembers where it left off. The agent's allow-list - its key card - opens that one folder and the client's Zoom account. Nothing else. If you keep that shape, the module stays debuggable forever.

Setup Time at a Glance - MeetingOS New Client Install

Step 1 · ~15 min

Create the Client's Zoom Server-to-Server OAuth App

MeetingOS fetches transcripts through the Zoom API using a Server-to-Server OAuth app on the client's Zoom account. JWT apps are deprecated - never use them. There is no per-user OAuth flow, no redirect URIs, no refresh tokens.

  1. Have the client sign in at marketplace.zoom.us (they must be an account admin).
  2. Develop → Build App → Server-to-Server OAuth → Create. Name it MeetingOS Transcript Fetch.
  3. Copy the three credentials from the Information page: Account ID, Client ID, Client Secret.
  4. On the Scopes page, add exactly these five:
    • meeting:read:meeting:admin
    • meeting:read:list_meetings:admin
    • meeting:read:past_meeting:admin - required for the instances call under granular scopes
    • user:read:user:admin
    • user:read:list_users:admin
  5. Activate the app. A non-activated app is the most common day-one failure.

Step 2 · ~5 min

Turn On Zoom AI Companion Transcript Retention

Zoom has two completely separate transcript systems, and querying the wrong one silently returns empty results. MeetingOS uses AI Companion transcripts - they do not require cloud recording, which is why they work for clients who record locally or not at all.

  1. In the client's Zoom web portal (zoom.us), as admin: Settings → AI Companion.
  2. Turn ON "Allow meeting hosts to retain and access meeting transcripts."
  3. Recommended: Meeting Summary → "Automatically start" so transcripts generate without the host remembering anything.

Sanity check before touching the API: after the client's next meeting, the portal's Recordings & Transcripts → Transcripts section must list the transcript. If it appears there, the API can fetch it. If it does not, no API call will ever find it - fix this setting first. (If the client uses Cloud Recording transcripts instead - a .vtt attached to recordings - that is the other system; the fetch script targets AI Companion only.)

Step 3 · ~10 min

Build the Client Folder - the Digital Employee's Brain

The folder is the memory. No database, no embeddings. One folder per client, and the agent's allow-list opens only that folder - that is the scope guard between clients. Structure:

clients/ └── comfortflow-hvac/ ← one folder per client ├── CLAUDE.md ← the briefing: who they are, meeting │ series, note style, delivery rules ├── config.yaml ← client variables: names, emails, │ meeting schedule, thresholds ├── .env ← ZOOM_ACCOUNT_ID / CLIENT_ID / SECRET │ (chmod 600, never committed to git) ├── transcripts/ ← raw .vtt files, fetched once each │ └── 2026-08-03_weekly-ops-huddle.vtt ├── notes/ ← finished notes, date + topic + style │ └── 2026-08-03_weekly-ops-huddle_detailed-third-person.md ├── state/ │ ├── .fetched_instances.json ← dedup: every transcript lands once │ └── last-check.json ← what happened since the last run └── dashboard/ └── index.html ← the client's morning dashboard

CLAUDE.md is the standard briefing: company context, who attends which recurring meeting, which note style each meeting series gets, and where notes are delivered. last-check.json is what separates a real employee from a goldfish - without it the agent cannot tell a new transcript from one it already processed, and it has no record of its own previous actions.

Step 4 · ~10 min

First Transcript Test Run + Dedup Verification

From the client folder, run the fetch script once, manually, verbose:

ZOOM_ENV_FILE=.env python3 scripts/zoom_fetch_latest.py --verbose --once
OutputMeaning
Fetched: <topic> (...) - N wordsWorking. Transcript saved to transcripts/.
No new Zoom transcripts... All caught up.Working. Nothing new in the lookback window.
Missing required config.env not loaded - check the ZOOM_ENV_FILE path.
HTTP 401Credentials wrong, or app not activated (Step 1).
401 mentioning scopes on the instances callThe past-meetings read scope is missing - re-add scopes, re-activate.
Nothing found, but transcripts exist in the portalThe instance-UUID / double-encoding pitfall - see the pitfalls table below.

Then run the identical command a second time. It must print All caught up. - that proves dedup state is being written to state/.fetched_instances.json and no client ever gets the same notes twice.

Step 5 · ~10 min

Schedule the Transcript Fetch

Schedule runs for shortly after each recurring call ends. The script retries every 5 minutes for up to ~40 minutes while Zoom processes, so it tolerates meetings that run long - and a meeting still in progress at job time is handled by polling inside that wait window, not by exiting. Example crontab for a client with Mon 1:00 PM, Wed 11:00 AM, Thu 1:00 PM calls:

15 13 * * 1 ZOOM_ENV_FILE=/full/path/.env python3 /full/path/scripts/zoom_fetch_latest.py 0 12 * * 3 ZOOM_ENV_FILE=/full/path/.env python3 /full/path/scripts/zoom_fetch_latest.py 30 13 * * 4 ZOOM_ENV_FILE=/full/path/.env python3 /full/path/scripts/zoom_fetch_latest.py

launchd (macOS LaunchAgent with StartCalendarInterval) or an agent-runtime scheduler both work - the script prints only when it fetches or hits a real error, so silent runs are safe. Set TZ_NAME (e.g. America/Los_Angeles) so the lookback window and filenames match the client's meeting times.

Tuning knobs: ZOOM_TRANSCRIPT_DIR, ZOOM_STATE_FILE, ZOOM_LOOKBACK_DAYS (default 3), ZOOM_MAX_WAIT_MINUTES (default 40), --once for manual runs.

Step 6 · ~15 min

Meeting Note Formatting Rules + Delivery Destinations

The .vtt is raw material. The agent reads it (strip timestamps; speaker labels are the Name: prefix), applies a note style, and delivers. Long transcripts may need chunking at roughly 15k words per pass - extract per chunk, merge sections.

Pick one style per meeting series - ask the client, don't guess
StyleBest for
Bullet SummaryFast reads, internal teams (standups, huddles)
Detailed Third-PersonClients or stakeholders who missed the call
Action Items OnlyWeekly reviews where decisions are already understood
Coaching TrackerRecurring advisory calls needing cross-session continuity

Delivery destinations (configure per client in config.yaml):

Standing formatting rules: name every file and page with date + topic + style so they sort chronologically, and every note links back to its source .vtt path so it is auditable against the raw transcript.

Zoom Transcript Pitfalls That Will Burn You

PitfallSymptom / Fix
Wrong UUID type - the scheduled UUID instead of the instance UUID Error 3323 "transcript does not exist." Use the instance UUID from GET /past_meetings/{id}/instances. The most common failure.
Single-encoding the instance UUID UUIDs containing / 404 unless double URL-encoded.
Parsing instances from the instances response The response key is meetings, not instances. A parser looking for instances reports zero meetings.
Querying Cloud Recordings on a local-recording account Returns zero by design. Check the portal first to learn which of the two transcript systems the account actually uses.
Transcript processing lag The endpoint 404s right after a meeting ends. Retry every 5 min for up to ~40 min - the script does this internally.
"Fixing" the empty-pending case An instance is not listed until the meeting ENDS. Never add live-meeting checks or early exits - that reintroduces the miss.
Token in download URL Zoom takes the OAuth token as a query parameter on the transcript download - it can land in proxy logs. It expires in one hour and is read-only, but know it happens.

Done When - New Client Handoff Checklist

Budget: about 60 minutes of consultant time once the client provides Zoom admin access. The wait is usually the client's admin, not the work.

Chart Source Data - MeetingOS New Client Install

The chart above links here. These are the exact numbers it draws.

Data Table: Consultant Minutes per Setup Step - MeetingOS New Client Install

StepWhat it coversBudgeted minutes
Step 1Zoom Server-to-Server OAuth app on the client's account15
Step 2AI Companion transcript retention turned on5
Step 3Client folder built from the master template10
Step 4First transcript test run and dedup verification10
Step 5Transcript fetch scheduled after each recurring call10
Step 6Note styles and delivery destinations configured15
Total budgetRuns nearer 60 minutes with overlapped waits65