Inspiration
A few months ago my father had sinus surgery. Afterwards something wasn't right — a constant irritation on the left side, like something was still stuck in there. He talked about it at home for weeks. He knew exactly what it felt like.
Then he'd go for his check-up, and it would come out wrong. Seven minutes in a room, doctor already behind schedule, him nervous. Half of what he meant to say never got said. At the next visit he was told it was probably just his imagination.
I don't think that doctor was careless. He had seven minutes and a patient who couldn't explain himself. That's the actual failure — not the medicine, the room. My father had the information. He just couldn't get it out in time.
So I built the thing I wish he'd had in the waiting room.
What it does
You write what's been happening in one box, in your own words. No forms, no medical vocabulary, no dropdowns.
Four independent perspectives then read it — heart and circulation, hormones and metabolism, nerves and brain-body, and everyday causes like medicines, infection, sleep and stress. None of them can see what the others wrote.
Each one is told what the other three already cover, and is allowed to say "this isn't my angle, I have nothing honest to add." That matters more than it sounds — it's what makes their agreement mean something when it happens.
Then they challenge each other. One perspective questions another's reading and it has to defend or revise it. Finally a separate pass looks for what all four of them walked past.
You leave with one printable page: the thing you're most afraid of answered directly, what stands out, topics worth raising (never diagnoses), the questions to ask, what's still missing, and where the perspectives disagreed. Every line traces back to something you actually wrote.
It is not a doctor and it does not diagnose. It says so on every page.
How we built it
The engine is written in Jac, where the unit of computation is a walker traversing a graph. That mapped directly onto the problem: your story becomes a graph — your words as evidence nodes, each perspective's view attached to the evidence that supports it, challenges as edges between two perspectives. The reasoning structure and the data structure are the same object, so the final brief is composed by walking the completed graph rather than re-prompting a model with a transcript.
The performance decision that made it work: zero per-node model calls. As a perspective traverses your evidence it emits a reading event immediately, with no model involved. Only after it has filtered to its own relevant subgraph does it make exactly one scoped synthesis call. Cross-examination is capped to a single pair. That's about 8 model calls for a whole session, landing near 65 seconds.
Around it: FastAPI streaming events over Server-Sent Events, React on the front, and a React Flow radial graph where you can watch each perspective read your evidence and argue in real time — with playback controls, so you can scrub and replay the debate.
Safety is deliberately not AI. safety.py is a deterministic pattern table — chest pain with radiation, sudden worst-ever headache, one-sided weakness, breathing difficulty, suicidal ideation, infant fever, uncontrolled bleeding, anaphylaxis — that runs before any model call. A model outage cannot suppress the emergency path. It fires in about 10 milliseconds.
Health text never touches disk. The case is handed to the engine in memory, sessions live in RAM and expire, and there is no database.
Challenges we ran into
Four voices that all said the same thing. The first working version had every perspective confidently return the same answer — the "neurological" one wrote about potassium. Four agents agreeing isn't a council, it's one agent copied four times. The fix wasn't a better model, it was telling each framing explicitly what the other three cover and making an honest "uncertain" an acceptable answer. That single change is the difference between a demo and a product.
A green test suite that was lying. My local checks all passed while the live path was broken. The suite blanked every API key to stay free — which meant it only ever exercised the offline fallback and never ran the real engine once. Every live defect hid behind a passing build. I now have a check that reads the prompts themselves, because that's the class of bug that got through.
Models inventing citations. Perspectives would cite evidence IDs that didn't exist, so the page pointed at words the user never wrote. Everything that reaches the brief is now filtered against real IDs — a claim with no provenance loses its citation rather than fabricating one.
Getting the visualisation to tell the truth. The graph opened almost empty and nodes physically jumped as evidence appeared, and recorded runs blew through 22 events in a second and a half. Fixed by putting the full evidence list in the very first event, and moving playback pacing out of the server and into the browser.
Accomplishments that we're proud of
Perspectives that will say "I've got nothing here." On a stomach story, three of the four abstain and the fourth finds a daily painkiller nobody had connected.
A brief where every single line points back at the user's own words — no invented provenance.
An emergency path that no model failure can silence.
A privacy story that's actually true: no database, and nothing written to disk.
And the page prints. Someone can hold it.
What we learned
Agreement between AI agents is cheap and nearly worthless. Disagreement has to be deliberately engineered, and honest uncertainty is more useful to a patient than confident noise.
A passing test suite can hide everything if it's only testing the fallback path.
"We don't have a database" is not the same as "this is private," and the copy has to say the harder, truer thing.
The hardest part of health tech isn't the medicine. It's the seven minutes.
What's next for UNMISSED
More perspectives — gut, musculoskeletal, ENT — since four lanes leave real gaps.
A bring-back loop: note what the clinician actually said and what got missed, so the next visit starts from there.
Other languages, because the people most likely to be dismissed in a consultation are often the ones not speaking their first language.
And the thing I actually want: sitting with clinicians and finding out whether a page like this makes their seven minutes better, not just the patient's.
Built With
- azure-openai
- byllm
- eslint
- fastapi
- framer-motion
- google-gemini
- jac
- jaseci
- litellm
- pydantic
- python
- react
- react-flow
- react-router
- server-sent-events
- tailwindcss
- typescript
- uvicorn
- vercel
- vite
Log in or sign up for Devpost to join the conversation.