EHR write operations from AI agents: read-write boundary patterns

Confident bearded man in blue shirt with arms crossed against bamboo wall background

Mirgen Hoxha, Founder & CEO – Motomtech | May 2026

The first time an AI agent in your stack writes to the EHR, the architecture review meeting gets uncomfortable. Read-only agents are easy to defend; the agent looks at the chart, summarizes, hands the summary to a clinician, no clinical record changed. The moment the agent is writing back to the chart, every question shifts: who approved it, how do we know it was correct, what happens if the agent retries on a timeout, how do we recover when somebody finds a bad write three weeks later. This post walks through the read-write boundary patterns that survive that review, organized by FHIR resource category.

The 90-10 rule on agent workloads

A pattern that holds across the HealthTech operators we have worked with: the vast majority of AI agent workloads at the EHR boundary are read-only. The exact split varies by surface and by how teams count drafts-that-trigger-clinician-writes, but the order of magnitude is consistent across stacks: most agent work touches the chart through synthesis, not through writes. The agent reads patient context, synthesizes, drafts, or recommends, and any actual write to the chart happens through a human-in-the-loop approval queue or a separate clinician action.

The 10 percent that does write tends to fall into a small number of categories: scheduling-system writes (appointments are technically EHR data in most integrated systems), patient-reported outcome captures from portal interactions, low-risk administrative writes (insurance verification confirmations, demographic updates with patient consent), and the targeted clinical writes the architecture review is actually about (medication-related, order-related, problem-list updates).

The reason this distribution matters is design economy. Most teams over-design the write path for use cases that turn out to be read-only with a downstream clinician action. The agent does not need to write the chart note; the agent needs to draft the chart note that the clinician then signs. Knowing where the actual writes live focuses the controls.

FHIR resource categories and their default write postures

FHIR R4 organizes EHR data into resource types, and the resource type is the right unit at which to assign a default write posture. The most common resources in patient-portal and care-coordination agent workflows, with their typical write postures:

Patient is identity and demographic data. Writes are rare from agents directly; most updates flow through registration or patient-portal self-service. When an agent does write, it is typically a demographic update with explicit patient consent (address change, preferred contact method). Default: HITL or patient-confirmed.

Appointment is scheduling data. Writes are common in scheduling agents and are usually auto-eligible inside business rules (provider availability, established-patient relationship, allowed appointment types). Default: auto with allow-list, HITL on exceptions.

Observation is a clinical measurement or finding (blood pressure reading, lab value, patient-reported pain score). Writes from agents are most common via patient-portal protocol responses (the patient submits a pain score, the agent records it). Default: auto when the source is structured patient input, HITL on derived or inferred values.

MedicationRequest is a prescription or refill. Writes from agents should default to HITL with a prescriber’s explicit approval. Auto-writes on MedicationRequest are the highest-risk pattern in this category and should be avoided. Default: HITL required, two-person on controlled substances.

ServiceRequest is a clinical order (lab, imaging, referral). Writes from agents typically draft the order for clinician approval. Default: HITL required.

Condition is a problem-list entry. Agent writes typically come from chart summarization or problem-list reconciliation. Default: HITL on add or remove, auto on read-only confirmation that an existing condition is still active.

DocumentReference is a clinical note or attachment. Agent writes are usually drafts that a clinician signs. Default: write the draft as an unsigned document, signing requires a clinician.

Encounter is a visit record. Agent writes are rare; the encounter is typically created by the registration system or the scheduling write. Default: read-mostly.

The pattern is that the FHIR resource category alone tells you most of what you need to know about the write posture. An agent that writes MedicationRequest needs a different control set from an agent that writes Appointment, regardless of what the agent is otherwise doing. Tagging tool calls by their FHIR resource (and where applicable, by sub-type within the resource) makes the policy enforceable at the framework level.

The eventual-consistency write pattern with HITL approval

The pattern that works for any non-trivial agent write is eventual consistency through a HITL approval queue. The agent does not write the EHR directly. It writes a proposed-change record to an approval queue. A clinician reviews the proposed change. On approval, a deterministic worker commits the change to the EHR.

The structure looks like this:

agent.draft_medication_request(...)
  --> approval_queue.insert(proposed_change)
       proposed_change.status = 'pending'
       proposed_change.payload = { resource_type, resource_data, source_context }
       proposed_change.audit = { agent_id, timestamp, tool_call_id }

clinician.review(proposed_change)
  --> approval_queue.update(proposed_change.status = 'approved' | 'rejected' | 'modified')

worker.commit_approved_changes()
  --> for each approved change:
        result = fhir_client.write(resource_type, resource_data)
        approval_queue.update(proposed_change.outcome = result)

Three properties make this pattern hold up under scrutiny.

