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.
Start
Intermediate catch
Intermediate throw
Boundary, interrupting
Boundary, non-interrupting
End
thin circle
double circle
double circle
double circle
double dashed circle
thick 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.
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
99
4
21
0
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.
Supported with boundary events and event sub-processes inside it.
Call 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-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-process
✅
tc:adHocactiveElementsCollection 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.
Worker-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.
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 task (native user task, tc:userTask)
✅
Native user-task lifecycle, with a user-task API.
User 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 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 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 (instantiate="true")
❌
Rejected at deployment. Use a message start event to start a process from a message.
Script 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 task, job-worker form (tc:taskDefinition)
✅
Creates a job like a service task. The JavaScript script worker runs it; see Script tasks.
Business 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 task, job worker (tc:taskDefinition)
Takes the first flow whose condition is true, otherwise the default flow. With no match and no default, it raises an incident.
Parallel (AND), fork and join
✅
Splits into parallel paths and waits for all of them where they join.
Inclusive (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 (OR), join
✅
Continues once every incoming flow has been taken, or once no active path can still reach one that hasn’t.
Event-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.
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.
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.
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.
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.
Timer start. Time date, duration and cycle (ISO repeat and cron) are
supported. An invalid fixed date, duration or cycle is rejected at
deployment.
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.
Signal start. Two start events of one process can’t use the same
signal name; the deployment is rejected.
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.
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.
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.
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.
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.
Terminate end event. Ends its own scope (the process, an embedded
sub-process or an event sub-process) and everything still active in it.
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, sequential
✅
Runs the instances one after another.
Loop (standard loop)
❌
Rejected at deployment, and the console’s Modeler flags it. Use multi-instance instead.
Compensation (activity is a handler)
✅
The handler must have no incoming or outgoing sequence flows and no boundary events.
Modelling only: accepted and ignored. Use process variables for data.
Data stores, data store references
✅
Modelling only: accepted and ignored.
Text annotations, groups, associations
✅
Modelling only. An association also links a compensation boundary event to its handler.
Input 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.
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).
Extension
Status
What 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.
Copies all variables from the child back to the parent, or from the parent into the child.
tc:calledElement / tc:calledDecisionbindingType
✅
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:formDefinitionformKey, 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:assignmentDefinitionassignee
✅
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).
The users and groups who may claim the task. Users are named like the assignee.
tc:taskScheduledueDate / 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.
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.
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.
Root-level conditional start events deploy, but nothing can start an
instance through them yet.
Variables sent with a job’s BPMN error don’t yet reach the catch path
in every case.
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.
Message throw and end events with neither tc:taskDefinition nor
tc:publishMessage deploy and run as job workers. The compatibility
target rejects the deployment.
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.