The problem
A patient books a colonoscopy. Three days before, they're supposed to collect a prep kit from the pharmacy and stop taking iron tablets. The day before, start a clear liquid diet.
If any of that hasn't happened, the procedure can't go ahead. The slot is burned, the clinician is idle, and the patient waits weeks for another one.
An appointment reminder doesn't catch this. A reminder tells the clinic the patient is coming. It doesn't tell them whether the patient is ready.
Why this needs a phone call
A form can ask. It can't act on the answer.
The answer isn't yes or no. It's "I'll pick the kit up tomorrow." That patient is neither prepared nor cancelled, and somebody has to remember to ask again in two days. An unreturned form is indistinguishable from an unprepared patient.
That's a conversation, and it has to come back as data. CALL-E does both.
What makes it different
Most call workflows treat each call as an isolated event: ask, record, done.
PrepCheck compares every call against the previous one, item by item. Prep steps move independently, so a patient can collect the kit and in the same conversation reveal that a step recorded as complete was never actually done:
call 1 kit ✗ iron tablets ✓ prep_status = partial call 2 kit ✓ iron tablets ✗ prep_status = partial
Overall status is identical both times. A workflow keyed on overall status sees nothing happen at all. PrepCheck reports:
resolved: collected the bowel prep kit | REGRESSED: stopped taking iron tablets | net: no_improvement
A regression means the clinic's record is wrong, not merely incomplete, so it always reaches a person regardless of what the overall status said. The same comparison catches preparation that has simply stopped moving — two follow-ups with no change escalates to staff instead of earning a third call.
How it's built
A clinic keeps patients in a Google Sheet. An hourly Apps Script trigger sweeps it for anyone due a call. CALL-E places the call with that checkpoint's prep checklist in context and returns a structured result. The result drives a state machine that writes back to the Sheet.
There are no waits. Apps Script executions are capped at a few minutes, so the 48-hour callback is a next_call_at timestamp in a cell, not a sleeping process. The Sheet is the database, the queue, and the audit log.
Clinic staff never open the script editor. A PrepCheck menu and a patient-list panel live inside the spreadsheet — patients needing attention first, each with a one-word standing and the step holding them up.
Safety
The agent verifies whether a step was done. Nothing else.
It opens by stating it's automated, verifies identity before mentioning the procedure, and leaves nothing in a voicemail but the clinic name and a callback number. A clinical question is acknowledged, flagged for staff, and the call ends.
That boundary isn't only in the prompt. The result schema has no field capable of carrying clinical content — even if a patient volunteered a symptom, there is nowhere for it to be stored.
What I learned
The hard part wasn't placing a call. It was deciding what a call means when you already have one from two days ago. Tracking overall status is easy and catches nothing; comparing per-item results across calls is where the actual signal turned out to be.
The other lesson was about the platform. Apps Script can't hold a process open, so every piece of pending state had to become a timestamp in a cell. That constraint made the system better — everything it knows is visible in a spreadsheet anyone can read.
Challenges
Outbound calling to my region was restricted part-way through the hackathon while I was building. The live integration is demonstrated against CALL-E's official test hotline; the multi-checkpoint workflow is demonstrated with recorded call results posted to the same webhook the platform posts to.
The other challenge was scope. Healthcare invites feature creep — post-discharge check-ins, symptom triage, medication reconciliation. All of it is out of scope on purpose. An unsupervised agent eliciting symptom reports is a liability, not a feature.
What's next
PrepCheck expects a fixed Sheet layout, and no real clinic's spreadsheet will match it. The next step is a mapping pass where an LLM reads their existing sheet and proposes a column mapping, so adoption doesn't mean re-entering data.
Built With
- calle
- css
- google-apps-script
- google-sheets
- html
- javascript
- webhooks

Log in or sign up for Devpost to join the conversation.