Inspiration
Every October, someone sits at the kitchen table with a parent's pill bottles, a stack of plan mailers and a Medicare website that asks for twenty fields before it shows a single price. Most families give up and keep whatever plan they had. That choice can cost hundreds of dollars a year, or a drug that is suddenly not covered.
The numbers say this is the norm, not the exception:
- 35.2 million people are in Medicare Advantage in 2026 (KFF), choosing among 32 drug plans on average (KFF).
- 69% of people with Medicare did not compare their options during the most recently measured open enrollment, and 82% of people in Medicare Advantage drug plans did not compare their drug coverage with other plans (KFF).
- When Medicare Advantage prior-authorization denials are appealed, 80.7% are overturned, yet only 11.5% are ever appealed (KFF).
The official tool is accurate but built like a form. Most other help is paid for by insurers. We wanted the thing a family actually needs: someone neutral who listens, does the math correctly, and says plainly what to do next.
What it does
Medicare Helper does one job well: help a family pick the right Medicare drug or Medicare Advantage plan for the medicines someone actually takes. Every dollar figure comes from Medicare's own public data; the AI never makes up a number.
- Tell it, or show it. Type, talk, or snap a photo of a pill bottle. It reads the label, matches the exact drug and strength, and asks only what is still missing (one question at a time in senior mode).
- See the best plans for these medicines. Every plan in the county, ranked by a typical year's total and a bad year's ceiling, with star ratings, drugs not covered, prior-authorization flags, cheaper generic switches, and the new Medicare-negotiated drug prices. Plan Finder gives you a table; this says in plain words why one plan costs more and where the catch is.
- Check the current plan. "Should I stay?" gets a verdict first: next year's premium and out-of-pocket max, the best alternative and what switching saves.
- Ask what families actually ask. Is the doctor in network? Could they get Extra Help? What if they use mail order?
- Get the family on the same page. One tap writes a short summary of the results in English or Spanish (or 16 other languages, including Haitian Creole, Chinese and Vietnamese), every number checked against the comparison, plus a calendar reminder for the December 7 deadline.
After you choose: the letters that follow. The same assistant reads what Medicare and the plan send later: a drug or care denial (deadline computed from the official rules, numbered steps, a drafted appeal where the person fills in the medical details), a notice that rehab or nursing-home care is ending (the fast-track appeal deadline and a call script), and a bill checked line by line against the plan's statement.
Around that: a big-text senior mode (yes/no buttons, read-aloud) and a family mode (a sidebar of the people you help, a table view, a printable page); full Spanish; a home page per person with a checklist. Profiles stay on the user's own device.
How we built it
The core design choice: models talk, read and explain; a deterministic engine does every calculation. A plan comparison that is wrong by $400 is worse than no help, so no number comes from an LLM.
- Agent: NVIDIA Nemotron 3 Super on Nebius Token Factory. Tool calling over eleven tools (find drug, find county, compare plans, check current plan, check plan news, check doctor, Extra Help screen, read Medicare letter, check bill, read label, save profile). The prompt forbids stating any number a tool did not return and asks for a verdict first, in plain words.
- Photo reading: Nemotron 3.5 Super VL + Nemotron 3.5 Lightning. The vision model transcribes the photo; Lightning turns the text into strict JSON (thinking turned off: it cut a label read from 31 s to 8 s). Checks confirm the extracted drug name and quantity actually appear in the transcript, and anything unsure is asked back.
- Cost engine (Python + DuckDB, no LLM). The full Part D benefit for 2026 and 2027: deductible, the $2,100 / $2,400 out-of-pocket cap, $35 insulin, tiers and copays per pharmacy type, quantity limits, and CMS's official negotiated (Inflation Reduction Act) prices. Medical costs use each plan's copays and out-of-pocket max with an estimated health-use level.
- Data pipeline. CMS monthly and quarterly Part D public use files (53 million pricing rows), the MA/PDP landscape, the negotiated-price file and 2025-to-2026 formulary history, rebuilt weekly by GitHub Actions into versioned Parquet releases that the app picks up on its own.
- Tavily searches insurer provider directories for a named doctor after an NPPES lookup confirms who the doctor is; results are reported as leads to confirm, never as "in network".
- App. FastAPI streaming to a React front end (English and Spanish, senior and family modes), Docker + Caddy on a Nebius AI Cloud VM.
- Measured, not guessed. Every model call is a named, versioned task with tokens and latency logged (never health content), so we can say what a turn costs and what got faster.
The agent only decides what to ask and which tool to call; every dollar figure comes back from the engine, which reads only CMS data.
Workflows where we can, an agent where we must. We followed Anthropic's Building effective agents: start simple and add model calls only where they earn their place.
- Routing without an LLM. Official notice titles ("Notice of Denial of Medicare Prescription Drug Coverage", "Medicare Summary Notice") are matched by keyword; Lightning is only the fallback for unknown letters.
- One short pipeline per task. Each letter type runs a fixed chain: extract fields, verify dates and phone numbers against the transcript, compute the deadline in code (65 days for a Part D redetermination, 60 days plus 5 for IRMAA), then draft one argument paragraph. The bill check is plain code.
- The evaluator is code, not another model. Every drafted paragraph and family summary is checked for numbers not in the facts, promised outcomes, invented medical history ("I tried metformin") and the wrong language. One rewrite, then a plain fallback.
- The agent loop only for the open-ended part: the conversation itself.
Challenges we ran into
- Matching Medicare Plan Finder to the dollar. The Part D benefit has phases, caps, per-pharmacy cost sharing and quantity limits that interact. We built a 440-case answer key from Plan Finder and iterated until the engine agreed with it.
- Speed on 53 million price rows. A county comparison first took 21 s; narrowing to the person's drugs before pricing and caching national prices brought it to about 1–5 s.
- Models that think too much. The extraction model spent 3,700 tokens reasoning to fill a ten-field JSON. Turning thinking off for extraction kept accuracy and cut the time by 95%.
- False positives in doctor search. Web results matched surnames, old directories and look-alike domains. We now require a full-name match, check the domain belongs to the insurer, flag older directory years, and ask when several doctors share a name.
- Writing for an 80-year-old. Tables in chat, two questions at once and words like "formulary" lose people. Senior mode asks one question, offers yes/no buttons only when the question really is yes/no, and reads answers aloud.
- Privacy without accounts. Remembering each person's medicines without storing health data on a server meant keeping the profile on the device and sending it only for the current turn.
- Drafts that invent a medical history. Asked to argue a denied Ozempic claim, the model wrote "I have tried metformin", which nobody had said. Now medical details are [placeholders] the person fills in, and a code check rejects first-person medical claims.
- Numbers in other languages. A Chinese summary invented a "confirm by September" date, and "December 7" comes back as 12月7日. The number check now knows month names, and summaries may mention only deadlines that are in the facts.
- Evals that lied. Our agent eval once reported every conversation as PASS while parallel writes were corrupting a drug cache and crashing the comparison tool. Another run passed while pricing "Ozempic 1 mg" as an oral tablet instead of the pen. Now the eval fails on any tool crash and checks what was actually priced, and both bugs are fixed in code.
Accomplishments that we're proud of
It agrees with Medicare's own tool. Against a Plan Finder answer key of 10 personas × 44 Miami-Dade plans:
| Check | Result |
|---|---|
| Annual drug cost within 10% or $100 | 432 of 440 (98.2%) |
| Coverage disagreements (covered vs not) | 0 of 440 |
| Priced estimates within $1 | 258 of 380 |
Spot check, Orange County FL, Eliquis + atorvastatin: our top plan (DrSelect-CFL HMO, $0 premium, $0 drugs, $3,500 max, 4.5 stars) is also Plan Finder's #1 with the same numbers.
The agent passes conversations it has never seen. 150 of 150 scripted conversation runs pass: a dev set plus three held-out sets, each scenario run three times, every run scored by code rather than another model. 43 more tests cover the guard rules that rewrite a draft when a number did not come from a tool.
It costs about $0.002 per chat turn on Nebius Token Factory (median of logged turns at public prices), so a full plan comparison is roughly a cent. That keeps the running cost small.
It asks for nothing it shouldn't. No accounts, no server-side profiles, no conversation logs in production, photos deleted after reading (a bill is kept at most 30 minutes to compare it with the statement), and it never asks for Medicare or Social Security numbers.
It speaks to both people at the table: the 80-year-old (big text, one question, yes/no, read-aloud, Spanish) and the adult child managing both parents' plans (sidebar, tables, print, calendar).
What we learned
- Split the work by what each part is good at. Open models are excellent at understanding a messy sentence or a blurry label and at explaining a result kindly; a small rules engine is better at arithmetic. Keeping the two apart is what made accuracy measurable.
- An answer key changes everything. Once 440 cases were checked against Plan Finder, every engine change became a number going up or down instead of a debate.
- Measure every model call. Naming and versioning each AI task with its tokens and latency is how we found the 25-second extraction and the 21-second comparison, and proved the fixes.
- Accessibility is a product decision, not a font size. One question at a time, a verdict before the details, and buttons only when they fit the question mattered more than styling.
- Medicare data is public but not easy. The files are large, change monthly and use their own vocabulary; treating data as a pipeline with versioned releases, not a one-time download, kept results current.
What's next
- 2027 plans as soon as CMS publishes them. The engine already implements the 2027 benefit rules, and the weekly pipeline loads CMS's CY2027 plan and formulary files as soon as they are published. Every answer shows the date of the plan data it used.
- Real families, this enrollment season. We have not tested with real users yet: every accuracy number above is measured against Medicare's own tool, not people. Next is sitting with SHIP counselors and caregivers, in English and Spanish, and fixing what confuses them.
- Pharmacy-level prices (dispensing fees and preferred pharmacies) to close the last gaps with Plan Finder.
- Native-speaker review. Ask Haitian Creole, Vietnamese and Chinese speakers to review summaries and letter drafts, then add prior-authorization requests and hospital discharge notices to the letter types.
- Work with the people who already help. Offer it to State Health Insurance Assistance Program (SHIP) counselors and community groups, so one counselor can help more families each open enrollment.
Log in or sign up for Devpost to join the conversation.