Skip to content

BPMN coverage

Use this page to check whether a BPMN element you want to model will deploy and run in TinyConductor. It covers BPMN 2.0 elements, event definitions and TinyConductor’s extension elements and attributes (the tc: namespace).

TinyConductor aims to behave like version 8.9 of an existing engine, the compatibility target. Every rating on this page compares TinyConductor with it; Compatibility explains what “compatible” means.

The icons follow the BPMN 2.0 notation. The outline of an event tells you where it sits; the marker inside tells you its trigger. The examples use the message trigger.

StartIntermediate catchIntermediate throwBoundary, interruptingBoundary, non-interruptingEnd
Message start eventMessage intermediate catch eventMessage intermediate throw eventMessage boundary event (interrupting)Message boundary event (non-interrupting)Message end event
thin circledouble circledouble circledouble circledouble dashed circlethick circle
  • Start, intermediate, end. A thin single circle is a start event, a double circle is an intermediate or boundary event, and a thick circle is an end event.
  • Catch and throw. An outlined marker catches (waits for) the trigger. A filled marker throws (sends) it.
  • Interrupting and non-interrupting. A solid border interrupts the activity or scope it belongs to. A dashed border lets it keep running. The same rule applies to event sub-process start events.
  • Activities and gateways. A task’s type is the marker in its top-left corner. A marker at the bottom centre shows a sub-process (+), a loop or multi-instance, or a compensation handler. The symbol inside a gateway diamond shows its type.
SymbolMeaning
✅Supported. Deploys and runs as the compatibility target does.
🟡Partial. Deploys and runs, with a difference you may meet in normal use. The note or row says which.
❌Not supported. Rejected at deployment. These elements are outside the set of BPMN features TinyConductor is designed to run, and the compatibility target doesn’t run them either.
🚧In progress. Work is underway, but nothing is available yet.
—Not a valid BPMN combination.
✅ Supported🟡 Partial❌ Not supported🚧 In progress
994210

The ❌ entries are the transaction sub-process, the complex gateway, the loop marker, the instantiating receive task, cancel, multiple and parallel-multiple events, and compensation event sub-processes. No element that the compatibility target runs is rejected. Every rating is backed by TinyConductor’s conformance test suite: small process models, each run against its expected results.


ElementStatusWhat to know
Pool (participant)Pools (participants)✅Each executable process in the file is deployed, and a pool whose process is not executable is skipped. A file needs at least one executable process.
Lanes in a poolLanes✅Modelling only: accepted and ignored at runtime.
Message flowMessage flows✅Modelling only: they don’t send messages. To send one, use a send task or a message throw event with a job worker.
ElementStatusWhat to know
Sub-process (collapsed)Embedded sub-process✅Supported with boundary events and event sub-processes inside it.
Call activityCall activity✅Calls a process by a fixed processId or a FEEL expression; an id that no deployed process has raises an incident. Boundary events, cancellation and output mappings pass through to the called process.
Event sub-processEvent sub-process✅Interrupting and non-interrupting, in the process, in embedded sub-processes and in ad-hoc sub-processes. Inside an ad-hoc sub-process only a non-interrupting one is allowed.
Ad-hoc sub-processAd-hoc sub-process✅tc:adHoc activeElementsCollection names the elements to start, and outputCollection and outputElement collect a result from each. The BPMN completionCondition and cancelRemainingInstances are supported; start and end events inside one are rejected at deployment.
Ad-hoc sub-processWorker-driven ad-hoc sub-process✅With tc:taskDefinition on the ad-hoc sub-process, a job worker chooses the elements to activate and says when the sub-process is done. It gets a new job when the sub-process starts and after each activated element completes.
Transaction sub-processTransaction sub-process❌Rejected at deployment.
ElementStatusWhat to know
Service taskService task✅Creates a job for a worker. If the job type or retries can’t be evaluated, an incident is raised before the job is created.
User taskUser task (native user task, tc:userTask)✅Native user-task lifecycle, with a user-task API.
User taskUser task (job-worker form, no tc:userTask)🟡Runs as a native user task too, so a job worker that polls for user tasks never sees it. See Known differences.
Send taskSend task✅Creates a job of its tc:taskDefinition type, and the worker sends the message. Without tc:taskDefinition it deploys, but raises an incident when it is reached.
Receive taskReceive task✅Waits for the message named by its messageRef, with the correlation key from tc:subscription. A receive task without a messageRef is rejected at deployment.
Receive task (instantiating)Receive task, instantiating (instantiate="true")❌Rejected at deployment. Use a message start event to start a process from a message.
Script taskScript task, inline FEEL (tc:script)✅Evaluated in the engine, and the result goes to resultVariable. A script task needs exactly one of tc:script or tc:taskDefinition.
Script taskScript task, job-worker form (tc:taskDefinition)✅Creates a job like a service task. The JavaScript script worker runs it; see Script tasks.
Business rule taskBusiness rule task, DMN (tc:calledDecision)✅Evaluates the decision in the engine. A version tag written on a single decision element isn’t read yet; see bindingType below.
Business rule taskBusiness rule task, job worker (tc:taskDefinition)✅Creates a job, like a service task.
Manual taskManual task✅Passes straight through.
Task (undefined type)Undefined task (bpmn:task)✅Passes straight through.
ElementStatusWhat to know
Exclusive gatewayExclusive (XOR)✅Takes the first flow whose condition is true, otherwise the default flow. With no match and no default, it raises an incident.
Parallel gatewayParallel (AND), fork and join✅Splits into parallel paths and waits for all of them where they join.
Inclusive gatewayInclusive (OR), fork✅Takes every flow whose condition is true, or the default flow; a flow without a condition counts as true. With no match and no default, it raises an incident.
Inclusive gatewayInclusive (OR), join✅Continues once every incoming flow has been taken, or once no active path can still reach one that hasn’t.
Event-based gatewayEvent-based✅Can be followed by message, timer, signal or conditional catch events, or by receive tasks; anything else is rejected at deployment. The first event to happen wins.
Complex gatewayComplex❌Rejected at deployment.

