One visit decides everything here: the one where a patient hears the findings and the care plan. Every one is graded against the practice's own 5-stage framework. When recording moved into the room, the grading had to move with it without leaking a word of patient data.
- poll interval: a recording marked finished is picked up for grading on the next poll
- 30 min
- stages of the practice's own framework, scored on every consultation
- 5
- finished consultations left for anyone to grade or file by hand at handover
- 0
From the handover log, the workflow exports and the day-one incident notes, June and July 2026. No patient data is shown or stored here.
US multi-doctor healthcare practice, Built and live June 2026, handed over July 2026
Watch it run.
Read the narration
This grader works for a US healthcare practice with several doctors. It grades every recorded consultation against the practice's own five-stage framework.
Consultations are recorded in the room on Otter. Every 30 minutes, n8n picks up the recordings that have finished processing.
The grader checks a shared secret, skips anything already graded, and fetches the transcript if it is missing. An OpenAI model grades it as strict JSON, and a second model writes the coaching notes.
The grade and the notes become a PDF, built inside the practice's own Google Workspace and filed in a Drive folder with the transcript.
The prompt encodes the practice's framework and times the doctor's part of the visit against their benchmark. These stage names are generic samples.
A manager gets an email only for a yellow or red grade. It carries the grade, the title and a Drive link, and no clinical detail.
Every consultation gets a row in the tracking sheet. Nothing is marked processed until that row is written, so a failed run runs again cleanly, and any failure sends an alert email.
On day one, the poller graded a recording still in progress, about two percent of its transcript. It now waits for finished recordings, and those consultations were re-graded in full.
At handover in July 2026, every finished consultation was graded, filed and logged without anyone touching it.
Before the build.
The grading was already automated, one consultation per doctor, on top of Zoom recordings.
Then recording moved into the room, on Otter, because bot notetakers could not sit in several consultations at once. The intake had to switch from Zoom to Otter without breaking the grading, the coaching notes, the PDF reports, the Drive archive, the tracking sheet or the alerts.
The constraint the whole build had to clear
Every recording carries patient data, so any shortcut that leaked it was off the table.
It is why the PDF is built inside the practice's own Google Workspace and why the alerts carry no clinical detail.
What I built.
n8n polls Otter every 30 minutes, OpenAI grades the transcript, and the PDF is built inside the practice's own Google Workspace.
Four parts, and two of them exist because the first version was not enough.
- A grader that reads Otter
- Reports that never leave the practice's Google Workspace
- A poller, because the webhook was not enough
- A prompt that follows the practice's framework, not a generic one
What is true today.
- At handover in July 2026, every finished consultation was graded, filed and logged without anyone touching it.
- A finished recording is picked up on the next 30-minute poll, and a day-one bug (grading a recording mid-appointment) was caught, fixed and re-graded.
- Managers only get an email for yellow and red grades, with the full report one click away in Drive.
Still open
- All recordings run under one login, so grades cannot yet be split by doctor. I laid out the options. It is a process decision for the practice, not something to guess at in code.
Updated
The details, when you need them.
A grader that reads Otter
If the transcript is missing from the payload, the workflow fetches it from the Otter API. An OpenAI model grades the consultation against the practice's framework and returns strict JSON, and a second model writes the coaching notes.
Reports that never leave the practice's Google Workspace
The grade and the coaching become an HTML report, converted to PDF through Google Docs inside the practice's own Google Workspace rather than a third-party service. Each consultation gets its own Drive folder with the report and the transcript, and a row in the tracking sheet.
A poller, because the webhook was not enough
The practice records under one Otter login and does not share recordings to the workspace, so Otter's webhook almost never fires. A second workflow checks that account every 30 minutes and hands the grader only what Otter has finished processing.
A prompt that follows the practice's framework, not a generic one
I replaced the inherited general prompt with one that encodes the practice's 5-stage framework and times the doctor's part of the visit against their own benchmark. The output schema stayed identical, so the sheet and the reports did not break. A summary tab shows the grade breakdown by month.
- Every 30 minutes
- Runs in the practice's own Google Workspace
- No clinical detail in any alert
consultation-grader
Poll Otter every 30 minutes
finished conversations only
Verify the shared secret
anything without it stops here
Check for a duplicate
read-only check, committed at the end
Normalise the transcript
Otter API fallback if it is missing
Grade against the 5-stage framework
OpenAI, strict JSON, validated
Write the coaching notes
second model
Build the PDF in Google Workspace
one Drive folder per consultation
Upsert the tracking sheet row
keyed on conversation ID
Alert on yellow or red
grade, title and Drive link only
Mark as processed
3 workflows / failures route to an alert workflow
What happens when it fails?
- Idempotent by design. The duplicate check only reads, and a conversation is marked processed after its sheet row is written, so any failure re-runs cleanly. A pre-go-live review of my own build caught the first version marking conversations done on entry, which would have dropped them silently.
- Finished-only polling. On day one the poller graded a recording that was still in progress, about 2% of its eventual transcript. I gated it on Otter's finished status and re-graded the affected consultations on their full transcripts.
- A validation step throws if the model returns anything but green, yellow or red, and an error-handler workflow emails me about any failure.
- Transcripts are fenced in the prompt as untrusted data, and conversation IDs are validated before they touch an API URL.
- Otter API calls and the key Google Drive calls retry up to 3 times, 2 to 3 seconds apart.
- Each recording runs as its own execution, keyed by conversation ID, so simultaneous consultations never collide.
What I could not show you
- This system handles patient data. No real transcript, grade, doctor or patient appears on this page: the walkthrough runs on a replica with sample data.
- The grade distribution is not published either. It is the practice's clinical performance, not my portfolio.
- The 5-stage framework is theirs. Its wording stays with them.
Measurements and project details
- n8n workflows handed over: grader, poller and error handler
- 3
- Client
- US multi-doctor healthcare practice
- Industry
- Healthcare
- Region
- United States
- Timeline
- Built and live June 2026, handed over July 2026
- Role
- Workflow design, build, prompt engineering and go-live support
Stack
- n8n Cloud
- Otter.ai API
- OpenAI
- Google Drive
- Google Docs
- Google Sheets
- Gmail
- JavaScript
- Python