Skip to Content
Evaluate Get Started

Activity

Key takeaways

An activity is a stable state where a process instance waits. Activities can have actions that run on entry, exception handlers for error recovery, timeouts that limit execution or idle time, and flags that disable database persistence. Use SetStateAsync and SetActivityWithExecutionAsync to move a process instance programmatically without going through normal transitions.

An activity is a stable state where a process instance waits. Activities are defined in a scheme. Every scheme has exactly one initial activity where new process instances start and can have zero or more activities marked as final. A process instance leaves an activity when a command executes, a timer fires, or an automatic transition fires. A process instance is always positioned at exactly one activity at a time.

During normal execution, when a process instance enters an activity, the activity can execute useful work through actions. Actions are blocks of code that run automatically upon entry, such as sending notifications, updating business data, or calling external services. Actions are attached to the activity via the Implementation property.

Activity properties

Each activity has a set of properties that define its identity, behavior, and position in the scheme.

Core properties

These are the most commonly configured properties:

Core activity properties
PropertyTypeDescription
NamestringCase-sensitive, unique identifier for the activity within the scheme
StatestringThe business state name associated with this activity; non-unique or absent
IsInitialboolOnly one activity per scheme may be initial
IsFinalboolMarks a final activity; optional in regular schemes and required in schemes used for inlining
IsForSetStateboolMarks this activity as the target when moving a process to a state by name. Only one activity per state value should have this enabled
Implementationlist of ActionDefinitionReferenceActions that execute when a process instance enters this activity

Scenario-specific properties

These properties are not always needed. Some are used in specialized scenarios such as disabling database persistence, setting timeouts, or handling errors. Others are metadata helpers:

Scenario-specific activity properties
PropertyTypeDescription
IsAutoSchemeUpdateboolAllows the process instance to be updated to a new scheme version when it reaches this activity
UserCommentstringOptional custom comment attached to the activity
Annotationslist of AnnotationKey-value metadata attached to the activity; see Annotations
DisablePersistStateboolSkips saving the current state of the process instance when entering this activity
DisablePersistTransitionHistoryboolSkips saving the transition history entry when passing through this activity
DisablePersistParametersboolSkips saving the parameter values when entering this activity
ExecutionTimeoutActivityTimeoutLimits activity execution time and cancels it when the interval expires; asynchronous actions must use the provided CancellationToken
IdleTimeoutActivityTimeoutLimits how long the process instance may sit in this activity without any transition
ExceptionsHandlerslist of ActivityExceptionsHandlerConfigures what should happen if an action throws an exception
PreExecutionImplementationlist of ActionDefinitionReferenceActions executed only during pre-execution simulation

Exception handling

When an action on an activity throws an exception, you can add exception handlers to the activity. If no handler processes the exception, it reaches the normal workflow error handling.

Each handler has two parts: which exceptions to catch and what to do when one occurs. The runtime evaluates handlers by ascending Order and uses the first matching handler. To catch a specific exception, use its full type name such as System.InvalidOperationException. To catch any exception, use *, and place that handler after more specific handlers.

Four actions are available when an exception is caught:

  • SetActivity - move the process instance to another activity. You specify which activity by name.
  • SetState - move the process instance to a business state. The runtime finds the activity that matches that state.
  • Retry - run the activity implementation again. You specify how many times to retry before giving up.
  • Ignore - suppress the exception and continue workflow execution.
<Activity Name="Review">    <Implementation>        <ActionRef Order="0" NameRef="SendNotification"/>    </Implementation>    <ExceptionsHandlers>        <ExceptionsHandler                Exceptions="System.InvalidOperationException"                Type="SetActivity"                NameForSet="Failed"                Order="1"/>        <ExceptionsHandler                Exceptions="*"                Type="Retry"                RetryCount="3"                Order="2"/>    </ExceptionsHandlers></Activity>

In this example, InvalidOperationException reaches the handler with Order="1", so the process moves to the Failed activity. Any other exception reaches the wildcard handler with Order="2" and retries the activity implementation up to three times.

Execution and idle timeouts

An activity can have two timeouts that limit how long things can take.

  • ExecutionTimeout - requests cancellation when activity execution exceeds the configured interval, then applies the configured result.
  • IdleTimeout - limits how long the process instance can sit at this activity without any transition firing. If the timer expires, the runtime takes the configured action.

ExecutionTimeout cancels execution through the CancellationToken passed to asynchronous actions and custom activity execution. It cannot stop synchronous code or asynchronous code that ignores the token; the runtime waits for that code to finish before handling the timeout.

Each timeout defines an interval and what to do when it expires. ExecutionTimeout supports SetActivity, SetState, and Retry. IdleTimeout supports SetActivity and SetState.

IdleTimeout is implemented as an interval timer and supports work calendars when its value uses calendar-aware units such as 2wd or 4 whours. ExecutionTimeout parses a regular elapsed-time interval directly and does not use work calendars.

<Activity Name="Review">    <IdleTimeout Timer="2d" Type="SetState" NameForSet="Escalated"/></Activity>