Each cell shows the event’s icon and its status. A superscript number points to a note below the table. “Start” is a process-level start event, “ESP” is an event sub-process start event, and “Catch” and “Throw” are intermediate events.

DefinitionStartESP interruptingESP non-interruptingCatchThrowBoundary interruptingBoundary non-interruptingEnd
NoneNone start event: supported ———None intermediate throw event: supported ——None end event: supported
MessageMessage start event: supported note 1Message event sub-process start event (interrupting): supported note 2Message event sub-process start event (non-interrupting): supported note 2Message intermediate catch event: supported Message intermediate throw event: supported note 3Message boundary event (interrupting): supported Message boundary event (non-interrupting): supported Message end event: supported note 3
TimerTimer start event: supported note 4Timer event sub-process start event (interrupting): supported Timer event sub-process start event (non-interrupting): supported Timer intermediate catch event: supported —Timer boundary event (interrupting): supported Timer boundary event (non-interrupting): supported —
Error—Error event sub-process start event (interrupting): partial support note 5———Error boundary event (interrupting): partial support note 5—Error end event: supported
SignalSignal start event: supported note 6Signal event sub-process start event (interrupting): supported Signal event sub-process start event (non-interrupting): supported Signal intermediate catch event: supported Signal intermediate throw event: supported Signal boundary event (interrupting): supported Signal boundary event (non-interrupting): supported Signal end event: supported
ConditionalConditional start event: partial support note 7Conditional event sub-process start event (interrupting): supported note 8Conditional event sub-process start event (non-interrupting): supported note 8Conditional intermediate catch event: supported note 8—Conditional boundary event (interrupting): supported note 8Conditional boundary event (non-interrupting): supported note 8—
Escalation—Escalation event sub-process start event (interrupting): supported note 9Escalation event sub-process start event (non-interrupting): supported —Escalation intermediate throw event: supported Escalation boundary event (interrupting): supported note 9Escalation boundary event (non-interrupting): supported note 9Escalation end event: supported
Compensation—Compensation event sub-process start event (interrupting): not supported ——Compensation intermediate throw event: supported note 10Compensation boundary event (interrupting): supported note 10—Compensation end event: supported note 10
Link———Link intermediate catch event: supported note 11Link intermediate throw event: supported note 11———
Terminate———————Terminate end event: supported note 12
Cancel—————Cancel boundary event (interrupting): not supported —Cancel end event: not supported
MultipleMultiple start event: not supported Multiple event sub-process start event (interrupting): not supported Multiple event sub-process start event (non-interrupting): not supported Multiple intermediate catch event: not supported Multiple intermediate throw event: not supported Multiple boundary event (interrupting): not supported Multiple boundary event (non-interrupting): not supported Multiple end event: not supported
Parallel multipleParallel multiple start event: not supported Parallel multiple event sub-process start event (interrupting): not supported Parallel multiple event sub-process start event (non-interrupting): not supported Parallel multiple intermediate catch event: not supported —Parallel multiple boundary event (interrupting): not supported Parallel multiple boundary event (non-interrupting): not supported —
  1. Message start. While an instance started by a message with a correlation key is active, another message with that key doesn’t start a second instance. The next one starts when the first instance ends.
  2. Message event sub-process. The correlation key is read before the process’s start-event output mappings are applied, so it can’t use a variable those mappings create.
  3. Message throw and end events. The event doesn’t send the message itself. With tc:taskDefinition it creates a job, like a send task, and the worker sends the message. With tc:publishMessage it completes without a job and publishes nothing, as the compatibility target does.
  4. Timer start. Time date, duration and cycle (ISO repeat and cron) are supported. An invalid fixed date, duration or cycle is rejected at deployment.
  5. Error catch. A catch for a specific error code wins over a catch-all. When a job worker throws a BPMN error with variables, the catch path doesn’t yet see them in every case.
  6. Signal start. Two start events of one process can’t use the same signal name; the deployment is rejected.
  7. Root-level conditional start. It deploys, but nothing starts an instance through it yet: TinyConductor doesn’t offer the request that asks the engine to evaluate the conditions. A process that also has a none start event can be started normally.
  8. Conditional events. A condition that can’t be evaluated, or doesn’t give true or false, counts as false: no incident is raised and the event keeps waiting. tc:conditionalFilter limits which variable changes are checked.
  9. Escalation catch. An escalation boundary event must be attached to a sub-process or call activity. A catch for a specific code wins over a catch-all.
  10. Compensation. Handlers run at the same time, not in reverse order, and compensation doesn’t reach into called processes. waitForCompletion="false" is rejected, and a compensation boundary event needs an association to its handler.
  11. Link events. A link throw event continues at the link catch event with the same name in the same scope; several throws can lead to one catch. A link throw can’t have an outgoing sequence flow, and a link catch can’t have an incoming one.
  12. Terminate end event. Ends its own scope (the process, an embedded sub-process or an event sub-process) and everything still active in it.
