Skip to main content

Tasks

Tasks are the units of work in a process. The engine supports the standard BPMN task types — service, user, script, business-rule, send, receive, manual, and generic — and adds runtime metadata via the quantum: extension namespace.

Common attributes

AttributeNotes
idRequired; unique within the process
nameOptional display name
defaultID of an outgoing flow to take when every other outgoing flow's condition evaluates false. See Sequence Flow → Default flows for the full evaluation model
isForCompensationtrue marks the task as a compensation handler — it never runs on a normal sequence flow and must be linked to a compensation boundary event by an <association>. The validator rejects any isForCompensation="true" activity that has incoming sequence flows

Most tasks accept these extensions:

ExtensionPurpose
quantum:taskDefinitiontype (worker type string) and optional retries
quantum:ioMappingVariable mappings — see Common extensions
quantum:taskHeadersStatic headers passed to the worker — see Common extensions

Standard loop and multi-instance loop characteristics can be attached to most tasks — see Structure → Loops.


Service task

Delegates work to an external worker identified by a task type string. The engine creates a job for the configured type, hands it to a polling worker, and waits for the worker to complete or fail it.

Required configuration

AttributeNotes
quantum:taskDefinition typeWorker type string. Required — without it, deployment fails
quantum:taskDefinition retriesOptional retry attempts on failure (e.g. "3")

Example

<bpmn:serviceTask id="charge-card" name="Charge Credit Card">
<bpmn:extensionElements>
<quantum:taskDefinition type="payment-worker" retries="3" />
<quantum:ioMapping>
<quantum:input source="=orderId" target="order_id" />
<quantum:input source="=totalAmount" target="amount" />
<quantum:output source="=result.transactionId" target="transactionId" />
</quantum:ioMapping>
<quantum:taskHeaders>
<quantum:header key="currency" value="USD" />
</quantum:taskHeaders>
</bpmn:extensionElements>
<bpmn:incoming>f1</bpmn:incoming>
<bpmn:outgoing>f2</bpmn:outgoing>
</bpmn:serviceTask>

For details on writing workers, see External workers.

Validation

CheckSeverity
quantum:taskDefinition type is missing or emptyError

User task

Requires a human to complete the work. The engine evaluates the assignment fields, registers the task with the platform's user-task system, and waits for an external completion signal.

Configuration

ExtensionNotes
quantum:assignmentDefinition assignee="..."Single assigned user
quantum:assignmentDefinition candidateGroups="..."Comma-separated list of groups who can claim the task
quantum:assignmentDefinition candidateUsers="..."Comma-separated list of candidate users
quantum:formDefinition formKey="..."Form key used by the UI to render the task
quantum:formDefinition formId="..."Form definition ID
quantum:taskDefinition type="..."Optional; only relevant for custom user-task backends

A user task can carry an error boundary event. Completing the task with an error code routes the token through the boundary instead of the normal outgoing flow.

Example

<bpmn:userTask id="approve-request" name="Approve Request">
<bpmn:extensionElements>
<quantum:assignmentDefinition assignee="manager" candidateGroups="approvers, leads" />
<quantum:formDefinition formKey="approve-form" />
<quantum:ioMapping>
<quantum:input source="=requestId" target="request_id" />
<quantum:output source="=approved" target="isApproved" />
</quantum:ioMapping>
</bpmn:extensionElements>
<bpmn:incoming>f1</bpmn:incoming>
<bpmn:outgoing>f2</bpmn:outgoing>
</bpmn:userTask>

Script task

Executes an inline script in the engine. FEEL is the supported script language.

Attributes

AttributeNotes
scriptFormatSet to "feel"

The script body goes inside a <script> child element. Output mappings can pull values out of the script's local scope and write them to the parent scope.

Example

<bpmn:scriptTask id="calculate-total" name="Calculate Total" scriptFormat="feel">
<bpmn:extensionElements>
<quantum:ioMapping>
<quantum:output source="=total" target="orderTotal" />
</quantum:ioMapping>
</bpmn:extensionElements>
<bpmn:incoming>f1</bpmn:incoming>
<bpmn:outgoing>f2</bpmn:outgoing>
<bpmn:script>{ total: sum(items.price) }</bpmn:script>
</bpmn:scriptTask>

Business rule task

Invokes a decision and stores the result in a process variable. Two modes are supported, mirroring the send-task shape: embedded DMN evaluation (the engine runs the rule) or external worker dispatch (a worker performs the evaluation, e.g. against a remote rules engine).

Execution modes

ModeWhen activeBehavior
Embedded DMNquantum:calledDecision decisionId="..." is setEngine evaluates the named DMN decision synchronously and stores the result in resultVariable
External workerquantum:taskDefinition type="..." is set, no calledDecisionEngine creates a job — same semantics as a service task (retries, headers, boundary events, I/O mappings). The worker performs the rule evaluation and returns the result

At least one mode must be configured. Setting both is a warning: the external-worker dispatch wins and calledDecision is ignored.

Required configuration — embedded DMN

ExtensionNotes
quantum:calledDecision decisionId="..."Required. ID of the DMN decision to evaluate
quantum:calledDecision resultVariable="..."Required. Variable name to store the decision output
quantum:calledDecision bindingType="..."Optional; how to select the decision version (e.g. "versionTag")
quantum:calledDecision versionTag="..."Used when bindingType="versionTag"

