Inspiration
Phones are built for people who are comfortable tapping through menus. For many older adults, reordering a tablet or getting a cab to the clinic means juggling several apps, and many simply stop trying. For their children, it means worrying from far away, or making the call on their parent's behalf every time.
Most "AI assistants" only talk. We wanted one that actually does the thing: the medicine order should land in a real pharmacy's queue, the ride in a real dispatcher's queue, and the family should know about both. We also wanted it to be safe enough that an elder, or a worried son, can trust it with real actions.
That became ElderCare.
What it does
An older adult talks (or types) to an assistant: "Order Mom's sugar medicine", "Book a cab to the clinic". ElderCare works out what is meant, reads the details back for confirmation, and only then performs the real action.
Family members are notified, and can help, within the permissions the elder has granted.
- Voice-first AI assistant
- Speech input and spoken replies in English and Hindi, or plain typing.
- Understands family words ("mom", "uncle") and private nicknames ("Beta"). If a name matches more than one person, it asks instead of guessing.
- Medicines and dose tracking
- Per-person medicine list with strength, schedule, pack size and remaining supply.
- One-tap Mark taken with undo. The remaining count changes only when a dose is actually logged.
- Estimated days left, and a reorder prompt when supply runs low.
- Real pharmacy ordering
- Search the pharmacy catalogue and order by voice or from the app.
- Cash on delivery. A delivered order tops up the medicine supply exactly once.
- A separate Pharmacy portal where pharmacists see orders, move them through → out for delivery → delivered , and manage stock.
- Real cab booking
- Pickup defaults to the saved home address; the assistant confirms the destination, time and fare estimate before booking.
- Status on demand, and cancellation any time before the ride starts.
- A separate Rides portal where dispatchers work the queue, assign drivers and track availability.
- Family circle
- Invite members with single-use codes; every relationship (son, niece, uncle...) is derived automatically from the first connection.
- Per-person permissions: who can manage medicines and orders, who can book rides, who is notified, who is an admin.
- The family is notified when an order is placed or a ride is booked, and again when a ride completes, is cancelled or is rejected.
- Built for older adults
- Large, high-contrast, touch-friendly UI with a one-switch large-text mode.
- Voice, text and plain buttons all work; nothing requires the assistant.
- India-first: OTP login with 10-digit phone numbers, rupee pricing, IST-aware ride times.
How we built it
ElderCare system architecture