MarkerStatusWhat to know
Multi-instance marker (parallel)Multi-instance, parallel✅On tasks, sub-processes, call activities and ad-hoc sub-processes, with input and output collections and a completionCondition. The output collection is created in the enclosing scope when all instances have completed.
Multi-instance marker (sequential)Multi-instance, sequential✅Runs the instances one after another.
Loop markerLoop (standard loop)❌Rejected at deployment, and the console’s Modeler flags it. Use multi-instance instead.
Compensation markerCompensation (activity is a handler)✅The handler must have no incoming or outgoing sequence flows and no boundary events.
FeatureStatusWhat to know
Data objectData objects, data object references✅Modelling only: accepted and ignored. Use process variables for data.
Data storeData stores, data store references✅Modelling only: accepted and ignored.
Text annotation and associationText annotations, groups, associations✅Modelling only. An association also links a compensation boundary event to its handler.
Data input and data outputInput and output mappings (tc:ioMapping)✅A source starting with = is FEEL; any other source is a literal string. A mapping with invalid FEEL or an invalid target name is rejected at deployment.
Process variables and scopes✅Local and propagated variables work, and so does propagateAllChildVariables.
Cluster variables (tinyconductor.vars in FEEL)✅Read in any expression; see Cluster variables.

TinyConductor’s extensions live in its own namespace, https://schema.tinyfactory.ai/tinyconductor/bpmn/1.0, written with the prefix tc: on this page. Any prefix bound to that address works. Models written in the compatibility namespace deploy unchanged (see Compatibility). Extensions of any other namespace stay in the stored model and are ignored.

Length limits. Ids and names of process elements, messages, signals, errors and escalations, fixed job types, property names, resource names, DMN ids and names, and form ids may be at most 256 characters, as in the compatibility target. A deployment over the limit is rejected with a message that names every element over it. Set CONDUCTOR_MAX_NAME_FIELD_LENGTH to change the limit (see Cluster mode).