In this example, if the process stays at the Review activity for more than 2 days without advancing, the runtime moves it to the Escalated state.

Disabling persistence

By default, the runtime saves the process state, its parameters, and the transition history to the database through the persistence provider every time the process moves. For high-throughput scenarios where every millisecond counts, you can skip some of these saves on a per-activity basis:

  • DisablePersistState - skip saving the current state (activity and status) for this activity.
  • DisablePersistParameters - skip saving the parameter values for this activity.
  • DisablePersistTransitionHistory - skip saving the transition history entry when moving through this activity.

These flags do not affect reads - the runtime still loads state and parameters from the database when needed. They only disable the write that happens after each transition. Use them on high-traffic activities where you are willing to lose the latest state data in exchange for faster execution.

Pre-execution implementation

An activity can have two sets of actions: the regular Implementation that runs during normal execution and PreExecutionImplementation that runs only during pre-execution simulation. During simulation, the runtime uses PreExecutionImplementation instead of Implementation for a visited activity.

Pre-execution actions should implement simulation-specific behavior. They can still call external systems, so adding an action to PreExecutionImplementation does not make that action free of side effects.

<Activity Name="Review">    <PreExecutionImplementation>        <ActionRef Order="0" NameRef="PreFetchDocument"/>    </PreExecutionImplementation>    <Implementation>        <ActionRef Order="0" NameRef="SendNotification"/>    </Implementation></Activity>

What is State

The State property represents the business state, which is the human-readable status such as "Draft", "Under Review", "Approved". An Activity is the physical state that the runtime tracks internally. One State can be shared across multiple activities; for example, "Under Review" can be the state for both a ManagerReview activity and a DirectorReview activity.

Declaring activities in a scheme

Activities are listed in the <Activities> section of a scheme. Each <Activity> element defines one waiting point in the process. Activities are connected by transitions, which determine the paths a process instance can take from one activity to another.

The activity itself does not execute logic. It is a named waiting point that holds the process instance until an outgoing transition fires. Actions run when the process instance arrives at an activity. Each activity can be configured to perform specific work, such as sending notifications, changing data, or calling an external service. This work is defined by the activity's actions.

<Activities>    <Activity Name="Draft" IsInitial="true"/>    <Activity Name="Review"/>    <Activity Name="Approved" IsFinal="true"/>    <Activity Name="Rejected" IsFinal="true"/></Activities>

IsInitial="true" marks the activity where Workflow Engine positions new instances. IsFinal="true" is a marker: if execution stops in that activity, the runtime sets the process status to Finalized. The marker does not prohibit outgoing transitions. A regular scheme may have no final activities, but a scheme used for inlining must have at least one so the inlined fragment can connect back to its parent scheme.

Managing activities from code

You can move a process instance to a specific activity or state programmatically without going through a normal transition. These methods are useful for error recovery, manual overrides, and testing.

SetState method

SetStateAsync selects an activity whose State matches the requested name and whose IsForSetState property is true. By default, the method executes that activity's Implementation and follows its automatic transitions, bypassing normal incoming transition conditions:

var setStateParams = new SetStateParams(processId, "Approved");await runtime.SetStateAsync(setStateParams);

SetActivity method

Moves the process to a specific activity directly, without requiring its State or IsForSetState properties. You have two options:

  • SetActivityWithExecutionAsync - moves and runs the activity's actions.
  • SetActivityWithoutExecutionAsync - moves without running actions.
var scheme = processInstance.ProcessScheme;var activity = scheme.FindActivity("Review");await runtime.SetActivityWithExecutionAsync(    "user-42", null, null, activity, processInstance);

Resume process

ResumeAsync continues from the current activity, or from the activity named in ResumeParams, without executing that starting activity's Implementation again. It evaluates the activity's outgoing automatic transitions and follows one when its conditions pass. Unlike SetStateAsync, ResumeAsync does not select a target by business state or execute the selected starting activity:

var result = await runtime.ResumeAsync(processId);

Finding activities in a scheme

Every process instance holds a reference to its scheme. Use it to look up activities by name or find the starting point:

var scheme = processInstance.ProcessScheme;// Find the initial activityvar start = scheme.InitialActivity;// Find a specific activity by namevar review = scheme.FindActivity("Review");// List all activitiesList<ActivityDefinition> allActivities = scheme.Activities;

FindActivity throws an exception if no activity with that name exists.

See also

Frequently asked questions

What is an activity in Workflow Engine?

An activity is a named stable state in a scheme where a process instance waits until a command, timer, or automatic transition moves it forward. Every scheme has exactly one initial activity and may have zero or more activities marked as final.

Can multiple activities share the same state?

Yes. Multiple activities can have the same State value. For example, both a ManagerReview and a DirectorReview activity can use the "Under Review" state. The activity name identifies the physical waiting point, while the state is the business status.

Where are activities declared in a scheme?

Activities are declared in the <Activities> section of the scheme XML. Each <Activity> element defines one waiting point, and activities are connected by transitions that determine how a process instance moves from one to another.