Home
All projects

VetCaseIQ

A second set of eyes for complex veterinary cases.

The VetCaseIQ application, headlined "Literature-backed differentials in minutes." beside a differential framework panel listing hepatic, inflammatory GI and endocrine considerations with confidence levels.
Status
LiveShipped and publicly available.
Started
Updated
Role
Founder, Product Design, Systems Architecture, QA & Validation, Deployment, Customer Discovery
Built with
  • Next.js
  • React
  • TypeScript
  • Node.js
  • OpenAI API
  • PubMed
  • Europe PMC
  • SQLite
  • Hetzner Cloud
  • Caddy

Overview

VetCaseIQ is a veterinary case-review application I began building around a simple idea: the patient record already exists, so a veterinarian should not have to manually rewrite the case into an AI prompt before getting a second structured review.

The core workflow is document-first. A clinic uploads the available records. VetCaseIQ extracts and organizes the case, identifies missing information, develops and reviews differential diagnoses, highlights important rule-outs, retrieves relevant veterinary literature, and produces a structured report for veterinarian review.

What began as “upload a record and generate a report” evolved into a multi-stage reasoning and validation system.

VetCaseIQ is deployed as a controlled beta. It is designed as research and decision support for veterinary professionals, not an autonomous diagnostic product, and its reports explicitly require veterinarian judgment.

Upload First. Questions Later.

Complex cases often contain the information needed for a strong second review, but it may be distributed across histories, laboratory reports, imaging, medications, and multiple visits.

The original workflow principle became:

Upload first. Questions later.

Instead of asking the user to reproduce information already present in the chart, VetCaseIQ reconstructs the case first and then asks targeted follow-up questions only where something appears genuinely missing.

The Start a case review screen, offering a Quick Case Review and a Comprehensive Case Review, with the instruction to enter only the information you have because empty fields are treated as
The intake screen states the contract directly: enter only what you have, and empty fields are treated as "Not provided" rather than as questions to answer first.

That changed the product from a chatbot interface into a document-processing and reasoning pipeline.

A Pipeline, Not One Prompt

The application is built with Next.js, React, TypeScript, and Node.js and runs on Hetzner behind Caddy.

Generative stages handle tasks that benefit from language-model reasoning: clinical extraction, candidate discovery, differential reasoning, QA, synthesis, and adjudication.

Six capability cards in the application: organizes the case, spots patterns and contradictions, builds a differential list, highlights do-not-miss risks, summarizes what is missing, and offers a condensed or detailed view.
The same pipeline described to the user as six outcomes — including the two that only exist because deterministic stages police the generative ones: contradictions surfaced, and missing information called out.

Deterministic stages handle claims the software can verify more directly.

Examples include:

  • whether a report claim contradicts a laboratory value;
  • whether a suggested diagnostic has already been performed;
  • whether a do-not-miss flag has enough case-specific evidence;
  • whether report sections contain duplicate items;
  • whether literature actually made it from retrieval into the final rendered differential;
  • whether later pipeline stages are silently increasing confidence without new evidence.

That last category became particularly important.

One Case, End to End

The clearest way to describe the output is to walk a single case through it. This one is a retrospective test case from the validation corpus: a 15-week-old Maltese puppy presented after one day of lethargy and vomiting, with icterus, marked azotemia, severely elevated liver enzymes, an inflammatory leukogram and an incomplete vaccination history. Everything below came out of the deployed system from the uploaded record.

The report opens by stating what it is not. The header, the safety notice and the case snapshot all land before a single differential, because the document is a research framework for the attending veterinarian rather than a diagnosis.

The first page of a VetCaseIQ report: the heading Differential-support report, a clinical safety notice stating the tool does not diagnose and that the veterinarian remains responsible, and a case snapshot listing species, breed, age and sex above key signs and key abnormal values.
Page one of the generated report. The case snapshot is reconstructed from the uploaded record — signalment, key signs and key abnormal values — and the safety notice sits above all of it rather than in a footer.

The differential framework follows the reconstructed problem list. Each candidate carries a likelihood, an urgency, and three separate scores: how strong the evidence is, how much it matters if missed, and how complete the evidence actually is. Splitting those apart is deliberate — a differential can be urgent and under-evidenced at the same time, and collapsing that into one confidence number is how a report starts sounding more certain than the case supports.

The AI-generated problem list followed by the differential diagnosis framework, whose first entry, Leptospirosis, is marked medium likelihood and potentially urgent with evidence 70/100, urgency if missed 90/100 and evidence completeness 55/100, above columns of supporting and nonspecific findings.
Leptospirosis leads at medium likelihood — evidence 70, urgency if missed 90, completeness 55. Supporting findings, merely nonspecific findings and contradictory findings are listed separately rather than blended into prose.

Rule-outs are attached to the differential they belong under, each with the testing that would settle it, and each with a caveat explaining why it sits where it sits.

A rule-out panel headed Specific rule-outs to consider under this syndrome, listing acute bacterial sepsis and acute pancreatitis with SIRS, each with the reasoning and the tests that would discriminate them, followed by a caveat explaining why the syndrome was held at medium likelihood.
Rule-outs under SIRS, each with its discriminating tests. The caveat is the part that matters: the syndrome is held at medium likelihood despite a high evidence score, because evidence completeness is low.

The report ends by being explicit about what it does not know. Missing information is a first-class section, not a hedge buried in the prose, and it feeds the suggested questions and the diagnostics worth discussing.