ExtensionStatusWhat to know
tc:taskDefinition (type, retries)✅Both accept FEEL. Also used on send tasks, message throw and end events, job-worker script and business rule tasks, and worker-driven ad-hoc sub-processes.
tc:taskHeaders✅Values are passed through exactly as written, including a leading =. Connectors depend on this.
tc:ioMapping✅See Data.
tc:calledElement processId✅A fixed id or a FEEL expression.
tc:calledElement propagateAllChildVariables / propagateAllParentVariables✅Copies all variables from the child back to the parent, or from the parent into the child.
tc:calledElement / tc:calledDecision bindingType✅latest, versionTag and deployment. With deployment, a fixed target must be part of the same deployment. A decision’s version tag is read only when the DMN file sets it for the whole file.
tc:versionTag✅At most one per process. Used by bindingType="versionTag".
Form linking (tc:formDefinition formKey, formId, externalReference)✅A formId is resolved to the deployed form; a missing form raises an incident.
Form definition inside the process model (tc:userTaskForm)✅Accepted.
tc:assignmentDefinition assignee✅The user the task is assigned to when it is created: alice for a person of the default identity provider, alice@corp for one of the provider corp (Who a person is).
tc:assignmentDefinition candidateUsers / candidateGroups✅The users and groups who may claim the task. Users are named like the assignee.
tc:taskSchedule dueDate / followUpDate✅A literal date is recorded in its shortest ISO-8601 form.
tc:priorityDefinition (user task priority)✅0 to 100, default 50, as a literal or an expression. A literal outside the range is rejected at deployment; an expression result outside it raises an incident.
tc:userTask (native user task marker)✅Every user task gets the native lifecycle anyway (see the user task rows).
tc:executionListeners✅On the process, sub-processes, call activities, tasks, events and gateways; each listener is a job that runs before or after the element’s work. Placements the compatibility target doesn’t support are rejected at deployment, such as start listeners on start or boundary events.
tc:taskListeners (creating, assigning, updating, completing)✅Each listener is a job that blocks the task change until it completes, and can correct the task or deny the change. Allowed only on user tasks.
tc:taskListeners canceling✅Runs whenever a user task is cancelled, and whatever cancels it waits for the listeners. A process instance modification skips them.
tc:script (expression, resultVariable)✅See the script task rows.
tc:calledDecision (decisionId, resultVariable)✅decisionId can be FEEL.
tc:subscription (correlationKey)✅Set on the message or on the element; the element’s own setting wins.
tc:loopCharacteristics✅Read only inside bpmn:multiInstanceLoopCharacteristics. Anywhere else it is ignored and the task runs once.
tc:adHoc (activeElementsCollection, outputCollection, outputElement)✅See the ad-hoc sub-process rows.
tc:conditionalFilter (variableName, variableEvents)✅Limits which variable changes a conditional event checks.
tc:properties✅Metadata, stored with the model.

These are the differences from the compatibility target that you can notice when you model or run a process. Compatibility has the full list, including details of the record stream.

  1. User tasks always use the native lifecycle. A user task without tc:userTask doesn’t create a job for a user-task worker. This is deliberate and matches the compatibility target’s direction.
  2. Root-level conditional start events deploy, but nothing can start an instance through them yet.
  3. Variables sent with a job’s BPMN error don’t yet reach the catch path in every case.
  4. Message event sub-processes read their correlation key before the start-event output mappings are applied, so the key can’t use a variable those mappings create.
  5. Message throw and end events with neither tc:taskDefinition nor tc:publishMessage deploy and run as job workers. The compatibility target rejects the deployment.
  6. Decision version tags. A version tag written on a single decision element of a DMN file isn’t read, so a business rule task bound by version tag can’t find that decision.
  • DMN conformance. TinyConductor runs the standard DMN test suite (TCK) at level 3; see DMN and FEEL for the latest result.
  • Decision tables: all hit policies, and requirement (DRD) evaluation.
  • Literal expressions: supported.
  • Business knowledge models: supported, including invocation from decisions. A business knowledge model whose logic is a decision table is not supported.
  • Decision services: single-output services work. Multi-output services, and calling a decision service from FEEL, are not supported.
  • FEEL: all helper functions of version 8.5 of the compatibility target are available, and so are fromAi and the new number overloads from 8.9. uuid() is left out on purpose: its random result would stop a process from replaying the same way every time.

Details: DMN and FEEL.