CALL-E × Yadira — the help button that rings a phone
Devpost story for the CALL-E hackathon. The reusable Agent Skill is urgent-help-escalation-call/; the feedback we compiled for the CALL-E team from live calls is in FEEDBACK.md.
Elevator pitch: When a person living with dementia presses "I need my caregiver," an in-app banner isn't enough — the moments it exists for are the moments nobody is looking at a screen. CALL-E rings the caregiver's phone, says only who asked and when, and tells the app whether the message actually landed.
Inspiration
We were building Yadira, an AI companion for people living with dementia. It has a help button: one tap that says I need my caregiver. It raised a banner on the caregiver's screen, and we were proud of it — until we asked the obvious question.
What if nobody is looking at the screen?
The moments the button exists for are exactly the moments that assumption fails: the middle of the night, a shower, a meeting, a commute. An in-app alert is only as good as somebody watching for it, and at 4am nobody is. We needed a channel that interrupts a person who isn't waiting to be interrupted. There is only one: a ringing phone.
That is the whole reason we reached for CALL-E. Not to add a feature — to close the gap between "the app knows someone needs help" and "a human is on the way."
What it does
patient presses help → banner raised on the caregiver's screen (every family, free) → CALL-E rings the caregiver's phone (Caregiver Pro) → readout: reached / voicemail / no answer, and did they say they're coming The call is deliberately small. It confirms who is listening before it discloses anything, says only who asked for them and when, never rings twice for repeated presses, and hands the app back a structured answer to two questions: did it reach a person, and did that person say they're going.
The part we're proudest of is what it does when the caregiver says they can't get there. That used to end with "thank you, goodbye" — the worst possible answer at the moment the patient is least likely to get help. Now the call accepts it without pressing, asks once whether anyone else is nearby, says the one thing that's actually true (the companion stays with them), and leaves the decision to call emergency services where it belongs. That answer travels back into the app, too: the companion stops telling the patient someone is on their way, because now that isn't true.
How we built it
The integration is a few small, single-purpose files, wired fire-and-forget off the existing alert route so a phone network can never delay the patient's own help:
Piece File The call, the message, the cooldown src/server/helpCall.ts CALL-E Developer API transport src/server/calleApi.ts Trigger wiring, fire-and-forget from the alert src/server/index.ts Tests, including "never dial the patient" src/server/helpCall.test.ts Fake CALL-E server, for tests/CI/demos calle/urgent-help-escalation-call/scripts/fake-calle-api.mjs Three things in the CALL-E API did real work for us:
recipient_result_schema — the best thing in the API. We declared the readout we wanted and got it back validated, which replaced a pile of regex over transcripts. Being able to put "unclear" and "unknown" in the enums mattered more than it sounds: it gave the model an honest way out, so it never invented a wellbeing signal that would then get charted and acted on. The plan/confirm split in the CLI — a genuine safety primitive. Being able to inspect a plan before spending the confirmation token is exactly the gate a product like ours needs, and we built our refuse-to-dial check on it. Idempotency-Key — a retried request cannot ring a frightened person's carer twice. We also lifted the whole thing out of Yadira into a reusable CALL-E Agent Skill, urgent-help-escalation-call, so any app with a panic button, a lone-worker alarm, a fall sensor, or a care-home call bell can do this correctly instead of learning our lessons the hard way. It ships with a fake CALL-E server so the entire pipeline — trigger, call, structured result, escalation ladder — runs without ringing anyone.
Challenges we ran into
Every one of these was measured on a live call, not read in the docs — and each changed the product. The full write-up is in FEEDBACK.md.
The caller ID isn't stable. Three consecutive test calls to the same caregiver came from Dallas, Houston, and New Orleans — three numbers, three cities, none the caregiver's own area code. This is the one call in the product that must not be missed, and it arrives looking exactly like the 4am spam call people are trained to decline. We had shipped a "save the number as a contact" feature; it could never have worked, and worse, a caregiver who followed it would have believed they were protected while nothing had changed. We tore it out and replaced it with the only advice that survives a rotating caller ID: turn off "silence unknown callers," because you can't allowlist what you can't predict. Time-to-ring is ~2 minutes, and undocumented. Button pressed at 04:04, phone rang at 04:06. We'd shipped copy saying "straight away" and had to correct it after watching a real call. No control over the voice. There's no parameter to supply your own voice. Yadira speaks to the patient in a specific cloned voice, and to someone whose recognition is failing, a familiar name in an unfamiliar voice reads as an impostor. So we removed our patient-facing call idea entirely and kept CALL-E only for reaching the caregiver — where the voice doesn't matter, because a caregiver knows what the call is.
Accomplishments that we're proud of
We named the two people and never confused them. Subject (the vulnerable person, never called) and Recipient (the carer, whose phone rings) live in separate fields with separate validation, and there's a test whose only job is to prove we never dial the patient. Dialling the wrong one means telling a frightened person that a frightened person needs help. Voicemail names nobody. It's the one case where the "who am I speaking to?" gate can't run, so the message is safe for a whole room to overhear: no name, no reason, just "there's an alert waiting in your app." The alert is free; only the call is paid. Nobody loses the help button. What Caregiver Pro buys is the phone ringing as well as the screen lighting up. We gave back a reusable skill. The escalation pattern is generalized, documented, and shippable to other builders, with a no-call test path built in. What we learned The hard-won lesson is a design one, and it's baked into the skill: confirm who is listening before you disclose anything. The obvious build leads with the message to save a second. It's wrong. A number will eventually be answered by a neighbour, a partner, a child, or a stranger with a recycled number — and leading with the message tells them a named vulnerable person needs help before you know who's on the line. Nothing downstream can un-say it.
The other lesson is humility about what a phone call is. It reaches one nominated person who may be asleep, driving, or unreachable, and it assesses nothing. It is not an emergency service and we refuse to present it as one. The patient must always have a real route to emergency help that doesn't depend on this call being placed, answered, or correctly understood.
What's next
The three asks in FEEDBACK.md that would most help urgent escalation on CALL-E: a stable outbound number per account (so a product can tell users "save this contact" at setup), caller-ID/CNAM configuration, and a documented time-to-ring with a queued vs dialling status on the call object. Getting the urgent-help-escalation-call skill merged into awesome-phone-call-agents, so the next builder starts where we finished.
Built With
- api
- call-e
- developer
- express.js
- firebase/firestore
- node:test
- react-19
- typescript
Log in or sign up for Devpost to join the conversation.