Limitations
OpenOnco deliberately does not try to replace a clinician or a full MDT. This page is the complete, honest list of what the engine does not do, where it refuses to generate a plan without additional data, and where the clinical decision stays with the clinician. Knowing the limitations is as important as knowing the capabilities.
2026-04-27 10:44 UTC.
1. Detecting missing data — the Open Questions mechanism
The engine does not make a decision when required data is missing. Instead of silently picking a default, it explicitly records which fields are missing and which test or finding is needed. This mechanism is called Open Questions and it is a deliberate part of the MDT orchestrator (Q1–Q6 + DQ1–DQ4 rules per MDT_ORCHESTRATOR_SPEC §3).
Treatment-mode Open Questions (Q1–Q6) — examples from real code
- Q1 — Histology not confirmed: if
disease.idresolves but there is nobiopsy_dateorhistology_report, the engine emits "Treatment Plan generated against ICD-O-3 code only; recommend confirming primary histology before initiating therapy". - Q2 — Stage missing: if Algorithm.decision_tree references staging but the profile has no
stage, the walker falls through to default with a flag "Lugano/Ann Arbor stage required for confident risk-stratification". - Q3 — RedFlag clause references findings absent: if
RF-MM-HIGH-RISK-CYTOGENETICScheckstp53_mutation+del_17p+t_4_14+gain_1qand onlydel_17pis in the profile, the engine does not produce a false negative; it emits "Cytogenetic panel incomplete; high-risk status assessed with partial data". - Q4 — Biomarker required by Indication missing: if
IND-CLL-1L-VENOrequiresBIO-CLL-HIGH-RISK-GENETICSfor default-track selection, the engine emits "IGHV mutation status + FISH del(17p) required to confirm 1L recommendation". - Q5 — Performance status missing: if
ecogis absent, the engine falls back to a conservative default (standard track only) and emits "ECOG performance status required for transplant-eligibility assessment". - Q6 — Drug availability flag: if the selected Regimen contains a drug flagged
nszu_reimbursement: false(e.g. daratumumab in MM), the engine emits "D-VRd: daratumumab not currently NHSU-reimbursed in Ukraine; verify funding pathway before initiation".
Diagnostic-mode Open Questions (DQ1–DQ4) — for pre-biopsy mode
- DQ1 — Tissue location missing: if
suspicion.tissue_locationsis empty, workup matching cannot rank candidates; emits "Tissue location is required to match a workup". - DQ2 — Lineage hint absent: without
lineage_hintthe engine matches on tissue + presentation only, with lower confidence. - DQ3 — Presentation free-text empty: presentation_keywords scoring × 0; only lineage + tissue contribute.
- DQ4 — Working hypotheses not provided: the engine has no preferred direction and prefers the most generic workup (e.g.
WORKUP-LYMPHADENOPATHY-NONSPECIFICoverWORKUP-SUSPECTED-LYMPHOMA).
2. Five personalization gaps
"Personalization" in OpenOnco is rule-based selection from fixed options, not AI generation. This is an intentional architectural stance (CHARTER §8.3 — forbidden prompt patterns). The concrete gaps:
No per-patient dose calculation
A Regimen stores the standard dose
(bortezomib 1.3 mg/m²); it is not multiplied by
patient BSA and not auto-reduced for CrCl < 30 mL/min. The
clinician recalculates. This is deliberate — it keeps OpenOnco
out of FDA medical-device classification.
No response-adapted cycle adjustment
A Regimen pins total_cycles: 6 + 2 maintenance.
The engine does not auto-adapt based on response (PR vs CR
after PET2). A re-staging plan is generated through a separate
revise_plan with a new profile — the clinician
triggers it explicitly.
Genomic matching is bounded by curated biomarkers
If a patient turns up with PD-L1 78%, the engine will not propose pembrolizumab — because no Indication with the corresponding biomarker_requirement exists in the KB. This is a coverage limit (add an entity), not an engine-logic limit.
SupportiveCare is uniform per regimen
PJP prophylaxis is attached to D-VRd for everyone — even for a patient allergic to bactrim. The engine does not know about alternatives (dapsone instead of bactrim). The clinician substitutes.
No cumulative-toxicity tracking across lines
2L+ algorithms are now in for 43 hematologic diseases
(129 2L+ indications), but the profile does not yet
carry prior_treatment_history as a structured
field. A 2L plan for a patient who received bortezomib in 1L
with grade 2 neuropathy — the engine does not know about the
prior exposure unless something new is added; the clinician
interprets prior_lines from free text.
3. Hard CHARTER constraints (will not change)
These are not technical debt — they are deliberate architectural decisions that establish the project's position as non-device CDS and gate FDA / clinical safety.
LLMs do not make clinical decisions
LLMs only assist with: boilerplate code, doc drafts, extraction from clinical documents (with human verification), translation with clinical review. Not: regimen selection, dose generation, biomarker interpretation for therapy choice.
No histology → no treatment Plan
A treatment Plan is generated only when disease.id
or icd_o_3_morphology is confirmed. Otherwise the
engine refuses and switches to DiagnosticPlan mode (workup
brief). revise_plan from treatment back to
diagnostic is forbidden and raises ValueError.
No time-critical recommendations
The engine is not designed for emergency oncology (oncologic
emergencies, time-sensitive infusion reactions). That would
trigger device classification. If an Indication is flagged
time_critical: true, the engine adds a
disqualification warning to FDA compliance.
Two-reviewer merge for clinical content
Any change under knowledge_base/hosted/content/
that affects clinical recommendations needs two of three
Clinical Co-Lead approvals. Without that, the Indication stays
STUB.
Anti automation-bias is mandatory
The engine never shows a single recommendation — always ≥2 tracks side by side. The alternative is never buried, never "click to expand", never fine-print. The clinician sees this is a choice, not a directive.
Patient data never in repo / public artifacts
patient_plans/ is gitignored. Any patient HTML
files are gitignored by pattern. The site (docs/)
ships only synthetic examples. Telemetry collection is
forbidden without explicit consent.
4. Coverage limits (current KB state)
OpenOnco is a work in progress. 65 diseases are currently modeled (37 hematologic + 28 solid tumors) — far short of the full WHO-HAEM5 / WHO Classification of Tumours. Specifically:
| Category | State | What it means |
|---|---|---|
| Diseases with the full chain | 64 / 65 | The rest are partially modeled; the engine may emit "no Algorithm found for disease=X" |
| Indications 1L | 173 | First line covered for all 65 diseases |
| Indications 2L+ | 129 | Second-to-fourth line: 34 hematologic diseases (AITL, ALCL, AML, APL, ATLL, B-ALL, BURKITT, CHL, CLL, CML, DLBCL-NOS, ET, FL, HCL, HCV-MZL, HGBL-DH, MCL, MDS-HR, MDS-LR, MF-SEZARY, MM, NK-T-NASAL, NLPBL, NODAL-MZL, PCNSL, PMBCL, PMF, PTCL-NOS, PTLD, PV, SPLENIC-MZL, T-ALL, T-PLL, WM) + 9 solid (BREAST, CRC, ENDOMETRIAL, ESOPHAGEAL, GASTRIC, MELANOMA, NSCLC, OVARIAN, RCC). The rest of solid-tumor 2L+ is partial (CRC, breast, urothelial), not systematic. |
| RedFlags | 381 | Cover critical clinical scenarios for existing diseases; new diseases need their own RFs added |
| Solid tumors | 28 | BREAST, CERVICAL, CHOLANGIOCARCINOMA, CHONDROSARCOMA, CRC, ENDOMETRIAL, ESOPHAGEAL, GASTRIC, GBM, GIST, GLIOMA-LOW-GRADE, HCC, HNSCC, IFS, IMT, MELANOMA, MPNST, MTC, NSCLC, OVARIAN, PDAC, PROSTATE, RCC, SALIVARY, SCLC, THYROID-ANAPLASTIC, THYROID-PAPILLARY, UROTHELIAL — mostly 1L. 2L+ and adjuvant contexts are partial. |
| Pediatric oncology | 0 | Out of scope for MVP — separate specialization track |
| Radiation therapy plans | partial | RT is wired into multimodality Indications (cervical CRT, GBM Stupp, PMBCL R-CHOP+RT, esophageal CROSS), but not yet modeled as a separate entity with technical parameters (dose / fractions / target volumes) |
| Surgery plans | not modeled | Surgical-oncology indications are absent |
| Live regimen-availability data (NHSU formulary live feed) | static flag | Currently hard-coded on regimens; not auto-refreshed from NHSU — separate backlog item |
| Experimental options (clinical trials) | integrated | Phase C done: enumerate_experimental_options + ExperimentalOption schema, integrated into generate_plan, third Plan track is rendered, 7-day on-disk TTL cache. Still missing: curated trial ↔ patient-eligibility mapping (not just disease+biomarker) |
| Access Matrix (UA-availability per Plan) | integrated | Phase D: AccessMatrix + AccessMatrixRow aggregate registered/НСЗУ/cost/pathway across tracks; rendered in Plan. Still missing: a curated AccessPathway seed (~30 drugs) — gated on two-reviewer signoff per CHARTER §6.1 |
5. What the engine never does
A transparent list of forbidden patterns — so the boundaries are clear:
Hide the alternative track
Both recommendations are always shown. The UI never has an "expand to see alternative" pattern.
Generate a new Indication via LLM
Everything is selected from already-curated KB. If no matching Indication exists, the engine emits a warning — never "creative invention".
Adjust doses "for the patient"
Doses come from standard NCCN/ESMO. Adjustments live only inside explicit dose_modification_rules in the Regimen YAML — no ad-hoc calculations.
Score "which is better" between tracks
The Algorithm picks a default but does not declare the default "better". The clinician retains full autonomy to choose the alternative — documented in automation_bias_warning.
Interpret imaging
"Bulky disease" arrives as a structured field dominant_nodal_mass_cm, not from image analysis. Image analysis = device classification.
Cohort matching
"In the cohort of N patients, M% picked X" is a future feature requiring a persisted patient registry + privacy review. Not available yet.
6. How to live with this
This engine is intended as tumor-board preparation, not a replacement. The clinician inputs a profile, receives a structured draft with all sources and open questions, and then:
Every claim in the plan carries a citation. The clinician can read the original NCCN / ESMO / local-MoH section and confirm the engine did not misquote it.
If the engine flags "cytogenetic panel incomplete", the
clinician orders the test, adds it to the profile, and runs
revise_plan. The plan refreshes, the OpenQuestion
closes.
Re-checks doses, substitutes supportive care for known allergies, manually verifies local-availability constraints. The engine produces a draft; the clinician produces the final.
The MDT brief shows which roles are activated and which questions are open. That is the structured agenda for the board meeting. Decisions taken at the board are captured as provenance events.