Inspiration

Every year Indonesia vaccinates millions of children at school during BIAS, the national school immunisation month. Consent for it goes home as a paper form in a schoolbag. A large share never comes back, so the school office spends the week before the session on the phone, one family at a time, and on the morning itself there are still children whose consent and screening nobody has. That is real phone work, at national scale, done by teachers.

What it does

VaxCheck calls every guardian on a class roster through CALL-E and asks four things: do you consent to the free school session or prefer your own doctor, has the child already had this vaccine, are there any allergies, is the child unwell today. It returns a triaged roster for immunisation day — as a terminal report, as JSON, and as the board: a self-contained HTML page a nurse opens on session morning. Who is cleared, who is going to their own doctor, who declined, who was never reached — and, the part that matters, who a person needs to look at before anything happens. Every review card shows the guardian's reported answers beside the reasons, so consent: granted sits next to allergy: severe and the question they asked.

Clearance is earned, never assumed. A student clears only when every signal is unambiguous. A severe or unclear allergy history, a possibly unwell child, an unclear prior dose, an unanswered question from the guardian, a callback request, unconfirmed identity, or a low completion_confidence from CALL-E all route the row to a nurse with the reasons listed. Voicemail is never consent. A cleared row means nothing was flagged; it is not medical clearance, and the roster says so at the bottom of every run.

How we built it

  • CALL-E Developer API via the calle-ai Python SDK: POST /v1/calls with a per-recipient result_schema of small closed enums, so a conversation becomes a row a nurse can act on.
  • One CALL-E task per student, not one per roster. A task carries a single completion_confidence; batching would let one voicemail drag a clean consent below threshold. Per-student tasks keep each clinical decision backed by that child's own call.
  • Idempotency keys derived, not generatedvaxcheck-<school>-<date>-<student> — so a re-run after a crash resumes instead of phoning a family twice. Duplicate student ids are rejected for the same reason.
  • Five modes in increasing order of consequence: --doctor (read-only live checks: CLI auth, SDK, API key via a real GET /v1/goals, region corridor via a real plan_call), preview (no network), --mock (fixture replay through the real triage code), --preflight (real plan_call per student, never dials), --execute --confirm-consent (real calls, double-guarded).
  • 68 tests. All run without network. Eleven install an httpx transport underneath a genuine CalleClient, so the real SDK assembles the request and the test asserts on the exact /v1/calls payload, both schemas, and the Idempotency-Key header.

Challenges we ran into

CALL-E cannot dial Indonesia — or Malaysia — even though both are listed in the published regions table. We verified it on both the agent surface (plan_call) and the Developer API (POST /v1/calls), filed it as feedback, and made the app corridor-agnostic with --preflight so a school finds a dead corridor on Tuesday, not on session morning. It also meant no real phone call could be shown: the film labels the roster as a fixture replay on screen and keeps the live API checks live.

The plan_call planner is an LLM. Our first preflight goal ("consent for Aisha") was ambiguous — the planner couldn't tell whether the bot was giving consent or collecting it — and passed or failed depending on the run. Rewriting the goal to state who is called, on whose behalf, and that the bot collects the guardian's decision made it pass 6/6, and the doctor now distinguishes a dead corridor from a planner asking about wording.

Accomplishments we're proud of

The triage rule survived every fixture we threw at it. Consent granted plus a reported severe reaction plus an unanswered question stays in review; consent granted with nothing else clears; "I don't remember" goes to a nurse; voicemail goes to retry. That distinction — consent and screening can disagree, and the software has to preserve the disagreement — is the whole product.

What we learned

Most of CALL-E's value for a workflow like this is in the schema and the confidence score, not the dialling. status: completed means the call finished; task_completed plus completion_confidence plus evidence[] is what you gate on. And a fixture-replay path isn't a compromise — it's what lets a judge, a school, or a contributor run the whole thing with no credentials and no calls.

What's next

Bahasa Indonesia the day CALL-E supports it. A webhook receiver so results land as they finish instead of by polling. A Goals-API mode so a school can run the same published call template every term. And a pilot with one school office to find out what the nurse actually wants at 7 a.m.

Built With

Share this project:

Updates

Submission history