Input mappings prepare the input data the decision expects; output mappings extract fields from the decision result for downstream use.

Example

<bpmn:businessRuleTask id="check-eligibility" name="Check Eligibility">
<bpmn:extensionElements>
<quantum:calledDecision decisionId="eligibility-rules" resultVariable="eligibilityResult" />
<quantum:ioMapping>
<quantum:input source="=customerAge" target="age" />
<quantum:input source="=annualIncome" target="income" />
<quantum:output source="=eligibilityResult.eligible" target="isEligible" />
</quantum:ioMapping>
</bpmn:extensionElements>
<bpmn:incoming>f1</bpmn:incoming>
<bpmn:outgoing>f2</bpmn:outgoing>
</bpmn:businessRuleTask>

Example — external worker

<bpmn:businessRuleTask id="check-eligibility-remote" name="Check Eligibility (remote)">
<bpmn:extensionElements>
<quantum:taskDefinition type="rules-worker" retries="2" />
<quantum:ioMapping>
<quantum:input source="=customerAge" target="age" />
<quantum:input source="=annualIncome" target="income" />
<quantum:output source="=result.eligible" target="isEligible" />
</quantum:ioMapping>
</bpmn:extensionElements>
<bpmn:incoming>f1</bpmn:incoming>
<bpmn:outgoing>f2</bpmn:outgoing>
</bpmn:businessRuleTask>

Validation

CheckSeverity
Neither quantum:calledDecision nor quantum:taskDefinition is setError
quantum:calledDecision is set but resultVariable is missingError
Both quantum:calledDecision and quantum:taskDefinition are setWarning (taskDefinition wins; calledDecision is ignored)

Send task

Emits a message and advances. Operates in one of two modes depending on what extensions are present.

Execution modes

ModeWhen activeBehavior
Direct publishmessageRef is set, no quantum:taskDefinitionResolves the message name from the global declaration, publishes the message with the current scope variables, advances immediately
External jobquantum:taskDefinition type="..." is setCreates a job for a worker — same semantics as a service task (retries, headers, boundary events, I/O mappings). Waits for worker completion

If neither is set, the task is a no-op pass-through. If both are set, the worker mode wins.

Examples

<!-- Direct publish -->
<bpmn:sendTask id="send-order" name="Notify Order Placed" messageRef="Msg_OrderPlaced">
<bpmn:incoming>f1</bpmn:incoming>
<bpmn:outgoing>f2</bpmn:outgoing>
</bpmn:sendTask>

<!-- Worker mode (e.g. SMTP, SMS) -->
<bpmn:sendTask id="notify-customer" name="Send Confirmation Email">
<bpmn:extensionElements>
<quantum:taskDefinition type="email-sender" retries="2" />
<quantum:ioMapping>
<quantum:input source="=customerEmail" target="to" />
<quantum:input source="=orderId" target="order_id" />
</quantum:ioMapping>
<quantum:taskHeaders>
<quantum:header key="template" value="order-confirmation" />
</quantum:taskHeaders>
</bpmn:extensionElements>
<bpmn:incoming>f1</bpmn:incoming>
<bpmn:outgoing>f2</bpmn:outgoing>
</bpmn:sendTask>

Receive task

Blocks until a correlated message arrives. The message is referenced by messageRef. If a buffered message is already available it fires immediately; otherwise the task waits.

messageRef is required. The runtime subscribes to the Temporal signal "message:" + <resolved name>; an empty name produces a subscription that no publish can ever match, leaving the task waiting forever. The validator rejects receive tasks without a messageRef.

Example

<bpmn:receiveTask id="wait-for-payment" name="Wait for Payment" messageRef="Msg_Payment">
<bpmn:extensionElements>
<quantum:ioMapping>
<quantum:output source="=amount" target="paidAmount" />
</quantum:ioMapping>
</bpmn:extensionElements>
<bpmn:incoming>f1</bpmn:incoming>
<bpmn:outgoing>f2</bpmn:outgoing>
</bpmn:receiveTask>

Validation

CheckSeverity
messageRef is missing or emptyError
messageRef references an unknown <message> definitionError

Manual task

Represents work performed entirely outside the engine, with no automated execution. The engine treats it like a service task: it creates a job and waits for an external system to complete it.

Example

<bpmn:manualTask id="physical-review" name="Physical Document Review">
<bpmn:extensionElements>
<quantum:taskDefinition type="manual-review-handler" />
</bpmn:extensionElements>
<bpmn:incoming>f1</bpmn:incoming>
<bpmn:outgoing>f2</bpmn:outgoing>
</bpmn:manualTask>

Generic task

<task> with no specific type. Treated as a service task — same extensions, same validation. Use it when the task category isn't relevant to the model.

Example

<bpmn:task id="generic-step" name="Generic Step">
<bpmn:extensionElements>
<quantum:taskDefinition type="generic-handler" />
</bpmn:extensionElements>
<bpmn:incoming>f1</bpmn:incoming>
<bpmn:outgoing>f2</bpmn:outgoing>
</bpmn:task>