Architecture
Grades each recorded Zoom consult with Gemini.Runs on Cloud Run for three offices.
A Zoom webhook says a consult's transcript is ready, and one Cloud Run service scores it against the CEO's seven criteria with Gemini. The report goes to the doctor, the TC and the CEO, the chart note goes to the TC, and every consult becomes one row in a master Sheet that feeds the weekly report cards.
2.7 min
median from transcript to sent report in October, 9 in 10 under 3.8
0
score fields the one machine route can return, by allowlist and test
471 consults
scored live since May 19 across Rochester, Buffalo and Syracuse
68 min
from the first commit on May 19 to the first live consult graded that night
New York --:-- simulated
Hover a part to trace what it touches. Click it for its notes.
- Built by me
- Managed by Google
- Outside system
- Main data path
- On demand
- Credentials cross
When it breaks
What each failure does, and what it does not do.
-
Zoom sends it twice
Delivery is at least once. A Firestore claim on the meeting and file turns repeats into one run, and a crashed claim can be retaken after 15 minutes.
zoom-transcript-pipeline/app/state.py:1
-
Gemini runs out of room
On gemini-2.5-pro the thinking spends the same token budget as the answer. A cut response is never parsed, and the retry doubles the budget instead of repeating the prompt.
zoom-transcript-pipeline/app/scorer.py:312
-
A send fails after scoring
The run turns amber. The sweep repairs only the missing email or Sheet row, without scoring again, up to 3 times, then emails me.
zoom-transcript-pipeline/app/auto_retry.py:86
What I tuned
Small choices that keep it fast and cheap.
-
Budget, not retries
After the September 11 incident the scoring ceiling went from 8,192 to 32,768 tokens. Unused ceiling costs nothing: thinking measured 3,534 tokens at 8,192 and 3,589 at 32,768.
zoom-transcript-pipeline/config/pipeline.yaml:34
-
Warm only in office hours
One instance stays warm 7 AM to 7 PM Eastern instead of all night. CPU stays allocated, because the work runs after the 202 and would starve otherwise.
zoom-transcript-pipeline/infra/main.tf:256
-
Resume, do not restart
Report and chart note run as two branches after scoring. A retry that finds a valid scorecard redoes only the branch that failed.
zoom-transcript-pipeline/app/resume_policy.py:1
Guards
Rules the code enforces, not rules people remember.
-
Signed or refused
Every webhook must match its account's HMAC within 5 minutes of its timestamp, compared in constant time.
zoom-transcript-pipeline/app/security.py:22
-
Scores stay in DocReview
The one route another service can call is an allowlist with no score fields, and it fails closed when its secret is missing.
zoom-transcript-pipeline/app/api_lookup.py:14
-
No transcript text in logs
The JSON logger redacts emails, phones and record numbers. Scoring failures log token counts and the finish reason, never the text.
zoom-transcript-pipeline/app/logging_config.py:1
