Not an interface developer? The same findings are written without the acronyms in The connection was the easy part, six pages, no prior knowledge assumed. It explains what a 403 is, why an empty refusal is worse than a rude one, and what the vendors’ own demonstration patients actually contain.
The AI MedAgent technical datasheet describes the method. This one answers the question every evaluator asks within ten minutes: can it reach the chart. It now answers it with measurements rather than with capability statements, because the two turned out to disagree in ways that matter.
It sets out what three EHR vendors will actually hand a third party, what each one costs to reach, what arrived when we asked, and the second question that follows immediately: the chart is not a live stream, so where does continuous infusion and ventilator status come from.
This is the first thing anyone building on top of an EHR needs and the last thing anyone publishes. The three vendors sit in three different tiers, and the difference is not technical.
| Vendor | What it takes to get in | Time to a first read | Status here |
|---|---|---|---|
| Oracle Health Millennium R4 open sandbox | Nothing. No account, no key, no agreement. An unauthenticated GET returns patient data. | Under an hour | Read and measured |
| Epic Epic on FHIR R4 sandbox | Self-service registration. Publish a JWK Set, sign an RS384 client assertion, exchange it for a token. No human in the loop. | Same day | Read and measured |
| MEDITECH Greenfield Workspace, US Core STU6 | Registration, then a welcome packet from the Greenfield team, a signed End-User License Agreement, a Google ID, and an OAuth2 client ID and secret. Authorization Code grant only. The client credentials grant is not offered, so there is no unattended access. | Gated on a human, and on a browser at every run | Serves all four resources Epic answers with 403 |
Correction, 24 August 2026. An earlier version of this sheet said Epic refuses four of seven resource types. That was wrong. Of the four 403s, only Condition and AllergyIntolerance had their scopes granted; Procedure, Immunization and DocumentReference were never requested, and DiagnosticReport was granted and served. Two is the correct number and it is still the finding. The error was found because a reader on chat.fhir.org asked whether the Patient read also returned 403. It does not: Patient, Observation, Encounter, MedicationRequest and DiagnosticReport all returned data for the same patient on the same token.
MEDITECH row measured 24 August 2026 against the live Greenfield Workspace, patient Sarai Mccall, 321 resources returned by a single Patient/$everything call. No fee is stated in the published EULA. Every figure in this row was read from the sandbox, not from the documentation.
Published capability statements say what a server supports. They do not say what it will give you. Those are different questions and only one of them can be answered by reading documentation.
| Resource | Epic sandbox | Oracle open sandbox | MEDITECH Greenfield | Synthea, for scale |
|---|---|---|---|---|
| Patient | served | served | served | served |
| Observation, vitals | 371 | 1,000 paging stopped here | 15 | 1,126 |
| Observation, laboratory | 5 | 345 | 33 | 7,766 |
| MedicationRequest | 1 | 500 paging stopped here | 5 | 1,113 |
| Condition, problem list | HTTP 403, zero-byte body. system/Condition.read was in the granted token | served, not counted | 10 | 273 |
| AllergyIntolerance | HTTP 403, zero-byte body. system/AllergyIntolerance.read was in the granted token | 124 | 1 Penicillins, anaphylaxis | 0 recorded |
| DocumentReference | 403. Scope never requested. Correct behavior, not a finding | 199 paging stopped here | 10 | 0 |
| Encounter | 10 | 200 paging stopped here | 4 | 453 |
| Procedure | 403. Scope never requested. Correct behavior, not a finding | 563 | 3 | 1,421 |
Read the MEDITECH column carefully too, for the opposite reason. Those figures are small because they are one real-shaped chart read in full, not a volume generator. The whole column came back in a single Patient/$everything call, 321 resources, and the bundle carried no next link, so nothing is truncated and no figure in that column is a paging cutoff. It is the only one of the four columns where the count and the total are the same number. MEDITECH is also the only server of the three that offered $everything at all.
Read the Oracle column carefully. Four of those figures are where the loader stopped paging at twenty pages, not how many records exist, and they are marked. More exist and were not read. Oracle answers Condition freely to an unauthenticated request, established by probe, but the bulk pull skipped it because Oracle ignores _count on that resource and the response runs to megabytes. A truncation point printed as a total is the same class of false statement this document is about, so it is not printed as one.
system/Condition.read sits in the granted token. The read still returns HTTP 403 with a zero-byte body, which is indistinguishable from a broken endpoint and gives a developer nothing to work with.
The answer came out of an error string on a different endpoint: "Combination of parameters is not valid for any authorized sub-resource." Epic authorizes at sub-resource level, beneath the scope. Four probes established it by measurement. It is not in the published documentation, and anyone planning a build against Epic should know it before month nine rather than after.
The practical consequence for a medication safety tool is severe and worth stating plainly. Epic proves the connection and then refuses the two resources a medication screen most needs, the problem list and the allergy list, having granted the scope for both. DocumentReference and Procedure also returned 403, but those scopes were never requested, so that is Epic behaving correctly and it is not part of this finding. DiagnosticReport was granted and served seven reports.
An integration datasheet that only covers how to connect is half a document. The other half is what comes back, and in both certified sandboxes what came back would break a naive reader.
None of this is a criticism of a test environment, which is what a test environment is for. It is the reason the integrity screen runs before any clinical content and prints its findings above the clinical section rather than in a footnote. A system that calculates perfectly and understands nothing averages a 37 kg swing into a trend line and hands a clinician a number.
Every figure above is reproducible from the saved records and the loaders in this repository. A reference-range check catches none of them: 45 kg and 89 kg are both plausible weights and 37 °C is a normal temperature. What fails is the rate of change, the variance, and the sign.
An earlier draft of this document proposed filing the consult note to the chart as a DocumentReference. That path was abandoned on 21 August and the reasons are worth keeping.
The Epic sandbox is shared with every developer on fhir.epic.com, so writing to it pollutes somebody else's test. More importantly, a note filed into a chart proves less than a card that appears while the clinician is still deciding. Nothing in the current design writes anything to any chart.
| Item | Status | Note |
|---|---|---|
| Backend Services authentication to Epic | Running | RS384 client assertion, published JWK Set, five read scopes granted. |
| Unauthenticated read from Oracle Health | Running | Full record including the resources Epic refuses. |
| One record shape across three loaders | Running | Epic, Oracle and Synthea. The engine cannot tell which it is reading. |
| Integrity screen, unit-aware | Running | 53 LOINC codes with impossibility bounds. Sign check is unit-independent. |
| Eight medication screening classes | Running | Text match only. See the drug knowledge socket below. |
| CDS Hooks service | Deployed | order-select and patient-view, live at aimedagent.net/cds-services. Returns a coverage card on every invocation. |
| AI MedAgent Reasoning inside the endpoint | Deployed | Runs after the deterministic screen. Hard timeout, and a card that says so when it does not complete. |
| Drug knowledge socket | Built and empty | Calling it throws DRUGKB_NOT_CONNECTED, in public, on purpose. Seven of eight classes are unserved without a maintained drug knowledge base. |
| MEDITECH | Connected 24 Aug 2026 | 321 resources on one Patient/$everything call, including Condition and AllergyIntolerance, the two resources Epic grants a scope for and then refuses. Authorization Code grant only, so every run needs a browser and a person. |
| Device cloud feed for infusion and ventilator status | Proposed | Not in any EHR FHIR surface measured here. Not carried by IPEC. No standard subscription transaction exists. |
| Any use with real patient data | Not possible today | Requires a named customer of the vendor. This project does not seek one. |
Everything above concerns the chart. The method reasons over a stream, and two of the signals it needs are not in any FHIR surface measured here: continuous infusion status and ventilator status. Epic’s documented route for infusion pump data remains an HL7 v2 flowsheet interface with row mapping negotiated per customer, and no vendor read for this document exposes a channel-level infusion state through FHIR, which is a custom build at the customer’s expense and delivers a flowsheet summary rather than a live channel state.
The standards do not close this gap either, and the detail matters. Citations are to the IHE Devices Technical Framework Rev. 10.0, Final Text, 4 November 2024. The domain was renamed from Patient Care Device, which is why transaction identifiers keep the PCD prefix.
It is the only place the required data currently exists. A continuous, channel-level view of what an infusion is actually doing is not defined by a Final Text transaction, is not exposed by the EHR, and is not obtainable without either a per-customer HL7 v2 build or a feed from the device manufacturer.
A manufacturer running an always-connected pump already holds this data in its own cloud. Publishing a read-only API over it would create the interface the standard has not yet defined, and would do it with a real device behind it rather than a specification.
Read only. Advisory only. No control path of any kind is requested, offered or implied.
| Signal | Shape | Why it is needed |
|---|---|---|
| Channel infusion state | periodic, per channel | rate, dose, VTBI, volume infused, and running, paused, KVO or alarming. This is the signal IPEC does not provide. |
| Programmed against delivered | both, kept distinct | a record of what was programmed is not a record of what was given, and collapsing them is the failure this whole method exists to address |
| Containment hierarchy | MDS, then VMD or channel, then metric | a multi-channel pump is one device with several channels. Flatten it and you lose which channel delivered which drug, which on a vasopressor and a maintenance fluid is the entire meaning of the message |
| Drug identity and concentration | with the dose, always | rate is not dose. Converting mL/h to mcg/kg/min needs concentration and weight. A dose carried without its basis cannot be recomputed or audited |
| Event stream | timestamped | the three IPEC milestones, plus rate change and KVO transition if the platform can emit them. Those two are the valuable ones precisely because the standard omits them |
| Ventilator status | periodic | mode, set parameters and measured parameters. Same gap, different device |
| Time base | synchronized, source named | an event stream that says the rate changed before the infusion started is a clock problem, and it is indistinguishable from a device problem without a stated time source |
Terminology. ISO/IEEE 11073-10101 nomenclature with the Rosetta Terminology Mapping value set, whose use is required in IHE DEV profiles per DEV TF-1 section 2.6, and UCUM for units. No specific MDC codes are asserted in this document. Codes look memorable and are easy to recall almost correctly, and an almost-correct code is worse than a missing one because it validates. Every code would be looked up in the published tables and agreed in writing before use.
These are not integration details. Each one is a way the record becomes wrong while every system reports success.
A device cloud API that handles those five is worth more than one that merely exists, and none of them is solved by choosing a transport.
This is not a partnership with, an endorsement by, or a listed application of Epic, Oracle Health or MEDITECH. None of them certifies, endorses or verifies third-party applications, and Epic says so plainly. It is not a product, not a pilot, and not a medical device. It is a demonstration that a method already shown to work on a simulated encounter can be fed by a real chart, built so that a licensee can evaluate the integration path instead of being asked to take it on faith.
Patent pending. The method is the subject of US provisional patent applications filed in 2026. It continues one long thread of the same idea: real-time reasoning over a live physiological signal (a processed-EEG algorithm, 1986), population-scale medical-terminology reasoning (UMLS on the MediCompass platform, 2003), and now language-model reasoning over the live medication context.