Inspiration
Most therapy starts don't fail at the pharmacy. They fail earlier, because the patient never comes back in. Half of US adults with diabetes go a full calendar year without seeing a PCP or endocrinologist (Bossingham et al., JGIM 2026). Among adults with hypertension, 49.1% of those with a visit in the past year have controlled blood pressure, against 8.0% of those without one (Muntner et al., JAMA 2020). Practices know these patients exist, but nobody has time to dig through the EHR and phone them. Impiricus already has physicians inside DocUpdate as well as eRx, so we wanted to build an app that focused on improving the doctor-patient relationship.
What it does
Dosely finds patients who are overdue for follow-up in the practice's own records, calls them, and books them straight into the practice calendar. This is automatically done on the behalf of doctor without need for approval. If an appointment is booked, then the doctor will be notified in our portal.
Key features:
- Recall. A scheduled CRON job finds every patient whose follow-up date has passed and who may be contacted. Patients on hold or marked do-not-contact are skipped.
- Voice agent. An ElevenLabs voice agent calls the patient over a Twilio number. It verifies their date of birth, offers three open times, books one, and texts a confirmation. It only does scheduling. Any medical question is handed to clinic staff and lands in an action-needed queue. If nobody picks up, a text goes out instead.
- Staff review the booking, not the call. There is no per-patient approval. New bookings show up on the Schedule tagged "Booked by Dosely", and staff can mark one as looking good, reschedule it, or reassign it to another provider. The patient gets a text when it moves.
- Patient card. The physician sees the follow-up status, clinical context, the full call transcript with every tool call the agent made, the texts, and an outreach timeline.
- Sponsored matches. Under the card, in a clearly labeled section, the physician sees partner drugs whose records are semantically close to the patient's chart. "Explain more" generates a short explanation of the overlap that is barred from recommending anything. Outreach never depends on whether a drug matched, and patients never hear a drug, company, or diagnosis name.
- Two dashboards. The practice sees its funnel: overdue found, contacted, booked, seen, and visit revenue recovered. Impiricus sees aggregates only: panels shown and bookings by drug, company, and therapeutic area. No patient rows ever reach the sponsor view.
How we built it
Database. Supabase Postgres holds the synthetic EHR (we generated ~5k patients with corresponding data like last_time_visited, symptom_notes etc.), the partner drug records, and one events table. Both dashboards are queries over that one table, so the practice view and the Impiricus view always agree. Most of the backend is Postgres functions: the recall job, slot booking, reschedule and reassign as atomic slot swaps, and one read function per screen. pg_cron runs recall every 30 minutes inside the database, so it keeps running with every laptop closed.
Retrieval/Classifier. Joel built the RAG pipeline in Python. It routes the patient's diagnoses to therapeutic areas, builds a de-identified context string (diagnoses, medications, visit note, with no name, date of birth, or phone), embeds it with gte-small (384 dimensions), and runs a cosine search over pgvector filtered to those therapeutic areas. The top 5 are saved with their deterministic scores. Gemini writes the "why surfaced" text, generated once per patient-drug pair and cached.
Voice. A setup script creates the ElevenLabs agent through their API, registers five tools as webhooks into our app (verify_patient, get_available_appointments, book_appointment, decline_followup, escalate_to_staff), imports the Twilio number, and registers a post-call webhook. The post-call webhook is HMAC-verified and turns the ElevenLabs transcript into the rows the patient card renders. Texts go straight through Twilio.
Web. Next.js 16 App Router, React 19, TypeScript, and Tailwind 4. The API is Next.js route handlers that call the Postgres functions. The booking review cards and the landing page use three.js.
Built with: Next.js, React, TypeScript, Tailwind CSS, three.js, Supabase, PostgreSQL, pgvector, pg_cron, Python, sentence-transformers, Gemini API, ElevenLabs Agents, Twilio
Challenges we ran into
Building a reliable voice workflow: Getting the ElevenLabs agent, Twilio outbound calling, branch publishing, dynamic variables, and conversation logic to work together was one of the biggest technical challenges. We also had to make sure the agent handled interruptions, tangents, failed verification, and scheduling naturally without getting stuck.
Protecting patient privacy while still being useful: Because the agent interacts with sensitive patient context, we had to design strict identity-verification rules before any clinical information could be discussed. We added safeguards for wrong patients, incorrect dates of birth, medical questions, and cases where the caller should be redirected or the call should end.
Making the pharmaceutical matching actually relevant: Pure semantic similarity was not enough because it could surface drugs from the right general specialty but with weak clinical relevance. We combined structured therapeutic-area filtering with embeddings, pgvector, HNSW search, and Gemini explanations so the results were more contextually grounded while still being clearly labeled as sponsored content rather than treatment recommendations.
Accomplishments that we're proud of
We were able to set up a CRON job that actually scanned the mock data and find the semantic similarity to a drug instead of simply hardcoding values for the purpose of a demo.
Seeing our phone ring and having a "healthcare AI agent" schedule an appointment meeting with us was also really cool.
On the pharmaceutical side, we built a complete RAG pipeline using structured therapeutic-area filtering, embeddings, pgvector, HNSW nearest-neighbor search, and Gemini-generated explanations to surface contextually relevant sponsored records.
What we're most proud of is that these components work together as one automated pipeline: detect an overdue patient → initiate outreach → schedule follow-up → record the outcome → surface relevant context to the physician.
What we learned
We learned how retrieval systems can combine structured database filtering with semantic vector search rather than relying entirely on an LLM. We also learned that building an AI system for healthcare is as much about controlling what the model should not do as what it can do. Identity verification, privacy boundaries, human clinical control, and clear separation between sponsored content and medical recommendations became core parts of the design.
We gained hands-on experience integrating voice AI, telephony, vector databases, LLMs, and a full-stack physician dashboard into one workflow.
What's next for Dosely
- Retrieval v2: coded indication and exclusion rules as the gate, vectors only for ranking, every rule that fired logged.
- Contraindication suppression, so a panel suggestion never appears when the chart has an exclusion on file.
- Inbound text handling (YES to book, C to cancel etc).
- FHIR Slot and Appointment integration in place of our mock EHR and calendar.
- Real manufacturer label content in place of the fictional partner drugs.
- Also measure recall-to-booked rate, show rate, and therapy starts per 1,000 patients.
Built With
- gemini
- nextjs
- pgvector
- postgresql
- python
- sql
- typescript
Log in or sign up for Devpost to join the conversation.