A pattern recognition summary followed by a missing information list — Leptospira serology or PCR, complete urinalysis with sediment, urine culture, repeat renal values after correction, further infectious disease testing, liver function testing, additional imaging, temperature measurement — and the start of a suggested questions section.
What the case does not contain, stated plainly. Temperature was never recorded, so SIRS could not be fully assessed — and the report says so instead of reasoning around the gap.

Preventing Later Stages from Undoing Better Reasoning

One test case showed a differential becoming more confident and gaining a do-not-miss flag after QA despite receiving no new discriminating evidence.

The prose still sounded reasonable. The pipeline state was not.

I added stage authority and promotion provenance so later stages cannot silently re-promote a candidate that an earlier reviewed stage had downgraded unless there is new evidence supporting that change.

That reflects a broader rule in VetCaseIQ: a polished final paragraph is not enough. The system has to preserve why a conclusion earned its position.

Every generation therefore keeps an observability view beside the report. It records which model ran which stage, whether any fallback or prior saved state was used, and which stage each published section was taken from — then prints the raw pre-QA differentials and the post-QA set side by side so a promotion or a demotion can be read directly instead of inferred from the finished prose.

An observability view of one generation: a pipeline summary table listing the generation id, the model used for extraction, reasoning and QA, whether fallback or prior saved data was used, and that the final differentials, suggested questions and literature all come from post-QA, above the start of a raw pre-QA differentials table.
The debug view for a single generation — stage models, fallback and prior-state flags, and the stage each published section came from. The pre-QA and post-QA differential tables follow, which is what makes an unearned promotion visible.

Avoiding Benchmark Overfitting

Repeated testing makes disease-specific fixes tempting.

I explicitly moved away from disease-name boosts, fixture-specific ranking patches, or injecting known answers into candidate sets. Fixes are expected to improve generic evidence quality: contradiction handling, grounding, specificity, stage authority, evidence normalization, and provenance.

The goal is not to make one benchmark case pass. It is to make the reasoning rules more defensible across unfamiliar cases.

Literature Has to Survive the Whole Pipeline

VetCaseIQ retrieves veterinary literature through PubMed and Europe PMC and associates sources with individual differentials.

A useful failure mode was discovering that verified papers could be successfully retrieved but disappear or become disconnected from the final differential structure.

That reinforced a lesson repeated throughout the project: successful intermediate computation means very little if the user-visible final object is inconsistent.

The final validation layer therefore checks the rendered state, not just the existence of good intermediate data.

Measuring the Real Bottleneck

Report generation was also slower than the first instrumentation suggested.

One measured report took roughly 347 seconds, while the initial timing system accounted for only around 90 seconds of work. Most of the runtime was effectively invisible.

I rebuilt observability around request-scoped stages, model calls, and external API timing so performance work could be based on measured bottlenecks instead of guesses.

Development and Validation Workflow

VetCaseIQ is not a solo build. I lead product, workflow and operations, working with a small advisory team: Dr. Jacob Piñón, a resident physician, advises on clinical reasoning workflows and how complex case information is prioritized and communicated; Akshay Basi, an MD candidate, advises on structured case review and differential organization; and Maxon Bowman advises on data structure, reporting logic and analytics workflows.

Claude Code serves as the primary implementation agent, while I direct architecture, product behavior, test design, and clinical-output evaluation.

There is an important split in validation. The local coding environment can prove deterministic tests and builds, but it cannot execute the complete real API-powered report pipeline. A change therefore is not accepted merely because the code compiles.

The implementation agent passes the local regression suite; I deploy the change and run actual cases through the real system before accepting clinical behavior.

That separation became essential as the automated suite grew beyond 1,100 tests.

Current State

VetCaseIQ is a deployed controlled-beta application capable of completing the case-review workflow and producing multi-page reports from uploaded cases.

The core product works, and several independent test cases have produced the expected primary differential. The latest recovered workflow version was intentionally treated as a partial clinical-correctness release rather than a finished validation milestone.

The current work is about confidence, not feature count: provenance, literature consistency, hierarchy, evidence specificity, latency, additional independent cases, and more feedback from practicing veterinarians.

The goal is not to make the report sound more certain. It is to make every conclusion easier to trace back to the evidence that earned it.

Milestones

  1. Document-first concept created

    Started from the idea that clinics should upload the existing record instead of rewriting a case into an AI prompt.

  2. Extraction and reasoning split into separate stages

    Replaced the single-prompt approach with a document-extraction stage feeding a separate differential-reasoning stage, so a weak reconstruction could no longer hide inside a confident report.

  3. Deterministic checks added around the generative stages

    Introduced contradiction, duplicate and already-performed-diagnostic checks that run against the case data rather than the prose.

  4. Stage authority and promotion provenance

    Made every differential carry the stage that placed it, so a later stage cannot silently re-promote a candidate an earlier reviewed stage downgraded without new evidence.

  5. Literature tied to individual differentials

    Moved retrieval from a general reading list to sources attached to specific differentials, and added a check that they survive into the rendered report.

  6. Per-generation observability view

    Added a debug report recording stage models, fallback usage and pre-QA versus post-QA differentials for every generation.

  7. Application deployed

    Moved the end-to-end case-review workflow into a controlled-access deployed beta.

  8. Validated against published Cornell cases

    Ran retrospective testing against published eClinPath diagnostic-challenge cases from Cornell, using only the information available before the published diagnosis and comparing the top differential against it.

  9. Customer discovery began

    Started direct outreach to veterinary companies and clinics while continuing product validation.