How PolyAI authenticates to Cerner Millennium, identifies or registers a patient, confirms or finds the physician, re-scopes its variant, validates and verifies insurance in real time for the appointment type, routes prescription refill requests to clinical pools, and books. Every node shows the request/response contract and, for each field, exactly where the data is sourced — captured from the caller, carried in conv.state from a prior call, set as a deployment attribute, or taken from the telephony ANI.
PolyAI runs as a backend client of Cerner Millennium's FHIR server. Reads go through FHIR R4 resources; scheduling writes go through standard FHIR R4 operations — Schedule + Slot search followed by POST Appointment. New-patient intake adds demographic duplicate-matching and FHIR R4 patient registration. Insurance is read from the FHIR Coverage resource, confirmed with the caller, validated against the payer before any write, and (when valid) written back provisionally — then a benefit check runs in real time, in-call against the payer via the pVerify eligibility seam.
Every booking is assembled from reusable building blocks in this order. Each block sources its inputs explicitly and writes named outputs to conv.state for the next block.
Coverage is read early so the payer is available to the in-network provider filter in Find Physician; the caller-facing confirm/update happens in its own step and validates the plan with the payer before writing it to Cerner; the live benefit check then runs after physician + variant so the rendering NPI and the service-type (appointment type) are both present.
No component requires a human logged into Cerner — correct for inbound telephony. The agent operates strictly in the administrative lane (see Scope & Compliance).
Resolved against Oracle_Health_Cerner_API_Documentation.md. "FHIR R4" = standard Cerner Millennium FHIR server; "FHIR R4 · Write" = write-scoped FHIR operations; "pVerify seam" = the real-time eligibility integration to be wired in the pVerify pass.
| Resource / service | Operation | Role in flows | Availability |
|---|---|---|---|
| Patient.Search (Demographics) | GET (R4) | Patient match / demographic duplicate check | FHIR R4 |
| Patient.Search (Broadened) | GET (R4) | Fallback patient match — name + DOB only | FHIR R4 |
| Patient (create) | POST (R4) | Create provisional new-patient record | FHIR R4 · Write |
| Coverage.Search | GET (R4) | Read insurance on file (payer + member ID) | FHIR R4 |
| EligibilitySummary (validation) | POST | Validate plan is real/active before write (org NPI) | pVerify seam |
| Coverage.Create | POST (R4) | Provisional patient-reported coverage write | FHIR R4 · Write |
| EligibilitySummary (benefit) | POST | Real-time copay / PA check for the appointment type | pVerify seam |
| Encounter.Search | GET (R4) | Recent / historical provider | FHIR R4 |
| Practitioner.Read / Search | GET (R4) | Resolve / find provider + NPI | FHIR R4 |
| Appointment.Search | GET (R4) | Locate existing appointment | FHIR R4 |
| Schedule.Search | GET (R4) | Find provider schedule (step 1 of slot search) | FHIR R4 |
| Slot.Search | GET (R4) | Find available time slots (step 2 of slot search) | FHIR R4 |
| Appointment (create) | POST (R4) | Book — new and established patients | FHIR R4 · Write |
| Appointment (cancel via PATCH) | PATCH (R4) | Cancel appointment (JSON Patch) | FHIR R4 · Write |
| AppointmentResponse | POST (R4) | Confirm / acknowledge appointment | FHIR R4 · Write |
| MedicationRequest.Search | GET (R4) | Retrieve active medications + refill count | FHIR R4 |
| MedicationDispense.Search | GET (R4) | Dispense history for remaining-refill calculation | FHIR R4 |
| RelatedPerson.Search | GET (R4) | Authorized representative verification | FHIR R4 |
| Encounter.Search (Eligibility) | GET (R4) | Completed-visit lookback (12-month refill gate) | FHIR R4 |
| Communication (create) | POST (R4) | Submit refill/renewal request to clinical pool | FHIR R4 · Write |
| Transaction Bundle | POST (R4) | Atomic reschedule (book + cancel in one request) | FHIR R4 |
Schedule + Slot two-step pattern rather than Epic's custom $find/$book operations. A Slot tells you when something can happen, not whether it is clinically appropriate — appropriateness is handled by the configured appointment type, never by the agent.conv.state, not regenerated.conv.state from a prior dip, a deployment/variant attribute, or the telephony ANI.conv.set_variant() re-points persona, department and appointment-type defaults the moment the provider is resolved.| Application | PolyAI |
| Prod Client ID | a1b2c3d4-…-e5f6g7h8i9j0 |
| SMART scope / FHIR | SMART V1 · R4 · system/* read + Coverage CRUD + Scheduling |
| Grant | client_credentials + JWT assertion |
| Open Scheduling | Standard FHIR R4 Patient + Appointment create |
| pVerify (seam) | OAuth2 client_credentials; sub-account per NPI |
Written for both PolyAI deployment teams and prospective clients. It states PolyAI's operating position and the design rationale. It is not legal advice; final determination that a deployment is permissible in its jurisdiction rests with the customer's legal, compliance, and clinical leadership.
Identifying and registering patients, finding the right provider and appointment type, confirming insurance, and booking are administrative functions — the same work a front-desk coordinator performs. They become the practice of medicine or nursing only when someone evaluates symptoms to determine clinical urgency or the type of care required. That boundary is the design.
The agent captures a reason-for-visit as an administrative label and maps it to a configured appointment type using the health system's own appointment-type configuration — the same administrative mapping configured in PowerChart for staff and patient self-scheduling. It does not interpret symptoms, rank severity, or select a specialty from a clinical presentation. "I need a cardiologist" or "my doctor referred me to dermatology" is administrative routing. "I have chest pain, what should I do?" is clinical — handled by the Safety-Net, not the agent.
Schmitt-Thompson protocols are the gold-standard telephone-triage decision support, used by the large majority of North American medical call centers — but they are physician-authored and administered by licensed nurses, peer-reviewed annually. PolyAI's decision is explicit: the agent does not run Schmitt-Thompson (or any) triage protocols and does not render dispositions. Where a caller introduces symptoms, the agent applies the Emergency Safety-Net and routes to the customer's licensed triage / clinical resource. Schmitt-Thompson stays with a licensed human.
New-patient registration and booking are administrative acts — automatable on the same basis as a human scheduler creating a chart and booking a visit — provided the interaction does not cross into symptom assessment or clinical triage. The flow collects identity and demographics, runs EMPI duplicate-matching, creates a provisional record (verified by staff at check-in), resolves an in-network provider, and books an administratively-mapped appointment type. The reason-for-visit is a routing label, not a clinical finding. That is what lets the function drive down patient leakage without becoming clinical decision-making.
Confirming insurance, validating that a plan is real and active, and running a real-time benefit check are administrative (financial / registration) acts with no symptom content, so they sit fully inside scope. One bright-line rule governs them: the agent surfaces the payer's determination; it never makes one. It reads back "your plan is active and covers this visit, your copay is $40," or "the payer shows this plan as inactive — let me get you to billing." It does not deny coverage, decide medical necessity, or issue an adverse benefit determination. This keeps the function clear of AI adverse-determination restrictions — for example Texas S.B. 815 (effective Sept 2025), which prohibits utilization-review agents from using AI to make adverse determinations. Patient-reported coverage is validated with the payer before it is written, and even then is written provisional; the authoritative truth is set by the payer's 270/271 response and staff verification, not by the agent.
A conservative, customer-clinically-approved red-flag layer fronts every reason-for-visit. On a small set of unambiguous emergency cues — chest pain, difficulty breathing, stroke signs, severe bleeding, suicidal ideation — the agent stops the flow, instructs the caller to seek emergency care / dial 911, and warm-transfers to a designated clinical resource. It is tuned to over-escalate when uncertain. It is not triage: it assigns no disposition and no level of care — it removes the highest-risk interactions from the automated path entirely.
PolyAI provides the mechanics: the administrative flows, the reason→appointment-type mapping, the escalation routing, the data lineage, and the eligibility seam. The health-system customer owns the clinical content: the emergency red-flag set, the escalation targets (nurse line, 911 guidance, warm transfer), the appointment-type configuration, and clinical governance.
Established-patient flows. Pick one; decisions fan out into labelled branches with their own terminals — loop-backs, CC handoffs, the continuing path. Click any node for utterances, request/response contracts with per-field data provenance, fallbacks, and capture strategy. New-patient intake has its own section. Click a building block to drill in.
The high-value, higher-care flow. A caller with no record wants to be seen. The agent runs the Safety-Net, matches against EMPI to avoid a duplicate, registers a provisional record only on no-match, takes insurance up front (so the provider search can filter in-network), validates the plan with the payer before writing it, finds a provider accepting new patients, re-scopes its variant, verifies benefits live, and books a new-patient visit type. The weight-bearing decisions — EMPI disposition, the Safety-Net, coverage validation, and the eligibility result — are explicit branches.
| Concern | Established patient | New patient |
|---|---|---|
| Record | Exists — resolve FHIR Patient ID | May not exist — EMPI match, then create only on no-match |
| Duplicate risk | Low | High — ambiguous match → data-stewardship handoff, never auto-create/merge |
| Insurance | On file → confirm, validate, update if changed | None on file → capture up front + validate before write (needed for in-network search) |
| Provider | Confirm the one they've seen | No history — directory search (specialty + location + accepting-new + network) |
| Appointment type | Established appointment types | New-patient appointment types (longer; different codes) |
| Booking write | FHIR R4 POST Appointment | FHIR R4 POST Appointment (same endpoint) |
Voice ASR makes some fields risky. These are the patterns PolyAI uses — validate against known values first, fall back to spelling only when needed, and treat reason-for-visit as an administrative label, never a clinical assessment.
Consolidated contract for all endpoints across the flows. For every field, the source line states exactly where the value comes from: caller capture, conv.state from a prior API call, a deployment / variant attribute, or the telephony ANI. Response fields show where the value is stored and what consumes it downstream.
OAuth 2.0 client_credentials with a signed JWT. No interactive login — correct for an inbound call where no clinician or patient can complete a browser consent. The same token serves read FHIR, scheduling operations (Schedule, Slot, Appointment), and Coverage writes. The pVerify eligibility seam uses its own OAuth2 token (covered in the pVerify pass).
| OAuth flow | Designed for | Voice-suitable? | Why |
|---|---|---|---|
| Backend Services Use | Server-to-server, no user present | Yes | JWT signed with a private key; Agent Studio auto-refreshes the token. |
| Clinician / EHR launch No | Apps launched inside PowerChart | No | Needs a logged-in Cerner user — impossible on an inbound call. |
| Patient (HealtheLife) No | Patient portal apps | No | Needs HealtheLife credentials + browser consent. (Some FHIR APIs also behave differently in a patient-facing context.) |
Build with Poly Agent Builder (non-technical) or the ADK (developers) — same dialog-native runtime. The data-lineage discipline below is what makes the deployment auditable.
Configure > Integrations > Cerner. Register the application via the Cerner Code Console; production access requires Oracle PartnerNetwork (OPN) validation. Enable system-level scopes for Patient, Coverage, Appointment, Schedule, and Slot. (pVerify provisioned separately in the pVerify pass.)
Configure > APIs: declare each endpoint with environment-specific base URLs and OAuth 2.0. All scheduling operations use standard FHIR R4 — no private vendor-gated endpoints. Configure Coverage write scope (cruds).
Each function reads inputs from a declared source — caller capture, a conv.state value from a prior dip, a variant attribute, or ANI — calls conv.api.cerner.<op>(...), and writes named results back to conv.state.
The moment Confirm/Find Physician resolves a provider, call conv.set_variant(specialty) and write provider / department / appointment-type to conv.state so every downstream {{attr:…}}, slot search and write re-points.
Front every reason-for-visit with the customer-approved red-flag set; map reason→appointment type via the configured type mapping; validate coverage with the payer before the Cerner write; run the live benefit check after physician + variant. Keep clinical content as customer-owned configuration.
conv.api.pverify.* call is the integration to be wired in the pVerify pass. The Cerner side (Coverage read + provisional write) is in-scope now; this node is drawn so the architecture is complete and the hook is unmistakable. It needs the rendering NPI + service type, which is why it runs after physician + variant \u2014 unlike the validation check.The agent checks the patient's active medications, computes remaining refills, verifies visit eligibility (12-month lookback), and routes the request to the appropriate clinical pool. Controlled substances require an in-person visit. The agent never dispenses, adjudicates, or overrides — it routes.
| Scenario | Agent action | API surface |
|---|---|---|
| Refills remaining on file | Direct caller to their pharmacy — no request submitted | MedicationRequest + MedicationDispense (read) |
| No refills remaining — visit within 12 months | Submit refill request to clinical pool | Communication (POST) to clinical pool |
| No refills remaining — no visit in 12 months | Schedule a visit and submit refill request | Schedule + Slot + POST Appointment + Communication |
| Controlled substance | Schedule in-person visit; submit request with HIGH priority | POST Appointment + Communication (priority: urgent) |
| Clinical question about medication | Transfer to Access Center staff | No API — CC handoff |
RelatedPerson when the caller is not the patient. Scheduling actions do not require this check.The Communication payload carries everything the clinical team needs to act without calling back:
| Field | Source |
|---|---|
| Patient name | conv.state.patient_name ← ID Patient |
| MRN | conv.state.mrn ← Patient.identifier |
| Medication + dosage | conv.state.medication ← MedicationRequest |
| Pharmacy | Caller capture (confirmed) |
| Eligibility status | conv.state.has_recent_visit ← Encounter eligibility check |
| Priority | HIGH for controlled substances, NORMAL otherwise |
The reasoning behind each choice, so it holds up to clinical and technical review.
Surfaces that exist in the Cerner Millennium ecosystem and could plausibly have been used here, with the reason each was set aside for this conversational, real-time, administrative use case. Confirm specifics against Oracle_Health_Cerner_API_Documentation.md for a given instance.