Future Action Rule Schema
A future action rule defines a scheduled clinical action that appears on a patient's care record. It targets a cohort of patients (via an external or inline patient query) and creates a future action with planned start and end dates. The rule tracks whether the action has been completed within the configured window.
See the Patient Query Language reference for full documentation of inline patient query syntax.
Two authoring patterns are supported:
- Pattern A (fixed dates): The planned start and end dates are literal
YYYY-MM-DDvalues. - Pattern B (variable dates): Dates are computed at runtime using variables defined in
additionalVariables. This is required when planned dates depend on patient data (for example, scheduling an annual check from the patient's last recorded measurement).
Examples
Pattern A: fixed dates
<?xml version="1.0" encoding="UTF-8"?>
<futureActionRule>
<identifier>my-org/annual-flu-vaccination-2025</identifier>
<name>Annual Flu Vaccination 2025/26</name>
<description>Annual influenza vaccination for eligible patients.</description>
<targetPatientQuery id="my-org/flu-eligible-patients-2025"/>
<completionWindow type="CURRENT_FINANCIAL_YEAR"/>
<futureAction
code="822851000000102"
plannedStartDate="2025-09-01"
plannedEndDate="2026-03-31"
codeDescription="Annual flu vaccination"
paymentPeriodStartDate="2025-04-01"
paymentPeriodEndDate="2026-03-31"
paymentPeriodLabel="QOF 2025/26"
/>
</futureActionRule>
Pattern B: variable dates
This example schedules a blood pressure check based on when the patient last had one measured, targeting a five-yearly recall.
<?xml version="1.0" encoding="UTF-8"?>
<futureActionRule>
<identifier>my-org/five-yearly-bp-check</identifier>
<name>Five-yearly Blood Pressure Check</name>
<description>Recalls patients aged 45 or over who have not had a blood pressure recorded in the past five years.</description>
<targetPatientQuery id="my-org/bp-recall-patients"/>
<patientQueryRuntimeValue name="Today">
<runtimeValue name="ACHV_DAT">today</runtimeValue>
<runtimeValue name="PPED">today</runtimeValue>
</patientQueryRuntimeValue>
<additionalVariables>
<codeLists>
<codeList>
<name>BP_COD</name>
<reference>my-org/BP_COD</reference>
</codeList>
</codeLists>
<runtimeValues>
<fixedDate name="ACHV_DAT" runtimeValue="true"/>
<fixedDate name="PPED" runtimeValue="true"/>
</runtimeValues>
<variables>
<codedEntryDate
name="LAST_BP_DAT"
codeList="BP_COD"
fetch="latest"
logic="LTEQ ACHV_DAT"
/>
<derivedCodedEntryDate
name="PLANNED_DATE"
codedEntryDateName="LAST_BP_DAT"
operation="+5 years"
/>
</variables>
</additionalVariables>
<completionWindow type="CURRENT_FINANCIAL_YEAR"/>
<futureAction
code="75367002"
plannedStartDate="PLANNED_DATE"
plannedEndDate="PLANNED_DATE"
codeDescription="Blood pressure measurement"
paymentPeriodStartDate="2025-04-01"
paymentPeriodEndDate="2026-03-31"
paymentPeriodLabel="QOF 2025/26"
/>
</futureActionRule>
Schema
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<!--
Schema for authorable Future Action Rule XML.
A future action rule drives the creation of future actions on patient care records.
Two authoring patterns are supported:
Pattern A: Fixed dates:
<futureAction code="..." plannedStartDate="2025-04-01" plannedEndDate="2026-03-31"/>
No <additionalVariables> section required.
Pattern B: Variable references:
<additionalVariables>
<codeLists>...</codeLists>
<runtimeValues>...</runtimeValues>
<variables>...</variables>
</additionalVariables>
<futureAction code="..." plannedStartDate="PLANNED_START" plannedEndDate="PLANNED_END"/>
Variable names in plannedStartDate/plannedEndDate must be defined in <variables> or <runtimeValues>.
-->
<!-- ===== Enumerations ===== -->
<xs:simpleType name="completionWindowType">
<xs:restriction base="xs:string">
<!--
CURRENT_FINANCIAL_YEAR: action is considered completed if the patient already
has the target code recorded within the current NHS financial year (Apr to Mar).
AFTER_FUTURE_ACTION_PLANNED_START: action is considered completed once the
planned start date has passed, regardless of financial year.
-->
<xs:enumeration value="CURRENT_FINANCIAL_YEAR"/>
<xs:enumeration value="AFTER_FUTURE_ACTION_PLANNED_START"/>
</xs:restriction>
</xs:simpleType>
<!-- ===== targetPatientQuery ===== -->
<!--
Identifies the patient cohort this rule applies to. There are two mutually exclusive configurations::
- id attribute: references an external patient query by identifier e.g. <targetPatientQuery id="nhs-england/AF006-2025-FUTURE-ACTION"/>
- inline child: embeds a <patientQuery> element directly e.g. <targetPatientQuery><patientQuery>...</patientQuery></targetPatientQuery>
Using both, or neither, is an error caught at runtime.
-->
<xs:complexType name="targetPatientQueryType">
<xs:sequence>
<xs:element name="patientQuery" minOccurs="0">
<xs:complexType mixed="true">
<xs:sequence>
<xs:any processContents="lax" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
<xs:attribute name="focus" use="required">
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:enumeration value="patients"/>
</xs:restriction>
</xs:simpleType>
</xs:attribute>
</xs:complexType>
</xs:element>
</xs:sequence>
<xs:attribute name="id" type="xs:string" use="optional"/>
</xs:complexType>
<!-- ===== patientQueryRuntimeValue ===== -->
<!--
Passes runtime values (e.g. today's date) into the target patient query.
Example:
<patientQueryRuntimeValue name="Today">
<runtimeValue name="ACHV_DAT">today</runtimeValue>
<runtimeValue name="PPED">today</runtimeValue>
</patientQueryRuntimeValue>
-->
<xs:complexType name="runtimeValueEntryType">
<xs:simpleContent>
<xs:extension base="xs:string">
<xs:attribute name="name" type="xs:string" use="required"/>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
<xs:complexType name="patientQueryRuntimeValueType">
<xs:sequence>
<xs:element name="runtimeValue" type="runtimeValueEntryType" maxOccurs="unbounded"/>
</xs:sequence>
<xs:attribute name="name" type="xs:string" use="required"/>
</xs:complexType>
<!-- ===== additionalVariables ===== -->
<!--
fixedDate in <runtimeValues>: a date whose value is injected at runtime.
runtimeValue="true" marks it as a runtime-injected value (e.g. "today").
-->
<xs:complexType name="fixedDateType">
<xs:attribute name="name" type="xs:string" use="required"/>
<xs:attribute name="runtimeValue" type="xs:boolean" use="optional"/>
<xs:attribute name="value" type="xs:string" use="optional"/>
</xs:complexType>
<!--
<codeLists>: named code list references used in variable definitions.
Content is opaque, new code list element types may be added by the patient
query engine without requiring an XSD change.
-->
<xs:complexType name="codeListsSectionType">
<xs:sequence>
<xs:any processContents="lax" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
<!--
<runtimeValues>: fixed dates whose values are injected at execution time.
Only <fixedDate> elements with runtimeValue="true" are valid here.
-->
<xs:complexType name="runtimeValuesSectionType">
<xs:sequence>
<xs:element name="fixedDate" type="fixedDateType" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
<!--
<variables>: computation logic: derivedFixedDate, patientEntryDate,
derivedPatientEntryDate, codedEntryDate, aggregatedEntryDate,
derivedCodedEntryDate, entryDateFromList, and others.
Content is opaque, new variable types are added by the patient query engine.
-->
<xs:complexType name="variablesSectionType">
<xs:sequence>
<xs:any processContents="lax" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
<!--
<additionalVariables>: optional for fixed-date rules; required for variable-reference rules.
Must use the three-section structure: <codeLists>, <runtimeValues>, <variables>.
Legacy flat structure (variables directly under <additionalVariables>) is not supported.
-->
<xs:complexType name="additionalVariablesType">
<xs:sequence>
<xs:element name="codeLists" type="codeListsSectionType" minOccurs="0"/>
<xs:element name="runtimeValues" type="runtimeValuesSectionType" minOccurs="0"/>
<xs:element name="variables" type="variablesSectionType" minOccurs="0"/>
</xs:sequence>
</xs:complexType>
<!-- ===== completionWindow ===== -->
<xs:complexType name="completionWindowElementType">
<xs:attribute name="type" type="completionWindowType" use="required"/>
</xs:complexType>
<!-- ===== futureAction ===== -->
<!--
Defines the action to be created on the patient care record.
Required attributes:
code - SNOMED CT code for the future action
plannedStartDate - start date (YYYY-MM-DD) or variable name from <variables>/<runtimeValues>
plannedEndDate - end date (YYYY-MM-DD) or variable name from <variables>/<runtimeValues>
Optional attributes:
codeDescription - overrides the default SNOMED preferred term shown to the user; must not be empty if present
details - additional free-text context displayed on the action
paymentPeriodStartDate - start of the payment period (YYYY-MM-DD or variable name)
paymentPeriodEndDate - end of the payment period (YYYY-MM-DD or variable name)
paymentPeriodLabel - label shown for the payment period e.g. "QOF 2025/26"
-->
<xs:complexType name="futureActionType">
<xs:attribute name="code" type="xs:string" use="required"/>
<xs:attribute name="plannedStartDate" type="xs:string" use="required"/>
<xs:attribute name="plannedEndDate" type="xs:string" use="required"/>
<xs:attribute name="codeDescription" type="xs:string" use="optional"/>
<xs:attribute name="details" type="xs:string" use="optional"/>
<xs:attribute name="paymentPeriodStartDate" type="xs:string" use="optional"/>
<xs:attribute name="paymentPeriodEndDate" type="xs:string" use="optional"/>
<xs:attribute name="paymentPeriodLabel" type="xs:string" use="optional"/>
</xs:complexType>
<!-- ===== Root element ===== -->
<!--
Element order within <futureActionRule>:
1. identifier (required) - unique rule identifier, e.g. "medicus-health/my-rule"
2. name (required) - human-readable name shown in the UI
3. description (optional) - longer description of what the rule does
4. targetPatientQuery (required) - patient cohort (external id or inline patientQuery)
5. patientQueryRuntimeValue (optional, repeatable) - runtime values for the patient query
6. additionalVariables (optional) - variable definitions for planned date computation
7. completionWindow (required) - when the action is considered completed
8. futureAction (required) - the action to be created
-->
<xs:element name="futureActionRule">
<xs:complexType>
<xs:sequence>
<xs:element name="identifier" type="xs:string"/>
<xs:element name="name" type="xs:string"/>
<xs:element name="description" type="xs:string" minOccurs="0"/>
<xs:element name="targetPatientQuery" type="targetPatientQueryType"/>
<xs:element name="patientQueryRuntimeValue" type="patientQueryRuntimeValueType" minOccurs="0" maxOccurs="unbounded"/>
<xs:element name="additionalVariables" type="additionalVariablesType" minOccurs="0"/>
<xs:element name="completionWindow" type="completionWindowElementType"/>
<xs:element name="futureAction" type="futureActionType"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
Additional variables reference
The <variables> section inside additionalVariables is validated loosely (not against a fixed schema), so it accepts a different, smaller set of elements than the <variables> section in Custom Report Schema and Patient Query Language. The two used in Pattern B above:
codedEntryDate
Finds coded entries matching a code list declared in this same additionalVariables block, similar in purpose to codedEntryVariable in custom reports.
| Attribute | Required | Description |
|---|---|---|
name | Yes | Variable name, referenced in codedEntryDateName (below) or in futureAction date attributes |
codeList | Yes | Name of a code list declared in this block's <codeLists> section |
fetch | Yes | latest, earliest, or all |
logic | No | Date range filter expression on the entry's date (e.g. LTEQ ACHV_DAT), same syntax as clinicallyRelevantDate in custom reports |
derivedCodedEntryDate
Computes a date by adding or subtracting a period from a codedEntryDate variable's result, analogous to derivedFixedDate in custom reports.
| Attribute | Required | Description |
|---|---|---|
name | Yes | Variable name, referenced in futureAction date attributes |
codedEntryDateName | Yes | Name of a codedEntryDate variable declared above |
operation | Yes | Date arithmetic expression, e.g. +5 years, -3 months first day of this month |
Key elements
| Element / Attribute | Required | Description |
|---|---|---|
identifier | Yes | Unique identifier for the rule, e.g. my-org/annual-flu-2025. |
name | Yes | Human-readable name shown in the UI. |
description | No | Longer description of what the rule does. |
targetPatientQuery @id | One of id or inline | References an external patient query by its identifier. |
targetPatientQuery > patientQuery | One of id or inline | Embeds an inline patient query with focus="patients". |
patientQueryRuntimeValue | No | Passes runtime values (e.g. today's date) into the target patient query. |
additionalVariables | No (required for Pattern B) | Variable definitions for computed planned dates. Uses three sections: codeLists, runtimeValues, variables. |
completionWindow @type | Yes | CURRENT_FINANCIAL_YEAR or AFTER_FUTURE_ACTION_PLANNED_START. |
futureAction @code | Yes | SNOMED CT concept ID for the future action. |
futureAction @plannedStartDate | Yes | Start date: a literal YYYY-MM-DD (Pattern A) or a variable name (Pattern B). |
futureAction @plannedEndDate | Yes | End date: a literal YYYY-MM-DD (Pattern A) or a variable name (Pattern B). |
futureAction @codeDescription | No | Overrides the default SNOMED CT preferred term shown to the user. Must not be empty if present. |
futureAction @details | No | Additional free-text context displayed on the action. |
futureAction @paymentPeriodStartDate | No | Start of the payment period (YYYY-MM-DD or variable name). |
futureAction @paymentPeriodEndDate | No | End of the payment period (YYYY-MM-DD or variable name). |
futureAction @paymentPeriodLabel | No | Label shown for the payment period, e.g. QOF 2025/26. |