Communication Profile¶
| Canonical | ../StructureDefinition/nexus-emr-core-communication |
|---|---|
| Status | draft (experimental) · 1.26.0 |
| Base | Communication (constraint) |
| Source | FSH · JSON |
Nexus EMR profile for Communication, covering two distinct populations: WELL-internal staff chat about a patient, and eReferral correspondence passed through from or to external partners. First pass -- the pass-through boundary and message threading are not yet settled.
TypedFhir API / Pydantic schema
The typed accessor surface Communication exposes for Communication — generated from this IG's compiled profile; each typed accessor has a validating raw-FHIR twin (xRaw) where marked. The three ports are parity-enforced.
The AI-facing shape: from typed_fhir.facade.generated.schemas import CommunicationSchema — model_json_schema() is a structured-output / tool definition; instantiating validates an extraction. Generated source.
class CommunicationSchema(BaseModel):
"""AI-facing shape of the Communication profile: the facade's typed accessor
surface (curated + salient fields) as a pydantic model. `model_json_schema()` is a
structured-output / tool schema; instantiating validates an extraction."""
model_config = ConfigDict(extra="forbid")
in_response_to: Reference | None = Field(
None,
description=(
"The message this one replies to. Prior communication that this communication is in "
"response to. Note: ⚠ FIRST PASS. The chat panel currently threads by neither "
"`inResponseTo` nor `partOf` -- conversation order is reconstructed from timestamps, "
"which is why concurrent messages can interleave wrongly. Declaring the element here "
"is the first step; deciding whether threads are `inResponseTo` chains or a `partOf` "
"grouping is open. Communication.inResponseTo — 0..*"
),
)
status: Literal[
"completed",
"entered-in-error",
"in-progress",
"not-done",
"on-hold",
"preparation",
"stopped",
"unknown",
] | None = Field(
None,
description=(
"preparation | in-progress | not-done | completed | entered-in-error | ... The status "
"of the transmission. Note: Internal chat writes `completed` on send. For eReferral "
"traffic the partner's lifecycle applies and `status` is pass-through -- do not infer "
"local workflow state from it. Communication.status — 1..1"
),
)
status_reason: Concept | None = Field(
None,
description=(
"Reason for current status. Captures the reason for the current state of the "
"Communication. Note: This is generally only used for \"exception\" statuses such as "
"\"not-done\", \"suspended\" or \"aborted\". The reason for performing the event at all is "
"captured in reasonCode, not here. Communication.statusReason — 0..1"
),
)
category: Concept | None = Field(
None,
description=(
"Which population: internal staff chat, or external eReferral correspondence. Which "
"population this Communication belongs to. Readers should scope on it -- internal "
"chat and external eReferral correspondence have different authorities over their "
"content, and a chat surface that does not scope will surface partner correspondence "
"into a panel never designed for it. ⚠ HERITAGE EMR SITUATION -- UNRESOLVED. If "
"heritage-EMR message history is ever migrated (see `identifier`), it becomes a THIRD "
"population alongside internal chat and eReferral, and this element is where that "
"distinction would have to live. No code for it exists, because the migration "
"decision has not been made. Anyone binding a value set here must resolve that first, "
"or the binding will need widening the moment migration is agreed. Note: ⚠ FIRST PASS "
"-- no value set is bound yet, deliberately. Binding one requires deciding the "
"pass-through boundary first (a partner-supplied category must remain conformant), "
"and that decision is not made. Until then this is text-or-code and readers MUST "
"tolerate text-only. A local NexusEmrCommunicationCategoryVS is the intended "
"follow-up. Communication.category — 0..*"
),
)
priority: Literal["asap", "routine", "stat", "urgent"] | None = Field(
None,
description=(
"routine | urgent | asap | stat. Characterizes how quickly the planned or in progress "
"communication must be addressed. Includes concepts such as stat, urgent, routine. "
"Note: Used to prioritize workflow (such as which communication to read first) when "
"the communication is planned or in progress. Communication.priority — 0..1"
),
)
medium: Concept | None = Field(
None,
description=(
"A channel of communication. A channel that was used for this communication (e.g. "
"email, fax). Communication.medium — 0..*"
),
)
subject: Reference | None = Field(
None,
description=(
"The patient the communication is about. The patient or group that was the focus of "
"this communication. Note: 0..1 per R4. Internal chat about a patient SHOULD carry it "
"-- a chat message with no subject cannot be scoped to a chart, and cannot be "
"filtered out of one either, which is the access-control concern. "
"Communication.subject — 0..1"
),
)
topic: Concept | None = Field(
None,
description=(
"Description of the purpose/content. Description of the purpose/content, similar to a "
"subject line in an email. Note: Communication.topic.text can be used without any "
"codings. Communication.topic — 0..1"
),
)
sent: FuzzyDate | None = Field(
None,
description=(
"When the message was sent. The time when this communication was sent. "
"Communication.sent — 0..1"
),
)
received: FuzzyDate | None = Field(
None,
description=(
"When the message was received. The time when this communication arrived at the "
"destination. Communication.received — 0..1"
),
)
recipient: Reference | None = Field(
None,
description=(
"Who the message was addressed to. The entity (e.g. person, organization, clinical "
"information system, care team or device) which was the target of the communication. "
"If receipts need to be tracked by an individual, a separate resource instance will "
"need to be created for each recipient. Multiple recipient communications are "
"intended where either receipts are not tracked (e.g. a mass mail-out) or a receipt "
"is captured in aggregate (all emails confirmed received by a particular time). "
"Communication.recipient — 0..*"
),
)
sender: Reference | None = Field(
None,
description=(
"Who sent the message. The entity (e.g. person, organization, clinical information "
"system, or device) which was the source of the communication. Note: Practitioner is "
"the primary provider identity in this IG. Organization covers a partner-system "
"sender on inbound eReferral traffic; Device covers system-generated messages. "
"RelatedPerson covers a SUBSTITUTE DECISION-MAKER acting for the patient -- a "
"distinct fact from the patient acting themselves, and one that must not be flattened "
"onto Patient: where a right over the record is exercised by proxy, the record has to "
"show that authority was delegated, because that is what is checked when the exercise "
"is challenged. Communication.sender — 0..1"
),
)
reason_code: Concept | None = Field(
None,
description=(
"Indication for message. The reason or justification for the communication. Note: "
"Textual reasons can be captured using reasonCode.text. Communication.reasonCode — "
"0..*"
),
)
payload: dict | None = Field(
None,
description=(
"The message content. Text, attachment(s), or resource(s) that was communicated to "
"the recipient. Note: Internal chat writes `contentString`. eReferral traffic may "
"carry `contentAttachment` or `contentReference` -- a reader that assumes "
"contentString will silently render an empty message. Handle all three. "
"Communication.payload — 0..*"
),
)
date: FuzzyDate | None = Field(
None,
description=(
"When the message was sent. The time when this communication was sent. Salient field "
"— sent | received"
),
)