| Layer | Technology | Role |
|---|---|---|
| Frontends | React 18, Vite, TypeScript | Three apps: ElderCare (elder + family), Pharmacy portal, Rides portal |
| AI agent | Node.js, Express, Amazon Bedrock | Agent loop backed by Bedrock, with Amazon Nova, Amazon Titan and Amazon Claude configured as an ordered list of models behind one adapter interface, with automatic failover between them |
| Tooling layer | Model Context Protocol (MCP) over HTTP | The agent has no hardcoded tools; everything it can do is an MCP tool, orchestrated and permission-checked by the MCP server |
| Backend services | Express, TypeScript | ElderCare API (auth, family, medicines), MCP server, independent Pharmacy API and Rides API, all on EC2 |
| Data | MongoDB Atlas | Three separate databases — ElderCare DB, Pharmacy DB, Rides DB |
| Auth | Phone + OTP, JWT, API keys | JWT for users; API keys for partner-system (Pharmacy/Rides) calls |
| Voice | Web Speech API | Speech recognition and synthesis in English / Hindi |
| Monorepo | pnpm workspaces | Shared TypeScript types and relationship logic across services |
| Cloud hosting | AWS EC2 (t3.small) | Runs all backend services: ElderCare API, AI agent, MCP server, Pharmacy API and Rides API |
| Frontend hosting | Vercel | The three React apps are static builds; Vercel rewrites proxy API calls to the EC2 backend |
| Domain & routing | api.nikhilgautam.me via Nginx on EC2 | One custom API domain in front of EC2; Nginx does path-based routing ( /api , /mcp , /pharmacy-api , /rides-api ) to each service |
| Third-party | SMS/OTP, WhatsApp, Maps/geocoding | Phone auth, optional family notifications, address resolution |
All five backend services run together on a single EC2 t3.small instance behind Nginx; the frontends are static builds on Vercel. Vercel rewrites each app's /api , /agent-api , /pharmacy-api , and calls to our own domain, https://api.nikhilgautam.me/``{=html}/... , and Nginx routes by path to the matching service on the instance. Data lives in MongoDB Atlas, split into per-domain databases for ElderCare, Pharmacy and Rides.
One request, end to end
- The elder says "Order Mom's sugar medicine." The browser transcribes it and sends it to the agent with the user's login token.
- The agent decides which MCP tools to call. The user's identity is injected from the verified token, never taken from the model or the request body.
- The MCP server resolves "Mom" (alias, then relationship, then name), checks the caller's permissions, and calls prepare_order , which stores a 15-minute draft.
- The assistant reads the draft back. When the user says yes, pharmacy. places exactly that draft with the
- The pharmacist sees the order in the portal and moves it along; the family is notified; supply is topped up on delivery.
Design choices we're proud of
- Safe by construction: every consequential action is draft, read back, confirm, with idempotency so a double "yes" cannot double-order or double-book.
- Permissions enforced at the tool layer, so the assistant can only do what the signed-in person may do for that elder.
- Model-neutral, resilient AI: LLMs are configured as an ordered list behind one interface. On any error (rate limit, bad key, outage) the agent switches to the next provider immediately and skips the failed one for a cooldown, even mid-conversation. Adding a new model provider is one adapter file.
- Genuinely independent partner apps: the pharmacy and rides services have their own databases and API-key auth and know nothing about ElderCare. ElderCare calls them like any partner would.
Challenges we ran into
- An assistant that acts must not act wrongly. A misheard "yes" or a retried request must never place a second order. We solved it with short-lived drafts, an explicit read-back step and idempotency keys (the draft ID doubles as the request ID).
- Who is "Mom"? People say mom, uncle, or a private nickname, and relationships differ per viewer. We store only direct links and derive every other relationship, then resolve names in a fixed order and ask when ambiguous.
- Keeping the model honest about identity. The model can never choose whose account it acts for; the agent hides the auth argument from the model and injects the verified identity on every call.
- LLM outages and rate limits during a live demo. We built a provider-neutral interface with automatic failover and cooldowns so a failing provider never blocks the user.
- Running a multi-service system on one small instance. Five Node services share a t3.small, so we kept each lean and kept the partner services independent.
- Stock and supply consistency. Stock is reserved atomically on order placement, and delivery tops up medicine supply exactly once, even if status updates repeat.
- Honest statuses. Ride and order statuses come from the real partner services (synced on demand), not from the assistant's guess.
Accomplishments that we're proud of
- A complete loop with real systems: voice request to actual pharmacy order and dispatched ride, visible in two separate portals.
- Two-step, idempotent confirmation for every consequential action.
- Fine-grained family permissions enforced on the server for every action, not just hidden in the UI.
- Hindi and English voice with a UI designed for older users.
- Three apps and five services in one typed monorepo, deployed and live: backends on AWS EC2 behind our own API domain, frontends on Vercel, data on MongoDB Atlas.
What we learned
- For assistants that take real actions, trust matters more than cleverness: read-backs, confirmation and permissions did more for usability than any extra capability.
- Exposing capabilities as MCP tools keeps the agent thin and makes permissions and auditing a property of the tool layer rather than the prompt.
- Treating partners as truly independent systems forced clean API contracts and made the demo credible.
- Small details (large text, plain buttons, Hindi voice) decide whether older users adopt a product.
What's next for ElderCare
- Real-time push notifications for the family (live updates instead of on-demand refresh).
- Deeper AWS integration: Amazon Bedrock models as another provider behind the existing LLM interface, and an Alexa skill that reuses the same MCP tools and confirm-before-acting flow for hands-free use.
- Move the backend to managed AWS services (containers, load balancing) as usage grows.
- More services behind the same safe flow: groceries, doctor appointments, bill payments.
- Proactive nudges: missed-dose reminders and refill suggestions before supply runs out.
- More Indian languages for voice.
- Online payment alongside cash on delivery.
Built With
- amazon-ec2
- amazon-web-services
- express.js
- jwt
- llm
- mcp
- mongodb
- mongodb-atlas
- node.js
- pnpm
- react
- typescript
- vercel
- vite
- web-search-api
Log in or sign up for Devpost to join the conversation.