Inspiration

Clinical trials mostly fail because sites can't enroll patients. In Regeneron's own figures, 11% of trial sites enroll zero patients and 37% under-enroll. Each enrolled patient costs about $41,117.

Before building, we talked to a Regeneron clinical operations rep. His point changed our plan: you have to convince doctors more than patients. A trial needs a facility and an investigator who already has the right patients, and only then is recruiting worth thinking about.

So we flipped the problem. Instead of hunting for patients, we find the doctor who already has them and bring the trial to that doctor, with the patients already found. And not just any doctor: established investigators already get every sponsor's call. Trialist is built for early-career clinicians, doctors a few years out of training in private or community practices, who want to build an academic name through research.

What it does

Trialist is a web app for a doctor's practice.

  • Recommended trials: we sync every open Regeneron trial from ClinicalTrials.gov (147 right now) and pre-screen the practice's own patients against them. The doctor sees trials as cards, sorted by therapeutic area.
  • Honest counts: opening a trial shows how many patients are pre-screen candidates and how many need chart review. That second group covers criteria a machine can't settle, like "adequate renal function". We never hide it or count it as a pass. The engine pre-screens; only a human screening visit confirms a patient.
  • One click to start outreach: when the doctor accepts a trial, Ava, our voice agent, calls those candidates from the doctor's own office:
    • She confirms the patient's date of birth before saying anything about the study. Our server checks it; the AI never sees it.
    • She asks a couple of questions the chart can't answer, then books a screening visit.
    • No answer gets a voicemail with no study details, then a text offering three real times. After three tries, the patient goes to the office staff.
  • Campaigns and Calendar: the doctor follows each trial live (called, reached, booked, needs a person) and sees visits appear on the practice calendar as Ava books them.
  • The patient stays with their doctor. Each practice only ever sees its own patients.

How we built it

  • App: Next.js (Pages Router), React and Tailwind, with Supabase (Postgres) as the database. A scheduled job pulls trials from the ClinicalTrials.gov API into Supabase.
  • Patients: 2,000 synthetic New Jersey patients generated with Synthea. Each county stands in for one practice, so our demo practice has 200 patients. The Supabase table plays the role of the practice's own records system.
  • Matching engine: pure TypeScript, run in four steps:
    1. Age and sex are checked in code.
    2. Condition: a lookup decides whether the patient has the trial's disease at all.
    3. Criteria: Gemini turns each trial's free-text eligibility criteria into structured questions. Lab thresholds and age limits stay in code.
    4. Judgment calls go to Jev, TypeSafe's decision model, accessed through OpenRouter. Jev gets a de-identified summary of each patient: no name, ID, birth date or location, and dates as relative time.
  • Turning answers into results: code, not the model, makes the final call. Any "no" means not a match, any "unknown" means chart review, otherwise the patient is a candidate. A low-confidence "no" (probability under 0.6) becomes chart review instead of ruling someone out.
  • Keeping it cheap: results are cached by a hash of the inputs, so reruns only pay for what changed, and a spending cap stops a run before it gets expensive.
  • Voice agent (Ava): FastAPI and SQLite, with an ElevenLabs conversational agent running on Claude, and Twilio for calls and texts. Patients can text back: a number books a time, "after 5" moves the next call, STOP stops everything. Calling the office back picks up the conversation.
  • Deploy: one Vercel project running the app, the engine and the caller.

Challenges we ran into

  • Most eligibility criteria aren't machine-checkable. "Clinically significant", "life expectancy over 6 months" and "able to comply" need a person. We made "unknown" a real result everywhere instead of forcing a yes or no.
  • Privacy at every boundary:
    • Jev only ever sees de-identified summaries.
    • Before identity is confirmed, ElevenLabs only gets the patient's first name, the office and the callback number.
    • Texts and voicemails never name a study or a condition.
  • Model mistakes: in our proof-of-concept test, Jev's wrong rejections had a median confidence of 0.56 and its correct ones 0.86. That's where the 0.6 cutoff came from.
  • Gaps in synthetic data: Synthea has no family history, few lung-function results and about one weight per year. Those gaps show up as chart review, not as failures.
  • Making a safe phone agent: handling emergencies, opt-outs, voicemail machines and confused callers without ever giving medical advice.

Accomplishments that we're proud of

  • The whole loop works end to end: trials sync, patients get pre-screened, the doctor accepts, Ava calls, and visits land on the calendar live.
  • Three-state results (candidate, chart review, not a match) carry through from the engine to the doctor's screen.
  • Patient data stays scoped to one practice, and identifiable data never goes to the matching model.
  • 37 tests on the engine's criteria preprocessing.
  • A calm, card-based interface a busy clinician can read at a glance.

What we learned

  • The doctor is the customer. The bottleneck is upstream of the phone call: the patients have to be found before anyone dials.
  • Honest uncertainty beats a bigger number. Showing "14 candidates, 6 need chart review" earns more trust from a clinician than an inflated count.
  • Language matters. The engine pre-screens; it never says it qualifies anyone. Only a screening visit can do that.
  • Let models answer questions and let code make decisions. Rules stay testable and explainable, and the model's role stays small and clear.

What's next for Trialist

  • Connect to real records systems through FHIR instead of synthetic data.
  • Benchmark our candidate lists against a real study coordinator's manual pre-screening.
  • Hold back small counts (under 5) when counts leave the practice, so a rare condition can't identify a patient.
  • A sponsor view: a map of which practices could fill which trial, built only from de-identified counts.
  • Have clinicians check Jev's answers, and do the HIPAA and compliance work a real deployment needs.

Built With

nextjs, react, typescript, tailwindcss, supabase, postgresql, python, fastapi, sqlite, elevenlabs, twilio, claude, gemini, openrouter, jev, synthea, vercel

Built With

Share this project:

Updates

Submission history