Inspiration

Telemedicine in Nigeria already works. Patients can chat, call, or video-call a doctor and get medication delivered, and platforms like TeleDoc, Healthconnect247, and WellaHealth already do this well. We're not claiming to have invented telehealth.

What stood out during research (and in conversation) was something less obvious: for a lot of people, privacy isn't a nice-to-have in healthcare. It's the reason they seek care at all. STIs, mental health, anything embarrassing to say out loud to a stranger; people delay or avoid treatment not only because of cost or distance, but because they'd have to say it to someone's face first. For these patients, telehealth's real advantage isn't convenience. It's that nobody in a waiting room is watching them walk in.

That's the idea Knot is built around. Connecting patients, doctors, and pharmacies for fast consults and less waiting, the same reasons telehealth exists in general, while also taking privacy seriously enough to design the product around it instead of treating it as an afterthought.

What it does

Knot is a multi-agent telehealth platform with four cooperating agents built on the Strands Agents SDK.

Intake Agent. Has a private, unhurried conversation with the patient before the doctor joins, gathering symptom history, duration, allergies, and prior treatment. The doctor walks into the consult already briefed, so their limited paid minutes go toward judgment instead of repetition.

Doctor-Efficiency Agent. After the consult, drafts a visit summary and a draft prescription from the transcript. The doctor reviews, edits, and signs off explicitly. Nothing reaches a pharmacy or patient without that human sign-off.

Fulfillment Agent. Takes a signed prescription and routes it to every partner pharmacy that stocks any part of it, not just one "best match." It handles partial fulfillment, substitution proposals, and, for pharmacies outside our network, a public verification-token system so an unregistered pharmacist can confirm and dispense legitimately.

Emergency Escalation Agent. This is the piece we're proudest of. It watches for red-flag language during intake and consult and treats two kinds of danger differently. A physical emergency triggers an active full-screen countdown, an audible alarm, and, if unanswered, a notification to the patient's emergency contact. A mental-health crisis triggers the opposite response: no alarm, no countdown, just calm de-escalation, crisis-line information, and a priority flag sent straight to a human doctor. We designed it this way deliberately. The same loud alert that could save someone's life during a physical emergency could just as easily break the trust of someone who has admitted something they've never said out loud, on a platform whose entire premise is that their privacy will be respected.

One rule holds everywhere in the system: the AI never diagnoses and never prescribes. It drafts, prepares, and flags. A licensed doctor or pharmacist always makes the final decision.

How we built it

We started from the constraint, not the feature list. This was a 24-day build with one person doing most of the implementation work, using AI-assisted tooling (Claude for architecture and design decisions, Cline for hands-on coding). That shaped nearly every choice we made.

Backend: FastAPI, a Strands multi-agent orchestrator, and SQLite. We deliberately avoided a hosted database service since a local demo doesn't need that complexity, and every dependency we skipped was one less thing that could break before the deadline.

Frontend: React, Vite, and Tailwind, with a dark glassmorphism design system chosen specifically to reinforce the privacy thesis. It's meant to feel like the after-hours, alone-with-your-phone moment this product actually serves, not a bright clinical waiting room.

Model: Google Gemini's free tier by default, with a documented one-line swap to Amazon Bedrock (MODEL_PROVIDER=bedrock) for the AgentCore deployment path.

Emergency detection: a two-stage design by choice. An LLM classifies patient messages against a fixed category list, but the decision about what action to take (countdown, de-escalation, or nothing) is deterministic Python, not left to the model. That keeps the safety-critical logic explainable and testable independent of any model call. We have zero-LLM unit tests confirming the mental-health path always wins over a simultaneous physical-emergency match, at every confidence level, because that's the one thing that must never be wrong.

Challenges we ran into

Prescription fulfillment got genuinely hard. Our first version routed a signed prescription to one "best match" pharmacy, which breaks the moment stock is split across two pharmacies or nobody has full coverage. We rebuilt it to route to every pharmacy with partial stock, track fulfillment per drug item instead of per prescription, and make "confirm" an atomic, race-safe claim, proven with concurrent-request tests rather than assumed to work.

Regulatory reality kept surfacing mid-build. We wanted doctor and pharmacy verification to be real, using MDCN for doctors and PCN for pharmacies, and discovered there's no clean public API for either, with Nigeria's MDCN manual lookup costing real money per check. Rather than fake automated verification, we built an honest "pending manual verification" state into sign-up and treated the cost as a business-model question to solve later, not a technical shortcut to paper over now.

Free-tier model rate limits shaped the UX more than we expected. Every patient message triggers two model calls, one for the intake reply and one for emergency classification running in parallel. Gemini's free tier is tight enough that we built a custom request-pacing layer just to stay under quota through a full demo run, which means there's real, visible latency per message we had to design around rather than hide.

Unregistered pharmacies were a real gap, not an edge case. A patient with a signed prescription and no registered pharmacy nearby needed a legitimate way to get their medication filled elsewhere, while still giving that outside pharmacy something to keep for their own legal records. We built a single-use, time-limited verification token system for exactly this. Patient details stay masked until a pharmacist actually commits to dispensing, the endpoint is rate-limited against brute-forcing, and a dispensing summary PDF is generated for the pharmacy's own compliance records.

Accomplishments that we're proud of

The emergency-escalation dual-flow design. Not just building an alert system, but recognizing that a physical emergency and a mental-health crisis need opposite responses, and proving it with tests instead of just good intentions. Our unit tests confirm the mental-health path always wins over a simultaneous physical-emergency match, at every confidence level.

Atomic, race-safe pharmacy fulfillment. When a prescription is routed to multiple pharmacies, only one can ever claim a given item. This is proven under real concurrent-request testing (20 out of 20 threaded races, 3 out of 3 concurrent HTTP races), not assumed to work in practice.

An honest verification story instead of a fabricated one. Rather than pretend we had live MDCN or PCN registry integration we don't actually have, we built a clear "pending manual verification" state into doctor and pharmacy sign-up, and designed a fallback for prescriptions going to pharmacies outside our network: a single-use, time-limited public verification token with patient details masked until a pharmacist commits to dispensing.

Keeping the "AI never diagnoses or prescribes" rule structurally true, not just stated. It's enforced in code paths, not only in prompts. For example, the Fulfillment Agent only ever sees a doctor-signed prescription, never an unsigned draft, by construction.

Shipping a genuinely complete product surface in the time available. Not just a chatbot demo, but real sign-up flows for three different user types, a working prescription PDF pipeline, live voice and video calling, and a full fulfillment lifecycle from doctor sign-off to pharmacy dispensing.

What we learned

Two different "emergencies" are not the same design problem. It would have been easy to build one generic "something's wrong" alert and call it done. Working through why an alarm helps in one crisis and actively harms in another is what made this feel like a real product decision instead of a feature checkbox.

Honest gaps are more defensible than confident guesses. Everywhere we couldn't verify something in real time, whether drug classifications or license registries, we flagged it clearly in the code and the README instead of quietly treating placeholder data as fact.

The boring infrastructure decisions mattered as much as the agent design. Getting persistence, authentication, and race-safe fulfillment right took at least as much care as the agent prompts did. A multi-agent system is only as trustworthy as the state it's built on top of.

What's next for Knot

Real drug-classification data verified against NAFDAC's actual registry, a resolved path for MDCN and PCN verification that doesn't depend on a per-lookup fee blocking onboarding, and continued work on reducing model latency in the live consult flow.

Built With

Share this project:

Updates

Submission history