First, the agent’s output is a record in your system, not a write to the EHR. The agent’s failure modes (hallucinated fields, wrong patient, wrong resource type) are contained inside your control surface. Nothing reaches the EHR until a clinician approves.

Second, the worker that commits to the EHR is deterministic and audited. The worker does not have judgment; it has a job description. It reads approved records, writes them via the FHIR API, records the outcome. If the worker fails (FHIR API timeout, validation error), the proposed change goes to a retry queue, not back to the agent.

Third, the audit trail is complete. Every proposed change has an agent identity, a clinician decision, a worker outcome, and timestamps for each transition. When somebody asks six months later why a particular Condition was added to the problem list, the answer is reconstructable from the queue’s history.

Idempotency keys: surviving retries without duplicate orders

The most boring and most expensive bug in agent EHR writes is the duplicate order. The worker times out on a FHIR write, the orchestrator retries, both writes eventually succeed, and the patient now has two amoxicillin prescriptions in their active medication list. The patch is idempotency keys.

The pattern is: every proposed change carries a UUID generated at the moment the agent produced the draft. The FHIR write request includes this UUID as a header or as a metadata field on the resource. The worker checks for an existing resource with that UUID before writing. The FHIR server (or your wrapper around it) refuses to create a duplicate resource with the same UUID.

For FHIR specifically, the conditional create pattern supports this directly: a POST with an If-None-Exist header that includes a search expression on an identifier the server can match. The pattern is:

POST /MedicationRequest
If-None-Exist: identifier=<agent-write-uuid>

{
  "resourceType": "MedicationRequest",
  "identifier": [{ "system": "agent-write-uuid", "value": "<uuid>" }],
  ...
}

A second attempt with the same UUID returns the existing resource instead of creating a duplicate. The retry is safe, and the worker can be aggressive about retrying transient failures without introducing data corruption.

Two implementation notes. First, the UUID has to be generated upstream of the first write attempt, not inside the worker. If the worker generates the UUID, a retry that comes through a different worker instance generates a different UUID and you are back to duplicates. Second, not all FHIR servers implement conditional create correctly. Test it explicitly against your target EHR’s FHIR endpoint before you rely on it; some integration layers strip the If-None-Exist header silently.

The two-person rule for prescription-level writes

For the highest-risk category of agent EHR writes (medication orders, particularly controlled substances), the architectural pattern that operators land on is a two-person rule. The agent drafts. A first clinician approves. A second clinician (or a different role) confirms before the write commits.

The two-person rule is not unique to AI-assisted prescribing. It maps to the existing clinical workflow for high-risk orders in many specialty contexts (chemotherapy, anticoagulation, controlled substances in some pharmacy contexts). The agent-write pattern simply re-uses an existing clinical control rather than inventing a new one.

The mechanics fit into the eventual-consistency queue. The proposed change has a two-stage approval flow: pending → first-approved → confirmed → committed. Either approver can downgrade to rejected. The worker commits only on confirmed. The audit trail captures both approvers and both timestamps.

Operators sometimes ask whether the second approver can be the same agent applying a “second-look” prompt. The answer is no, for the same reason “the model can refuse” is not a HIPAA control: a model-based check is a soft control, and the two-person rule is a hard control. The second approver is a human. The model can produce a second-look draft or a flag, but the approval is a human action.

Audit trail requirements per HIPAA §164.312(b)

45 CFR §164.312(b) requires audit controls on any system that contains or uses electronic PHI. For agent EHR writes, that means a complete record of every proposed change, every approval decision, and every committed write, from origin through commit and across retries.

The audit log fields that operators converge on:

  • proposed_change_id: the queue record’s UUID
  • agent_id: which agent produced the draft (including version)
  • tool_call_id: the upstream tool call that produced the draft (so the model conversation is reconstructable)
  • source_context_hash: a hash of the chart context the agent saw, so you can later check whether the input was as expected
  • target_resource_type and target_resource_id: the FHIR resource the proposed change refers to
  • proposed_payload: the resource data the agent drafted (post-PHI-redaction-policy)
  • approver_id and approver_decision and approver_timestamp: one per approval stage
  • commit_uuid: the idempotency key the worker used
  • commit_result: success, error, or retry-pending
  • final_resource_id: the EHR’s resource ID after commit, so you can join back to the EHR data

The log is append-only with cryptographic integrity. Operators typically pick from append-only log services (AWS QLDB, immutable S3 with object-lock), database write-ahead-log patterns with signed checkpoints, or BAA-covered SaaS audit-log products. The choice depends on your existing infrastructure; the property that matters is tamper-evidence.

Retention is at least six years per HIPAA’s general guidance, with the audit log itself classified as PHI-bearing and subject to the same access controls as the underlying clinical data. The retention requirement means you cannot dump audit logs into a logging system whose retention policy is 90 days because somebody set it for cost reasons. The audit log lives in storage with explicit long-term retention.

