Inspiration

Millions of elderly people live alone, recovering from surgery, recently widowed, or simply far from family who wish they could check in more often. Wellness check-in programs already exist — but they rely on volunteers or family members manually dialing a phone, which doesn't scale past a handful of people.

What struck us most is that this population is also the one least reachable by modern software. Apps, push notifications, and texts assume comfort with a smartphone that many elderly people simply don't have. But almost everyone can answer a phone call. When we saw CALL-E let an AI agent make a real outbound call — not generate text, not simulate a conversation, but actually dial and talk — the fit was immediate: the one channel this population can't be excluded from is exactly the one CALL-E unlocks for AI agents.

Well-Check was born from a simple question: what if the daily check-in call your family can't always make, an AI could make for you — safely, warmly, and with a human always in the loop for anything that matters?

What it does

Well-Check places a scheduled or on-demand phone call to a person living alone, holds a short, warm conversation, and returns a structured result a caregiver can act on immediately.

A single check-in call covers:

Step What happens
Consent Agent identifies itself and asks permission to talk
Wellbeing Open-ended "how are you feeling today?"
Structured checks Medication taken, meals eaten, anything needed
Escalation path Any mention of a fall, pain, or emergency triggers a calm, non-diagnostic safety response — never medical advice
Structured output CALL-E returns a JSON result matching a fixed schema, not just a transcript

That structured result feeds a caregiver-facing dashboard showing:

  • Per-contact status — last check-in time, concern level (none / low / high)
  • Recent Check-ins — a running history with plain-language summaries
  • Recent Pattern — our own longitudinal trend detector that looks across the last several check-ins and flags things like consecutive high-concern streaks, so a single "I'm fine" day doesn't hide a worsening pattern

We define a concerning streak simply, using only data we already have — no inference, no diagnosis:

$$ \text{streak_flag} = 1 \iff \sum_{i=n-1}^{n} \mathbb{1}[\text{concern}_i = \text{high}] = 2 $$

i.e., if the two most recent check-ins were both flagged high, the dashboard surfaces a clear "concern level has been HIGH for N check-ins in a row" banner — the single most actionable signal on the whole page.

How we built it

Architecture

┌─────────────┐     ┌──────────────────┐     ┌────────────────┐
│  Dashboard   │────▶│  Express Backend  │────▶│   CALL-E SDK     │
│ (HTML/CSS/JS)│◀────│  (calle-service,  │◀────│ (real outbound   │
│              │     │   index.js)       │     │  phone call)     │
└─────────────┘     └────────┬─────────┘     └────────────────┘
                              │
                      ┌───────▼────────┐
                      │  database.json  │
                      │ (contacts, logs) │
                      └─────────────────┘

Project structure

wellcheck/
├── index.js              # Express server, API routes
├── calle-service.js       # CALL-E SDK integration + safety guards
├── database.js            # File-based JSON persistence
├── database.json          # Contacts + check-in log history
├── public/
│   ├── index.html          # Home dashboard
│   ├── contact.html        # Contact detail view
│   ├── app.js               # Dashboard rendering + API calls
│   ├── contact.js           # Contact detail rendering
│   ├── styles.css            # Design system (colors, cards, badges)
│   └── assets/               # Illustrated hero imagery
├── .env                    # CALLE_API_KEY, TEST_MODE, ALLOWED_TEST_NUMBERS
└── .gitignore

Tech stack

Layer Choice Why
Backend Node.js + Express Zero-build, fast to iterate under a hackathon deadline
Voice AI @call-e/calle SDK client.calls.createAndWait() — one call, structured JSON result
Data File-based JSON No infra overhead; swappable for a real DB post-hackathon
Frontend Vanilla HTML/CSS/JS No build step; kept the whole stack lightweight and judge-runnable
Safety TEST_MODE + ALLOWED_TEST_NUMBERS guard Hard-blocks calls to any number not explicitly allow-listed

We deliberately avoided a frontend framework and a database engine — every added dependency is time a hackathon team doesn't get back, and CALL-E's own integration was the thing worth spending that time on.

Challenges we ran into

  • SDK vs. MCP vs. raw API — CALL-E offers three integration paths. We initially built against the MCP tool surface before realizing the published @call-e/calle npm package (installed separately, not bundled in the integrations repo) was the right fit for a backend automation service like ours. Re-architecting mid-build cost time but resulted in a much cleaner createAndWait() call.
  • Structured-output edge cases — our first schema required fields (checks, concern_level) even on calls that never connected, which meant an unanswered call could crash validation. We restructured the schema so only wellbeing_summary is required, and let our orchestrator branch on CALL-E's own call.status before ever touching call-specific fields.
  • Silent SDK misconfiguration — an early version of our call omitted the recipient field entirely, embedding the phone number only in the natural-language task string. CALL-E silently dialed its internal sandbox number instead of failing loudly — a subtle bug that cost real call credits before we traced it back to the SDK's actual TypeScript definitions.
  • Regional call delivery — as a India-based (+91) test number, some calls settled as billed on CALL-E's side but never rang our phone, consistent with CALL-E's own documentation describing international lines as intended primarily for testing.
  • Credit budgeting under pressure — with a limited real-call budget, every live test had a real cost. We added explicit safety guards, pre-call logging, and a strict "never call without explicit authorization" workflow to avoid wasting credits on unverified assumptions.

Accomplishments that we're proud of

  • A genuinely real, working CALL-E integration — not a mock: real outbound calls, real structured JSON extraction, real billing history to prove it.
  • A safety-first prompt design that never gives medical advice, always escalates emergencies to the person's own judgment and emergency services, and asks consent before every call.
  • A trend-detection feature that turns single data points into a longitudinal signal — a small feature with an outsized impact on what a caregiver actually needs to know.
  • A caregiver-first UI that stays calm by default and reserves color/urgency exclusively for genuine concern, matching the emotional register of the problem we're solving.

What we learned

We learned to read a vendor's actual published package sources and type definitions rather than trust a README's simplified example — the gap between "documented example" and "what the SDK actually accepts" caused several of our hardest bugs. We also learned how much a tone decision (a warm, unhurried phone script) matters just as much as the technical integration when the end user is someone who may be anxious, isolated, or hard of hearing. Technology built for vulnerable users has to be gentle by design, not just accurate.

What's next for Well-Check

  • Verified self-serve trials — a rate-limited, phone-verified way for real caregivers (or hackathon judges!) to safely try a check-in call without opening the system to abuse.
  • Multi-call orchestration — automatically calling a backup contact if the primary check-in goes unanswered.
  • Longer-term trend analytics — moving beyond a 5-call rolling window toward real historical pattern detection.
  • Real caregiver notification channels — SMS/email alerts firing automatically on a high concern result, not just a dashboard update.
  • Partnering with a community wellness-check nonprofit to pilot Well-Check as a scale multiplier for their existing volunteer programs.

Built With

Share this project:

Updates

Submission history