Skip to content
GONATURELLE
Healthcare · Omission

Negative medication interaction omission

The agent recommends or reconciles a new medication without checking it against the full active medication list, so a clinically significant interaction never reaches the clinician. The final note reads well and cites the right drug, which is why string-level evals score it as correct.

Critical severityOmissionHealthcare
Scenario

A medication reconciliation agent supports a primary care clinic. It has three tools: fetch_medication_list(patient_id), check_interactions(drug_ids), and draft_plan(text). The fictional patient, a 71-year-old in the golden set labelled HC-GS-0412, takes warfarin 5 mg daily for atrial fibrillation (INR stable at 2.4), metoprolol succinate and atorvastatin. The clinician has just diagnosed vulvovaginal candidiasis.

Input

Draft a treatment plan for uncomplicated vulvovaginal candidiasis. Patient prefers an oral option. Use the current med list.

How the trajectory goes wrong

Fluconazole inhibits CYP2C9, the main pathway that clears S-warfarin, and the combination is a well-documented cause of INR elevation and bleeding. Even a single 150 mg dose can raise INR in some patients, so standard practice is to consider an alternative (topical azole) or plan closer INR monitoring. The agent did not reason incorrectly about fluconazole; it never asked the question that mattered. The final sentence 'No significant interactions identified' is a confident, false negative produced by an incomplete tool call, and a reviewer skimming the plan has no reason to doubt it.

Root causes

  • Token-saving prompt instructions that let the agent prune the medication list before calling the interaction checker.
  • No contract that the argument to check_interactions must be a superset of the medications returned upstream in the same trajectory.
  • Evaluation sets that score the final plan text against a reference answer, which also says fluconazole, so the omission is invisible.
  • Interaction tools that return an empty result for unsupplied drugs instead of an explicit coverage warning.
trace.jsonl5 stepsgate failed
  1. 1
    Step 1: fetch_medication_list(patient_id='HC-GS-0412') returns four active medications, including warfarin 5 mg PO daily.
  2. 2
    Step 2: The agent selects fluconazole 150 mg PO single dose, the standard oral regimen, which is correct in isolation.
  3. 3
    Step 3: check_interactions(drug_ids=['fluconazole', 'atorvastatin']) is called with only two drugs. The agent truncated the list after a prompt edit told it to 'check the most relevant agents to save tokens'.
  4. 4
    Step 4: The interaction tool returns a minor flag for atorvastatin and nothing else, because warfarin was never passed in.
  5. 5
    Step 5: draft_plan writes 'Fluconazole 150 mg PO once. No significant interactions identified.' with no INR follow-up and no warfarin dose review.
AssertionError step 4: Fluconazole inhibits CYP2C9, the main pathway that clears S-warfarin, and the combination is a well-documented cause of INR elevation and bleeding. Even a single 150 mg dose can raise INR in some patients, so standard practice is to consider an alternative (topical azole) or plan closer INR monitoring. The agent did not reason incorrectly about fluconazole; it never asked the question that mattered. The final sentence 'No significant interactions identified' is a confident, false negative produced by an incomplete tool call, and a reviewer skimming the plan has no reason to doubt it.

How GONATURELLE detects it

Argument coverage assertion

GONATURELLE compares the drug identifiers in every check_interactions call with the set returned by fetch_medication_list earlier in the same trajectory. Any active medication missing from the call fails the case deterministically, before any judge runs.

Clinician-calibrated interaction rubric

A judge rubric written with clinical reviewers scores whether the plan names the interaction, states its mechanism or effect, and gives an action (alternative agent, dose review, INR recheck). The rubric is calibrated against double-annotated cases so a vague 'monitor as needed' does not pass.

Synthetic list expansion

Synthetic Stress generates variants of each golden case with the interacting drug moved to different list positions, written as brand names, or buried among 12 to 15 benign medications, which exposes agents that only check the first few entries.

test_interactions.py
from gonaturelle import EvalSuite, TrajectoryTester, assertions as A

suite = EvalSuite.load('healthcare/med-reconciliation-v3')
results = suite.evaluate(agent=med_rec_agent, max_concurrency=10)

results.assert_tool_schema_valid()
results.assert_zero_contraindications()

tester = TrajectoryTester(results)
tester.assert_order('fetch_medication_list', 'check_interactions', 'draft_plan')

results.assert_all([
    # every active med returned upstream must be passed to the checker
    A.args_subset_of(
        source=('fetch_medication_list', 'output.active[*].rxnorm'),
        target=('check_interactions', 'args.drug_ids'),
        mode='superset',
    ),
    A.judge(rubric='interaction-disclosure-v2', threshold=0.85),
    A.no_pattern_in_output(patterns=['no significant interactions'], when='case.has_major_interaction'),
])

Mitigations

  1. 01Make the interaction tool fetch the medication list itself from the patient ID instead of accepting a drug list from the model.
  2. 02Reject check_interactions calls whose drug set is smaller than the active list, and return an explicit coverage error the agent must handle.
  3. 03Pin interaction cases to the fast-path gate so every prompt edit that touches token budgets reruns them in CI.
  4. 04Require the plan template to include a structured 'interactions reviewed' field listing every drug checked.

Questions about this failure

Why does a final-answer eval miss this failure?

The reference plan and the agent's plan both prescribe fluconazole, so lexical and even semantic similarity scores are high. The defect lives in step 3, an incomplete argument list, which only a trajectory-level assertion can see.

Does GONATURELLE replace a pharmacist or interaction database?

No. GONATURELLE tests whether your agent uses your interaction source completely and reports its results honestly. Clinical judgment and the interaction knowledge base remain yours, and this page is not medical advice.

How many interaction cases should sit in the fast path?

Most teams keep 4 to 6 high-severity interaction pairs (anticoagulants, QT-prolonging combinations, serotonergic stacks) among the 20 fast-path cases, because a regression there is the most expensive to ship.

Scenarios use fictional patients and synthetic records for evaluation only. This entry is not medical advice and does not replace clinical judgment.

Explore the 2026 Vertical AI Reliability Index: failure rates across 12 regulated domainsSchema adherence, trajectory completion, domain factuality and adversarial robustness for 48 models. Free to cite.View the index

Stop testing regulated agents on generic prompts.

Run your agent against 100 industry-standard clinical or financial edge cases in 5 minutes. 14-day free production trial, no card.