What read-only agents should still do

Even agents that never write to the EHR have a write-adjacent surface that operators sometimes miss. A read-only agent that drafts a message for a clinician to send is, at the moment the clinician clicks send, generating a write to the patient communication record. A read-only summarizer whose summary becomes part of a chart note is generating a write to DocumentReference even though the summarizer itself never called the FHIR API.

The audit-trail discipline travels with the agent’s output, not just the agent’s writes. If a clinician copies the agent’s draft into a chart note and signs it, the audit log should still capture the upstream agent’s role: which agent produced the draft, what the source context was, when the clinician copied it. This is how investigations work six months later when a chart note’s content gets questioned. “The clinician wrote it” is usually true and almost never sufficient.

The implementation pattern is to instrument the clinician-facing UI (the message editor, the chart-note composer) to track which model-drafted content was inserted and to write that lineage into the same audit-log structure as the agent’s direct writes. The clinician’s edits on top are also captured, so the final committed content’s lineage is “agent drafted X, clinician edited to Y, clinician signed at Z.”

FAQ

Q: How should an AI agent handle EHR write operations?

The pattern that holds up under architecture review is eventual consistency through a HITL approval queue. The agent does not write to the EHR directly. It produces a proposed-change record in an internal queue, a clinician reviews and approves, and a deterministic worker commits the approved change to the EHR via the FHIR API. The agent’s failure modes are contained inside the queue, the worker is deterministic and audited, and the audit trail captures every transition from draft through commit.

Q: What percentage of AI agent workloads write to the EHR?

In our experience, the large majority are read-only at the EHR boundary, with any actual write happening through a human-in-the-loop approval queue or a separate clinician action. The minority that writes tends to concentrate in scheduling, patient-reported outcomes, low-risk administrative updates, and the targeted clinical writes (medication, orders, problem-list) that need the strongest controls. Knowing the distribution helps focus engineering effort on the small set of writes that actually need the heavy machinery.

Q: How do I prevent duplicate orders when an AI agent retries a failed EHR write?

Use idempotency keys. Generate a UUID at the moment the agent produces the draft, carry the UUID through the entire pipeline, and include it in the FHIR write request. FHIR’s conditional-create pattern with an If-None-Exist header that matches the identifier prevents duplicate resources when the worker retries. The UUID must be generated upstream of the first write attempt; if the worker generates it, retries through different worker instances will produce duplicates.

Q: When should an AI-drafted prescription require two-person approval?

The two-person rule is standard for the highest-risk prescription categories, particularly controlled substances and Schedule II medications, and many operators extend it to any AI-drafted medication write regardless of category. The pattern is: agent drafts, first clinician approves, second clinician (or a different role) confirms before the write commits. Either approver can reject. Both approvers are human; a model-based second-look is not a substitute, because the rule needs to be a hard control, not a probabilistic one.

Q: What does HIPAA require in the audit log for an AI agent EHR write?

HIPAA’s Security Rule at 45 CFR §164.312(b) requires audit controls that record and examine activity on PHI-bearing systems. For AI agent EHR writes, the practical implementation is an append-only, tamper-evident log that captures the proposed-change ID, agent identity and version, upstream tool call, hashed source context, target FHIR resource, approver identity and decision per stage, idempotency key, commit result, and final EHR resource ID. Retention is at least six years, the log itself is PHI-bearing and lives under the same access controls as the underlying data, and the storage substrate has to support tamper-evidence (append-only, signed, or immutable).

Q: Do read-only AI agents need an audit trail?

Yes, even when they never call a write API. A read-only agent whose drafts become part of a clinical note or a patient communication is generating content that is later written to the EHR by a clinician action. The audit trail should follow the agent’s output through the clinician’s UI: which model produced the draft, what source context was provided, when the clinician inserted it, what edits the clinician made before signing. This lineage is what makes investigations of chart-note content tractable months later.

Related reading

Next step

The read-write boundary is where AI agents in healthcare either earn the right to operate inside the EHR or get blocked at the architecture review. The patterns above (HITL queues, FHIR-resource-tagged postures, idempotency keys, two-person rules on high-risk writes, complete audit trails) are what we build into every HealthTech engagement at Motomtech, both in Agentic AI Development work and in Custom Software Development engagements that add an AI layer to a HIPAA-bound system. If you want to talk through your specific FHIR setup and where the write boundaries should sit, grab time at cal.com/mirgen-motomtech/quick-intro.

Mirgen Hoxha, CEO, Motomtech.

Ready to accelerate your digital transformation?

Subscribe To Our Newsletter

Subscribe to our newsletter and get the latest case studies to your email address.

Logo icon