A patient who just had a seizure can't fill in a sixteen-field form. But they can talk. Wazzy takes a 5-minute voice or chat conversation and produces a clinically rich, structured record — and a quantified before/after for every medication change.
iOS · watchOS · Web — three surfaces from one FastAPI backend
Model
AWS Bedrock · Claude Haiku 4.5
Data
AWS DocumentDB · versioned frameworks & prompts
Tests
125 integration tests · zero real AWS calls in CI
$0.15/mo
Typical patient LLM cost
3-stage
Orchestration per turn — planner · agent · parser
16
Structured medical fields extracted from conversation
A neurologist sees the patient every three to six months.
By the time the appointment comes round, the patient or their caregiver can rarely recall what happened with the granular detail clinical decisions need. When exactly. How long. What they were doing. Witnesses. Injuries. Whether it matched a known pattern. The data the doctor needs is gone — and titrating medication on vague impressions is how patients stay sick.
Existing trackers — Epsy, Helpilepsy, paper diaries — all share the same friction: sixteen-field structured forms that patients won't fill in consistently, especially when stressed or post-ictal. Compliance drops within weeks. The data layer of epilepsy care has been broken for as long as smartphones have been around.
What we replaced16 fields
A 16-field form, after a seizure
Date & time
Duration
Onset style
Triggers
Sleep last night
Medication adherence
Witness present
Witness account
Post-ictal state
Injuries
Unusual symptoms
Location
Activity at onset
Mood / stress today
Pattern match
Notes
— Compliance drops within weeks.
But they can talk.
One user message. Three LLM calls, none of them fragile.
We do not ask one model to be the assistant and extract the data and decide what to do next. Each LLM call has exactly one job, exactly one prompt, exactly one schema. The conversation never drifts because no single call has the freedom to drift.
wazapi.wazure.app · liveTurn 1 / 3
Patient
I had another seizure this morning
Wazzy
I'm sorry that happened. Can you tell me roughly when it started, and how long it lasted?
Where does the conversation need to be?tool: plan_mode_transition → report_episode · new event referenced
Conversation agent~600 ms · $0.002
What does Wazzy say next?Output (assistant reply) · user just reported a new event
Per-mode parser~400 ms · $0.003
What structured data did the user just provide?update_seizure_parsed_state · extracted: { episode_type: GTC?, date_hint: today, time_hint: morning }
This turn cost $0.0060Session $0.0060
Prompts and field schemas are data.Iterate on the AI without a code deploy.
Both the prompts that drive the planner, parsers, and agent — and the field specifications they extract against — live in MongoDB as versioned documents. Exactly one version per prompt is active at any time. Admins draft new versions, A/B them privately in a playground that never touches real patient records, then promote with a one-click rollback safety net.
You are Wazzy, a calm seizure-diary assistant.
Keep replies under 25 words. Ask one question at a time.
Do not diagnose. Do not advise on medication.
For caregivers, address the caregiver directly.
On a "first seizure ever" admission, surface the regional
emergency number for the patient's locale once,
then continue logging.
date · timeonset stylepost-ictal durationwitness presentsleep hours last nightmedication adherenceconsciousness levelwitness accountstress todayobserved_onset · NEWaudible cry · NEWtongue bite · NEWincontinence · NEW
Parser tool schema regenerates automatically — no code change for new fields.
Playground
A safe place to change Wazzy's mind
Every admin gets a private playground. Draft a new version of a prompt, replay an old conversation against it, compare outputs side by side, capture the result as a "PlaygroundSession" record. Promote only when the diff is what you intended. Real patient records never see a draft prompt.
We use exactly one model — Claude Haiku 4.5 — for every LLM call. Prompt-caching on Bedrock makes repeated system prompts almost free. Whisper is only called when the on-device transcriber fails. Polly is only called for branded longer audio. Every Bedrock and Whisper call writes an LLMCallLog row with estimated cost, so admins watch real spend per patient, per purpose, per model — in real time.
A heavy power user logging thirty events a month, with an admin actively iterating in the playground, sits under two dollars. The bill never surprises anyone.
Per turn
Mode planner120 ms · $0.001
Conversation agent600 ms · $0.002
Per-mode parser400 ms · $0.003
A typical month
~4 events / month × 4 turns each$0.11
Nightly Layer-1 pattern discovery$0.03
Layer-3 layperson summary$0.01
Typical patient — all-in$0.15
Every LLM call logged with model, tokens, latency, and estimated USD. The admin "LLM cost (30d)" KPI aggregates from this. No surprise bills.
One FastAPI service. Three radically different clients.
The same 38 admin endpoints and 7 mobile-bulk endpoints serve three jobs — a watch that listens, a phone that diaries, and a web cockpit that tunes the AI. The mobile team caches locally and syncs with since=last_pull_at. The admin team filters and sorts at the database. Every client uses the same JWT, the same schemas, the same FastAPI.
watchOS
Voice-only · the hardest moment
The watch is what a patient touches the second after a seizure. No keyboard. No reading. Just "Hey Siri, ask Wazzy to record a seizure." The watch reads short Wazzy replies out loud using on-device AVSpeechSynthesizer — free, fast, offline.
On-device SFSpeechRecognizer for the happy path
Posts raw audio to /api/chat/messages/audio only on low confidence
Reads replies via on-device AVSpeechSynthesizer (Polly only for branded long-form)
iOS app
The patient's diary
Five screens. The dashboard with KPIs and trends. Chat with the orchestrator. Reports list for events and interventions. Insights with the Layer-3 markdown summary. Settings. Offline-tolerant — GRDB on device, keyset-paginated bulk sync via /api/{resource}/all?since=<isoDateTime>.
Offline cache via GRDB · resumes mid-conversation across app restarts
Insights tab activates once 3+ reports exist (Layer 3 is the gate)
Angular admin
The operator's cockpit
Twenty screens for the clinic operator. Patient management. Conversation playback with planner+parser traces. Prompt editor. Framework editor. LLM playground. Analytics dashboards. Server-side filtered DataTables — the admin UI never holds the full dataset.
POST /api/admin/{resource}/grid — paginated, filter & sort at the database
Conversation replay with planner trace + parser tool calls visible
One-click prompt rollback · A/B test in playground without touching real records
125 integration tests. Zero real AWS calls in CI.
We mock AWS once and run end-to-end through every endpoint, every planner branch, every parser tool — in about thirty seconds, on a developer laptop. No flaky integration suite, no surprise prod-only failures, no debugging an LLM mock for a week. The whole conversation orchestrator is exercised under mongomock-motor with httpx.AsyncClient.
BackendFastAPI · gunicorn · uvicornPython 3.12 · Beanie · MotorArq · Redis · async jobsJWT (tymon · same as parent)
If you're building a conversational AI in a sensitive domain, the orchestration pattern is portable.
Three-stage orchestration. Versioned prompts as data. One model, many tight prompts. Per-call cost accounting. We have applied this pattern to clinical conversations, legal intake, and support — the domain changes, the architecture stays.
If you're thinking about AI for your business and you want to talk to someone who will tell you the truth — including when AI is the wrong answer — book a call. We'll spend 30 minutes understanding what you're trying to do, what you're worried about, and whether we're the right fit.
No sales pitch. No deck. No follow-up pressure.
Calls are taken by a senior engineer who has shipped the work, not a BDR.
You'll walk away with at least one practical idea — even if we never work together.