One model, many workflows¶
A task says: someone is responsible for doing something, possibly about a patient, possibly about something that already exists, and possibly carrying something new that could be added to a chart.
Almost everything that looks like a separate kind of task -- an AI suggestion, a care-gap card, a document to review, an appointment to book -- is the same object with different fields set. This page walks that model one idea at a time, and defines each term once. Several words in this area get used for more than one concept, so The words, settled is the reference to point at when that happens.
These are not proposed labels for a user interface. They are the words FHIR uses, and they are here because the work item is stored in FHIR and has to stay workflow-interoperable with other EMRs at this level. What a screen calls any of it is a product decision. What matters is that everyone means the same thing by each word, and that whatever the screen says maps cleanly onto exactly one of them.
Clinical Tasks: the idea is the same model in one short read; Clinical Task Design is the profile detail.
The fields every task has¶
Five elements are required on every Task -- requester, description, intent, status and
authoredOn -- and owner joins them whenever responsibility has been narrowed. Three of the six
carry the interesting decisions; the rest have obvious defaults.
| Core element | What it says |
|---|---|
requester |
who asked for the work. A person, a rules engine, or an AI graph |
owner |
who is responsible right now. Never more than one: a practitioner, a practitioner role, a CareTeam, or a software agent. 0..1 since 1.26.0 -- absent means the whole clinic holds it, and that relaxation is not yet settled (see Ownership) |
description |
the ask. What is wanted and why the task exists. Stable for the life of the task |
intent |
am I being told, or asked? See Order or proposal |
status |
where it is in its life. See The lifecycle |
authoredOn |
when it was created. Set by the system |
Everything else is optional and set when it applies:
| Optional element | What it says |
|---|---|
for |
the patient the task is about. Leave it out and the task is a provider-only to-do |
focus |
a specific item that already exists, which the task is filed against |
restriction.period |
the fulfillment window. Its end is the due date |
contained bundle |
candidate chart entries the task is carrying |
note |
what has been said since the task was created |
code |
which worklist bin it files under |
groupIdentifier |
which card it was raised with |
Three simple shapes¶
All three carry the same six required elements. Only the placement varies.
| Shape | for |
focus |
The ask |
|---|---|---|---|
| Provider-only to-do | -- | -- | "Call the pharmacy." |
| Patient task | Jane Patient | -- | "Call Jane about her symptoms." |
| Patient plus existing item | Jane Patient | Lab Result 123 | "Review this result." |
A task you made for yourself still names you as the requester. Requester and owner being the same person is ordinary rather than a special case, and the moment you hand it to somebody else the owner changes and the requester does not.
Nothing else about a task changes these basics. It can be human- or machine-created, an order or a proposal, and it can carry something new for the chart. Those are separate elements on the same object.
Owner and patient answer two different questions¶
Routing and patient visibility are independent, and both are guarantees.
Owner decides whose worklist a task is in. Patient decides whose chart it shows on. A task with both appears in both places, and neither surface is the real one.
Owner to provider inbox. Every task owned by a provider must be discoverable from that provider's inbox. A surface may filter it out by default, may put it in a different pane, may slice the inbox any way it likes. But if a provider asks to see everything assigned to them, every task they own has to be there: proposals, machine-created, human-created, patient or no patient.
Patient to chart task view. If a task names a patient, it must be discoverable from that patient's chart, regardless of who currently owns it. Outstanding work on a patient is often the most clinically interesting thing about them, and the person opening the chart is frequently not the person holding the task.
These two rules are contracts a consumer keeps, not constraints a validator checks
Most of what follows can be checked mechanically. These two cannot: nothing in FHIR enforces either of them. They are the reason the rest of the model is worth agreeing on, and they are the first thing to test when a task goes missing.
Who asked for this¶
The requester is separate from the owner, and a machine requester is not a different kind of task.
Requester is who asked. Owner is who is responsible right now. The original requester stays put while ownership moves around the clinic.
Task.requester is where "what produced this" lives, and it is the only place that names which
producer. No task category, no status and no intent distinguishes a machine-made task from a
human-made one. A non-human producer is named as a logical
nexus-harness-graph reference -- the graph or
rule under a name a clinician or auditor would recognise, with no Device resource to register
anywhere.
A machine creates exactly the same shapes a person does: provider only ("you have unsigned work"), provider plus patient ("consider following up"), provider plus patient plus focus ("review this result").
That a machine was involved is recorded separately and coarsely, by one label used specification-wide:
the AIAST security label on the task. Two things about it are
worth knowing before you read one:
- It goes on the task, never on the suggested content inside it.
- It is not retroactive. An absent label means unknown, not human.
Focus means the item already exists¶
Task.focus names a resource that already exists: the lab that was filed, the note that was written,
the letter that was created, the problem being followed up. Nothing is created by the focus itself.
This is enforced rather than merely intended -- the invariant nexus-task-focus-not-contained makes
it an error for focus to point inside the task. See the
invariants.
The item's own lifecycle is beside the point. A note can be a draft, a report can be preliminary, and some workflows deliberately create a placeholder up front. All of those exist, so all of them are good focus targets. "Please finish and sign my draft note" is a focus task. The test is not whether the item is finished; it is whether it exists.
Focus does not imply a patient¶
"In the chart" is shorthand, and it is misleading in a way that matters. A great deal of real inbox work is about something that is not on anybody's chart, and some of it never will be: a pharmacy bulletin saying their number has changed, a fax misdirected to this clinic for somebody else's patient, an administrative request that just needs somebody to do a thing.
The task side already handles this, because Task.for is optional. There are three populations, and
only one of them is temporary:
| Population | What to do | Why |
|---|---|---|
| Belongs to a patient, matched | File it immediately, marked unreviewed, with the review task attached | Holding reports out of the chart until somebody processes them is a pattern several EMRs have shipped and regretted. A clinician opens the chart, does not see the result, and the delay stops being administrative |
| Belongs to a patient, unmatched | Create the document anyway; it acquires a patient once somebody files it | The item should exist as a resource in the meantime, so the task about it has something to point at |
| Belongs to no patient, ever | Carry no patient at all | The bulletin and the misfax are permanent members of this set. This is the case that gets forgotten, and it is not rare |
A fax arrives asking for something administrative. Whoever triages it says "I cannot do this, the front desk has to" and assigns the task. The new owner opens it, sees the attached fax on focus, does the thing, and marks it complete. Everything in this page still applies: one owner at a time, a conversation on the task, a completion. The only element that is empty is the patient.
This is what the "junk mail" patient is really about. Some clinics create a fake patient and attach these items to it. That is a workaround rather than a filing instinct: attaching to a patient is the only way the inbox will let them label the item, so the fix is a display affordance rather than a data one. Let people retitle a document in the inbox and the reason to invent a fake patient disappears. Fake patients are expensive -- they enter searches, counts, reports and every cross-patient safety check, and they are very hard to remove later.
Not yet settled: a document with no patient
DocumentReference.subject
and DiagnosticReport.subject
are both 1..1 in the current profiles, so a patient-less document is not representable today
and the fake-patient workaround is the only way to hold one. Relaxing those two is the change.
What would decide it: confirming that nothing downstream treats a patient as guaranteed, since a
reader that assumes one will fault on the first unfiled fax.
Containing such a document inside its task would be legal and would keep a one-off out of the document space, but containment means the item does not exist yet, which an arrived fax plainly does. Keeping it first-class stays consistent with both rules on this page.
Forms and inbox documents are not stored inside tasks. A completed form is a
QuestionnaireResponse,
an arriving document is a DocumentReference, an authored note is a
Composition, and the task points
at it. One copy, in the record, readable by anything that knows nothing about task workflow.
A reminder filed against a prescription¶
A titration reminder checkpoint -- "recheck BP", "increase to 10 mg", on a date, about one drug --
is a dated, acknowledgeable prompt about a prescription that already exists. It needs no new shape:
it is a focus task, and it passes the test this section applies, because the MedicationRequest is
already in the chart before the reminder is written.
| Element | What it holds |
|---|---|
focus |
the MedicationRequest the checkpoint is about |
for |
the patient |
description |
the checkpoint label, as it was written when the drug was prescribed |
code |
the worklist bin it files under |
restriction.period |
its end is the date the checkpoint is due |
status and lastModified |
acknowledgement: completed, and when |
The due date goes on restriction.period.end, which is what this guide recommends everywhere and
what the profile already documents as the due date.
executionPeriod
exists, sits beside it and looks like the obvious candidate; it is still the wrong element, for the
reason given under Due date.
Where this belongs when it is persisted -- not what is written today
Nothing writes these tasks. Titration checkpoints are held per patient in browser local storage against a prescription id and never reach FHIR, so a consumer reading a chart will find no such task and must not read their absence as a gap in the record. This section says what shape to write when they are persisted, and says nothing about what exists now.
The reminder half is the only half modelled here, and that is deliberate. There is no structured
dose-step plan -- no per-step dose, no per-step duration, no machine-readable schedule -- and a
series of these checkpoints is not one. Planned dose changes are written as free text in
MedicationRequest.dosageInstruction.text, where the prescriber writes the instructions anyway.
A reader must not reconstruct a titration schedule from the checkpoints.
A suggested resource does not exist yet¶
A task can contain a template: one or more prototype chart entries that a user instantiates from the task. Until somebody does, they are candidates held inside it, and they are invisible to chart queries -- not filtered out, but genuinely unreachable, because a contained resource has no independent existence to return.
That last point is the whole reason for the design. A team that has never read a line of this cannot accidentally show a patient an unapproved diagnosis, because the query they wrote was never capable of returning one. There is no "remember to exclude suggestions" rule for anyone to forget.
Writing the candidate into the chart with a flag instead would be worse on three counts:
- It may never happen. A candidate the clinician declines should not have existed in the record as a fact.
- Details often still need working out: the appointment time, the dose, the specificity of the code.
- Everything downstream would need to learn a new flag, and anything that forgot would treat a machine guess as an asserted clinical fact.
Three examples, and only one of them involves a machine:
- Machine suggestion. Extraction reads the encounter note and suggests adding type 2 diabetes to the problem list.
- Draft appointment. A doctor sends reception an approximate follow-up to arrange. It is not booked, because the details are not known yet.
- Proposed medication. A specialist sends the GP who owns the medication list a candidate prescription to consider.
Suggesting is not an AI capability. One person can suggest a chart entry to another -- a specialist to a GP, a supervisor to a resident -- and the model is identical, with a person as requester. A suggestion is defined by what it carries, not by who made it. See Suggested-Resource Tasks.
Focus and suggested resources point in opposite directions¶
This is the most important distinction in the model, and the easiest one to gloss over.
Colour carries the distinction in every diagram on this page: petrol is something that already exists, violet is a candidate that does not exist yet.
Do not use the word "suggestion" loosely. Three nearby things are three different dimensions, and ordinary English makes them sound like one:
- A proposal is how authoritative the request is.
- A suggested resource is chart content the task is carrying.
- Machine-generated is where the task came from.
Any of the three can be true without the other two.
suggestion is not a code anywhere in this specification
There is no such task category, and searching for one returns nothing. Whether a task carries a candidate chart entry is answered by reading what it contains.
What a suggestion actually carries¶
A transaction Bundle. Which means one task can add, update and retire -- atomically, and stated per
item.
The payload is a contained transaction bundle. Each entry states for itself what it would do to the chart, and the transaction states that they happen together or not at all.
This is the same container a reusable letter template uses and the same one a form uses: one
mechanism, three wrappers -- a List for
a named template, a Questionnaire
for a form, a Task for a suggested chart entry. Instantiating any of them is an ordinary FHIR
transaction rather than an operation this specification had to invent.
| The suggestion | Request | The candidate is |
|---|---|---|
| Add an entry | POST to the type's endpoint |
the new resource |
| Update an entry | PUT to the existing resource |
its suggested new state |
| Retire an entry | PUT, as above |
its suggested new state, marked entered-in-error |
Retiring is a kind of update, because there is no delete in this chart. A consult letter that refutes a recorded allergy produces a suggestion to withdraw it, not to erase it.
Why this matters for medications¶
Prescribing has three distinct workflows that look identical from the outside and must not be handled identically: a renewal, a dose change, and a net-new medication. A dose change is not one write -- it expires the old prescription and creates the new one. That is one task, one bundle, two entries, and the transaction is what guarantees you never get half of it.
"contained": [{ "resourceType": "Bundle", "type": "transaction",
"entry": [
{ "resource": { "resourceType": "MedicationRequest" },
"request": { "method": "PUT", "url": "MedicationRequest/abc" } },
{ "resource": { "resourceType": "MedicationRequest" },
"request": { "method": "POST", "url": "MedicationRequest" } }
]}]
focus does not tell you whether something is created or updated. Focus means what it means
everywhere else: the element the task is filed against. A task has only one focus, and a single
suggestion may both update and add. The request method on each entry is what says what happens. See
Add, update, retire.
Two more things the payload has to get right:
- A candidate states the clinical fact, not its review state. A suggested condition extracted
from a note documenting an established diagnosis is written as
confirmed. Reaching forunconfirmedto mean "not yet approved" corrupts a modifier element that every downstream consumer reads, and the wrong value would survive into the chart, because instantiating does not edit the inside of a candidate. - Citations travel inside the bundle. The
Provenancerecording which passage of which document each statement rests on is an entry in the same bundle, so it is written on acceptance along with the content. An accepted machine-produced entry with no trail back to its source is exactly what the attribution rules exist to prevent.
Instantiate: the act that writes¶
Everything else in this model moves labels around. This is the one act that changes the chart.
Instantiate takes the template a task is carrying and writes it into the chart. It is deliberately the same verb, and the same operation, as instantiating a letter template a user picked from a list, and it is an ordinary FHIR transaction.
Instantiating involves five things:
- Fill in what the producer could not know, and rewrite the references between the candidates.
- Write them to the chart as one transaction: all of them, or none.
- Carry the shared business key onto what was written, so the trail back exists.
- Say what was decided, as a note on the task.
- Hand the task back to whoever asked. If that was an agent, reassigning it is the notification -- nothing sits waiting between runs, so assignment is the signal.
Step 1 is not a button
Reconciling a candidate against what is already in the chart is the normal case, not the edge case: which of three similarly named problems does this update, which of two near-identical medications does this match, which level of coding specificity does this physician want. Medications, referrals, billing and problems each need a real editor with real screen space. It is the same problem as medication reconciliation at a transition of care, and it has the same irreducible ambiguity -- sometimes the answer genuinely is not knowable by the producer, and a human has to resolve it.
What gets written may not be what was suggested, because the clinician edited it on the way through. The contained template is therefore not a reliable account of what ended up in the chart. The trail back runs on the shared business key and provenance rather than on the payload.
The other answer is declining. Status becomes cancelled with a
statusReason
saying a human declined it. The task and everything it carries are retained, because what was offered
and refused is part of the record. Nothing is written to the chart.
A suggestion is cleared by an explicit instantiate or an explicit decline, and by nothing else. It does not expire, and it is not silently dropped on chart reload. Anything that removes work from a clinician's view without a recorded decision destroys the audit trail that the distinction exists to create.
Order or proposal: am I being told, or asked?¶
One element, and its practical meaning is which list a user sees the task in.
intent |
Means | Example |
|---|---|---|
order |
Do this. The work is authorized and assigned. The owner is expected to perform it, not to decide whether it should happen. Inbox items, follow-ups and to-dos are orders | A doctor to a nurse: "please print this letter" |
proposal |
Consider this. Something is being offered, and the owner has discretion to accept, decline or modify it | Extraction to a clinician: "consider adding this problem" |
A suggestions list and a tasks list here name two behaviours, not two mandated screen names: one place for things you are being asked to decide on, one for things you are expected to do. Whether that is two tabs, two panes, a filter or one list with a divider is a design question, and this element does not answer it. See the task intent value set.
The difference is about the relationship between the requester and the owner: does the requester have the standing to require this work, or only to put it forward? Which is why machine requesters essentially always produce proposals. An AI graph or a rules engine has no authority to issue orders to clinicians.
Intent is independent of what the task carries. All four combinations are real:
intent = proposal |
intent = order |
|
|---|---|---|
| carries a suggested resource | A candidate awaiting a decision. The usual AI and decision-support shape, and also a specialist proposing a medication to the GP | Agreed, and needs recording. The entry is already decided; the task exists to get it into the chart |
| carries nothing | "Consider doing this." Advice with no draft attached | An ordinary to-do. Most of the chart |
So do not read intent to decide whether a task carries a suggestion; anything that does will
misfile the top-right cell. Read the containment for "does this carry a candidate". Read intent for
"what am I being asked to do".
Approve and accept¶
The model can express two further gestures precisely. Whether a user ever performs either is a product question that is not settled, and the model costs nothing either way: they simply become things the system does on a user's behalf, or does not do at all.
What matters regardless is that approve, accept and instantiate are three distinct acts, because they get used for each other constantly and conflating any two of them is a bug.
Three separate tracks, and the two dashed ones are the open questions. A task could be approved and not instantiated -- that is just an order somebody still has to carry out. A template can be instantiated with no task anywhere near it.
| Gesture | It would change | And it would mean |
|---|---|---|
| Approve | intent from proposal to order |
The task moves out of the suggestions list and into the tasks list. One-way. Writes nothing to the chart |
| Accept | status to accepted |
Somebody has claimed the work. Where the owner was a care team, the owner becomes the person claiming it |
"Promote a suggestion to a task" is approve. Whatever is decided about the gesture, that is what it would be: the proposal becomes an order and changes which list it lives in. Nothing new is created and the chart is untouched. A description of it as creating a second task is the thing to push back on regardless, because a task pointing at a task is a duplicate of work that already exists.
And neither of them is instantiate. Approving authorizes; instantiating writes. A task can sit approved and un-instantiated, which is simply an order somebody still has to carry out. See Approving and declining.
The lifecycle stays boring on purpose¶
Seven states. They are meanings, not a path.
There is deliberately no flowchart. Ready straight to completed is a normal day's work, and accepted back to ready is handing something back.
| Status | Means |
|---|---|
draft |
Being composed. In nobody's list yet |
ready |
Actionable, in its owner's list. Where the owner is a care team, it is in the pool and unclaimed |
accepted |
Claimed by its owner, not yet started. Out of common circulation |
in-progress |
Actively being worked |
on-hold |
Deliberately parked: snoozed, or waiting on something outside this task |
completed |
The work was done. Terminal |
cancelled |
The work will not be done. Terminal |
The full set is the clinical task status value set.
There is no rejected. A declined proposal is cancelled, the same as one that became moot when
its alternative was approved. Those are different clinical records, and Task.statusReason is the
only thing that tells them apart -- which makes the reason close to required on any cancelled
proposal. Cancel one without a reason and the record can never afterwards say whether a clinician
considered it and said no.
Five base FHIR statuses are deliberately excluded
requested was a second name for ready; received is a fulfilment step this model does not
have; failed is a technical outcome rather than a clinical one; entered-in-error has no
workflow that writes it; and rejected for the reason above. Anything storing requested
today needs rewriting to ready.
Not yet settled: whether accepted is used in practice
The argument for it is circulation rather than progress: claiming a pooled task moves the owner from the team to the person and takes it out of everybody else's view, which answers "has anybody picked this up?". The argument against is that almost nothing sits in it, because most people claim work by starting it -- and a state nobody dwells in is still a state every renderer has to handle. What would decide it: whether an explicit accept gesture exists on any surface at all. Being in the value set does not oblige a producer to write it.
Actions on a task¶
A small, closed set. Everything else that gets called a task type is one of these plus some fields.
- Create. Make a new task. It may start as a draft or go straight to ready, depending on the workflow.
- Comment. Append a note with an author, a timestamp and text. Long-lived tasks should accumulate a readable history of what people actually did.
- Forward / reassign. Change the owner, usually with a comment explaining why it moved.
- Reply. Hand the task back to whoever it came from, usually with a comment. Reply does not mean completed.
- Approve (if adopted). Proposal becomes order. Moves it between lists; writes nothing.
- Accept (if adopted). Take responsibility. Typically reassigns from a care team to yourself.
- Instantiate. For a task carrying candidates: write them into the chart as one transaction. The only action here that changes the chart.
- Complete / Cancel. Done, or will not be done. Cancel with a reason -- always on a proposal, and usefully everywhere else.
These are operation names, not FHIR vocabulary. Base FHIR does publish a list of task actions -- approve, fulfill, abort, replace, change, suspend, resume -- and this specification deliberately does not use it. What a task would do to the chart is already stated per entry inside the payload; coding it a second time would let the two disagree. Hold and snooze are future extended actions, and the status they would use already exists.
The task is the conversation¶
The ask is one element. Everything said since is the thread. There is no message resource.
Task.description carries the ask -- "please check whether Jane actually started the metformin, and
let me know what she says" -- and it is stable for the life of the task. Task.note carries the
turns that follow, oldest first, each with its own author and time, profiled as
Task Note.
Four rules follow from that shape, and each one is a bug somewhere if you skip it:
- The ask is
description, not the first note. Do not copy it into the thread to fill it. That stores the same statement twice and opens the conversation with something nobody said. - A task with no notes is completely ordinary. It is new work nobody has commented on. A renderer that requires at least one turn will fault on the most common task in the system.
- Every turn is attributed and timed. An unattributed turn in a clinical conversation is worse than no turn: a statement in the record with nobody behind it. Time is also the ordering key, and one undated turn makes the whole thread's order a guess.
- The thread runs the whole life of the task. It is still readable a year later, and it travels with the task when it is handed over, which is what makes a handed-over task intelligible to the person receiving it.
An AI conversation is this, unchanged. Asking the harness something is not an API call from the chart's point of view -- it is a task assigned to the agent, with the question as the ask. The agent answers by appending a turn and handing it back. So chat history is a task read, "go back to that conversation" is a task query, and a conversation with an agent is auditable exactly the way a conversation with a colleague is.
Two consequences worth knowing before you build against it:
- A task can be owned by a practitioner role or a care team, but neither can author a turn. Base FHIR permits only a practitioner, patient, related person or organization as a note author, and a profile cannot widen that. A team-owned task still has every turn authored by a person. Reusing the owner reference as the note author produces an invalid note.
- An agent authors a turn as an identifier-only reference under the harness-graph naming system,
with a readable display name. FHIR does not allow a
Deviceas a note author, so the identifier's system carries the identity instead.
This replaced an earlier design
Task conversation used to be modelled as separate message resources linked back to the task with email-style threading. That shape is superseded. Anything written against it reads turns from the wrong place and finds none. See Conversation Threading.
Forward and reply move ownership, not completion¶
A task can travel the whole clinic and still be one continuous piece of work.
Reply returns the task to whoever handed it to you, which is not necessarily the person who created it. The requester stays unchanged while ownership moves.
Forward is routing. Change the owner. It is still the same task, and it does not mean the work is finished. A comment usually explains why it moved.
Reply is not completion. "Yes, I did it, here is what happened." The task is simply back on the previous person's desk. They may complete it, do more work, or route it again.
Forwarding by copying is the failure this model exists to prevent
Systems that forward a task by copying it -- email semantics -- leave it in your inbox and theirs. In a clinic that is a disaster: nobody can tell who is responsible, and the count never goes down. Never more than one owner at any moment is the whole point of the constraint. (Never FEWER than one is a different question, with a different answer: a task with no owner is everyone's, and every user sees it -- see Ownership.)
Not yet settled: multi-hop reply
Reply should return the task to whoever handed it to the current owner, which past one hop is
not the requester. Every ownership transfer is recorded as provenance in
relevantHistory,
independently of whether anybody chose to comment, but there is no maintained back-pointer on
the task, so "who handed this to me" is recoverable only by searching that audit trail. What
would decide it: whether reply is expected to work past one hop, which turns that lookup into a
stated requirement rather than an implementation detail.
Many at once, and not filing the same one twice¶
Decision support does not answer with one proposal, and a rule that runs nightly must not leave a nightly pile.
The card is what holds them together. One search on the shared identifier returns the set, and no parent resource has to exist.
Grouping is not alternation. A card offering three things all worth doing raises three proposals
that happen to share a group. A card offering three ways to close one gap raises three
alternatives. Read both; neither answers
alone. Approving an option moves its siblings to cancelled, with a reason recording that they
stopped being on offer rather than that anybody declined them. The group is carried on
Task.groupIdentifier under the CDS card naming system.
The gap is the identity, never the run. Every machine-written task carries a business key under
nexus-harness-key, and a producer searches for it
before writing. The value is derived from what the task is about -- the gap being addressed -- and
never from the run that produced it. A key containing a run id or a timestamp is a new key on every
execution, which is precisely the duplicate it was meant to prevent.
This is most of the "infinite pile" problem solved in the data model rather than in the surface. Re-running the rules updates the task that already exists instead of adding another one. And a producer re-running against a gap that no longer holds finds its own task and resolves it, so a gap that closes on its own closes its own task with nobody having to dismiss anything.
Three rules come with persisting decision support:
- Card suggestions persist once presented. This is a real departure from traditional decision support, where a card is a point-in-time thing that vanishes when you navigate away. If you dismiss it and it is gone, the record cannot say it was ever offered.
- Alert fatigue is a display problem, not a storage problem. Caps, ranking and suppression windows all stay exactly where they are. Store everything, curate the surface.
- A producer must read its own open suggestions as context. The human test is the right one: a colleague who reviewed your note and made suggestions would not repeat the ones they already made.
Triage: due date and priority¶
The two elements an inbox sorts on. Each has a wrinkle worth knowing before you build against it.
Due date¶
The due date is the end of the fulfillment window: Task.restriction.period, whose base definition
says so -- "period.high is the due date representing the time by which the task should be completed."
Do not reach for executionPeriod
Task.executionPeriod
sits right beside it, it is a period, and it looks like the obvious candidate. It means when the
work is being or was done, not when it is wanted by. Writing a due date there produces a task
that claims to have been worked on a date in the future.
Where the deadline is set by law rather than by a clinic it goes in the same place: a privacy request's statutory response clock is this element, and nothing privacy-specific holds it. See access requests.
Priority, and the thing below routine¶
Task.priority
takes one of four values, and they only go one direction: routine, urgent, asap, stat. All
four are conformant. Unlike status, which is narrowed to a required subset, priority binds the base
FHIR vocabulary unchanged, and R4 gives nothing below routine.
routine is the floor. There is no low, no optional, no whenever. Every task in the vocabulary is at
least ordinary work, and the only thing the scale can express is how much more urgent than ordinary
something is.
That is a genuine mismatch with the clinic. A large and growing share of what lands in an inbox is
work a provider may reasonably never do: a problem-list tidy-up, an optional code refinement, a
suggestion they simply do not care about. Filing all of it as routine puts it in the same bucket as
a callback a patient is waiting on, and that is how an inbox becomes something people stop reading.
A fifth code is not available. Base FHIR binds this element required to its own vocabulary and a
profile may only narrow a binding, never widen it; and the element is a bare code rather than a
CodeableConcept, so there is no second coding slot to put an alternative in even if the binding
allowed it. So the refinement rides beside it.
The priority-detail extension
carries the finer value, and an invariant requires priority to be routine whenever it is present.
It currently carries exactly one value, trivial, from the
priority detail value set. The rule that
makes it safe is the interesting part: when the extension is present, priority shall be routine,
so anything that has never heard of the extension reads the task as ordinary. It under-states the
task rather than mis-sorting it, which is the only failure direction that is acceptable on an element
that also carries stat.
First pass -- half a mechanism today
The extension exists; the practice around it does not yet. Three things are undecided, and they
are the difference between trivial being useful and being decoration. What actually gets it:
if AI and decision-support suggestions are trivial by default, that is a real answer with real
consequences, and if nothing is ever written as trivial the extension is dead weight. Whether
any surface sorts on it: an extension nobody reads changes nothing, so the inbox and the
suggestions panel have to treat it differently -- below the fold, collapsed by default, excluded
from counts -- or it does not exist in practice. Whether one value below routine is enough:
there is one, and whether the clinic needs two is untested.
There is a nearby question this does not answer, and it is worth not conflating: how much attention a
task deserves is not the same as how long it can wait. Priority is about urgency. "This is optional"
is closer to a statement about whether the work is worth doing at all, which is what intent already
says when it says proposal. Reaching for trivial on everything that is a proposal is a sign of
encoding the same fact twice.
Worked examples¶
The same handful of elements, producing workflows that look nothing like each other.
| Example | Requester | Owner | for |
focus |
intent |
Carries |
|---|---|---|---|---|---|---|
| Personal to-do: "call the pharmacy" | a person | Dr. Lee | -- | -- | order | -- |
| Patient follow-up: "call Jane about her symptoms" | a person | Nurse Jones | Jane | -- | order | -- |
| Review an incoming report: "please review this result" | ingestion software | Dr. Lee | Jane | Lab Result 123 | order | -- |
| Print an existing letter: "please print this" | Dr. Lee | Nurse Jones | Jane | Letter 456 | order | -- |
| Extracted problem: "add type 2 diabetes?" | extraction graph | Dr. Lee | Jane | the note | proposal | Condition, POST |
| Specialist proposes a medication: "consider adding this" | the specialist | the GP | Jane | -- | proposal | MedicationRequest, POST |
| Dose change: "metformin 500 to 1000" | extraction graph | Dr. Lee | Jane | the prescription | proposal | two entries, PUT and POST |
| Retract a recorded allergy: "the consult letter refutes this" | extraction graph | Dr. Lee | Jane | the allergy | proposal | AllergyIntolerance, PUT |
| Arrange an appointment: "roughly this follow-up" | the doctor | reception | Jane | -- | order | Appointment, POST |
| Care-gap card: three ways to close one gap | a rule | Dr. Lee | Jane | -- | option, three of them | one each, shared card |
| Pooled work: anyone on the desk can take it | a person | the nursing pool | Jane | -- | order | -- |
| Administrative fax: "I cannot do this, the front desk has to" | whoever triaged it | the front desk | none | the fax | order | -- |
| Ask the AI a question: "what changed since I last saw her?" | Dr. Lee | the agent graph | Jane | -- | order | -- (the answer is a note) |
Notice what is not a task type in that table: "AI task", "patient task", "suggestion", "document review", "care-gap card", "appointment request", "AI chat". Every one of them is a combination of the same small set of elements. That is the entire argument for having one model: build the surface once, and all of these render on it.
There is a category axis, and it is only for filing. Task.code currently carries nine bins --
reminder, call, appointment, review-report, prevention, referral, billing, medication, other -- and
it is expected to grow. It says what kind of work a task is, for sorting a worklist. It does not say
what the task carries and it does not say who produced it. The binding is extensible, so a bin that
is not in the task code value set yet does not block
anybody.
Worked instances in the specification: a plain chart task, a lab review, an AI triage task, a suggestion that adds an entry, a suggestion that retires an entry, a card alternative, a team-owned task, a nursing-pool task, a referral, and all task examples.
The words, settled¶
Most of the disagreement in this area is vocabulary, not design. Here is each term used once.
This is the storage and interop vocabulary, not a screen-label proposal. Nothing here says a user has to see the word instantiate, or proposal, or focus. Two things do have to hold: that the same thing is meant by each word, and that whatever a screen calls something maps cleanly onto exactly one row of this table. Where a label covers two rows, that is the bug this section exists to catch.
| Term | Means exactly | Do not use it for |
|---|---|---|
| Task | The work item. All of them, including the ones people call something else | -- |
| Proposal | A task offered for a decision. intent = proposal |
Whether the task carries content |
| Order | A task that is authorized. intent = order |
Urgency. That is priority |
| Suggested-resource task | A task carrying a template of candidate chart entries, instantiated from the task by a user | Anything about who made it |
| Focus | The existing element the task is filed against -- whatever state it is in, and it need not belong to a patient | What the task would write; how finished the item is |
| Approve | Proposal becomes order. Writes nothing | Writing to the chart |
| Accept | Claim the work. Status becomes accepted |
Approving; instantiating |
| Instantiate | Write the carried candidates into the chart | Approving |
| Decline | Cancelled, with a reason. Task and payload retained | Deleting anything |
| Card | One evaluation's proposals, sharing a group identifier | A single suggestion |
Three words to stop using:
- "Review" on its own. It means at least four different things in an EMR: completing a
lab-review task, reading a document, claiming a pooled item, and a reopened referral's business
status. Say which one. This is also why the claimed state is called
acceptedand notreviewed. - "Suggestion" as a task type. There is no such category and searching for one returns nothing. Say proposal if you mean the decision, or suggested-resource task if you mean the payload.
- "Promote to a task" as though a second task appears. It is approve, on the task that already exists.
The whole model on one page¶
Six elements are required on every task: requester, owner, description, intent, status,
authoredOn. Everything below is optional, and set when it applies.
Placement
owner-- who currently has it. Exactly one.for-- which patient, if any.focus-- which existing item, if any. Patient optional.
Origin and authority
requester-- who asked. The only place that names which producer.AIASTlabel -- a machine produced this. On the task, not the payload.intent-- order, proposal, or one-of-several.
Content and conversation
description-- the ask. Required, stable.- contained bundle -- candidate chart entries, with a method each.
note-- what has been said since, authored and timed.
Lifecycle and grouping
status-- draft, ready, accepted, in-progress, on-hold, completed, cancelled.statusReason-- why. Near-required on a cancelled proposal.restriction.period-- the fulfillment window; its end is the due date.priority-- routine and up, withtrivialon a sibling extension.groupIdentifier-- raised together, as one card.- business key -- derived from the gap, so a re-run updates instead of duplicating.
The four invariants¶
- Owner controls inbox routing. Everything a provider owns is findable from their inbox. A consumer contract; no validator can check it.
- Patient controls chart visibility. Every task naming a patient is findable on that chart, whoever owns it. A consumer contract; no validator can check it.
- Focus always already exists. Draft or final, patient or none, it already exists, and it is never something inside the task. Enforced.
- Candidates are not chart content. Nothing reaches the chart until somebody instantiates it, and no query can see it before then. Enforced.
Two of these are checkable by a machine and two are only checkable by the people building the surfaces. That is worth knowing when deciding what to test.
What is not settled¶
The model above is stable. These are the parts that are not, stated as what is undecided and what would decide it.
- Whether approve is a gesture a user makes. The model expresses it cleanly -- a proposal becoming an order is one element change -- but whether a user should ever make that gesture is a separate question. For: a provider handles the prescription and the requisition during the visit and leaves the referral letter and the problem list until later, and moving the deferred ones into the task list is how those stop being suggestions and start being committed work. Against: it manufactures task volume in a system whose loudest complaint is already that there are too many tasks. What would decide it: a surface committing to the gesture.
- Whether accept is a gesture or only a state. The status exists and the circulation argument for it is sound. What would decide it: whether an explicit accept action is shown at all, or whether claiming work is simply implicit in starting it.
- Whether an instantiated task points at what it produced. Today the trail runs through the shared
business key and provenance. Setting
focusto the created resource would make "what came of this?" a single read, but every legal focus target is also a plausible instantiation target, so the two meanings could not be told apart by type. What would decide it: a way to distinguish them that does not overloadfocus. - Multi-hop reply. See above: the back-pointer is recoverable from provenance but not maintained on the task.
- Reopening a terminal task. Technically supportable, clinically contentious, and it muddies the audit. The better answer is a new task derived from the old one, and the business status built for this case is deprecated for that reason: a completed task does not come back to life.
- Documents with no patient. See above:
subjectis1..1on both document types. - Auditing patient-less work. Completed tasks that never had a patient are still work somebody did, and there is no chart to find them from. A per-user completed-task history covers it. What would decide it: whether that history is expected of an implementation or is a reporting concern.
- Snooze semantics. The
on-holdstatus exists. What releases a held task -- a person, a time, a trigger -- is not designed.
What is deliberately not open: the two axes, the containment, the status set, single ownership, and the conversation living on the task. Those are what the examples in this specification demonstrate, and reopening them costs more than it buys.
Related¶
- Clinical Tasks: the idea -- the same model in one short read.
- Clinical Task Design -- the profile, the state machine, ownership transfer and agent identity.
- Conversation Threading -- the one mechanism behind a colleague's question, an accepted suggestion, and a back-and-forth with an agent.
- Proposals -- intent, approving, declining, cards and alternatives.
- Suggested-Resource Tasks -- the contained transaction bundle in full, including the input type code system.
- AI Attribution -- the
AIASTlabel and what it does and does not claim. - Clinical Task profile -- the normative element definitions and invariants.