# Workflow Runtime Workflow Runtime is the main API access point for Workflow Engine and a facade over the structures that execute and manage processes. Application code configures a `WorkflowRuntime` with a workflow builder and [persistence provider](https://docs.workflowengine.io/get-started/concepts/persistence/), then uses it to create and control [process instances](https://docs.workflowengine.io/get-started/concepts/process-instance/). ## What Workflow Runtime coordinates Workflow Runtime connects the public process API to the engine components responsible for scheme management, execution, persistence, and background services. Its main responsibilities are: - **Scheme management** - the workflow builder generates, parses, and caches [schemes](https://docs.workflowengine.io/get-started/concepts/scheme/) used by process instances. - **Process operations** - the runtime API creates and deletes process instances, returns available [commands](https://docs.workflowengine.io/get-started/concepts/command/), executes commands, and reads or changes process state. - **Process execution** - internal execution components evaluate transition conditions, run [actions](https://docs.workflowengine.io/get-started/concepts/action/), and move a process to the next activity. - **Persistence** - the configured persistence provider reads and writes process status, parameters, transition history, and timers. - **Background services** - the configured service runner and timer manager restore interrupted processes and execute due [timers](https://docs.workflowengine.io/get-started/concepts/timer/). For example, when application code executes a command, Workflow Runtime obtains the process instance and its scheme, delegates the transition execution, and uses the persistence provider to save the result. ## Runtime lifecycle Configure Workflow Runtime with `WithBuilder(...)` and `WithPersistenceProvider(...)` before calling `StartAsync()`. Action providers, rule providers, plugins, calendars, logging, and other extensions are optional configuration points. The following code illustrates the full Workflow Runtime lifecycle for direct integration: it accepts database-specific components, starts a single-server runtime, runs application work, and guarantees shutdown. Most ASP.NET Core applications do not need to manage this lifecycle explicitly. The [Workflow Engine Web API integration](https://docs.workflowengine.io/get-started/install-workflow-engine/) registers Workflow Runtime in the standard .NET dependency injection container and uses the host lifecycle to start and stop it. ```csharp filename="RuntimeLifecycle.cs" using System; using System.Threading.Tasks; using OptimaJet.Workflow.Core.Builder; using OptimaJet.Workflow.Core.Persistence; using OptimaJet.Workflow.Core.Runtime; public static class RuntimeLifecycle { public static async Task RunAsync( IWorkflowBuilder workflowBuilder, IPersistenceProvider persistenceProvider, Func runApplicationAsync) { var runtime = new WorkflowRuntime() .WithBuilder(workflowBuilder) .WithPersistenceProvider(persistenceProvider) .AsSingleServer(); await runtime.StartAsync(); try { await runApplicationAsync(runtime); } finally { await runtime.ShutdownAsync(); } } } ``` `AsSingleServer()` selects the single-server service runner and timer manager. `AsMultiServer()` selects their multi-server implementations. After configuration, `StartAsync()` starts runtime services and compiles global code actions. `ShutdownAsync()` switches off the runtime API, waits for active API calls, and stops timers. Table: Common runtime configuration methods | Method | Role | |-----------------------------------------|-------------------------------------------------------------------------| | `WithBuilder(...)` | Connects the workflow builder and adds the default scheme build steps. | | `WithPersistenceProvider(...)` | Connects and initializes the process persistence provider. | | `WithActionProvider(...)` | Registers an action provider. | | `WithActionProvider(provider, schemes)` | Registers an action provider for specified schemes. | | `WithRuleProvider(...)` | Registers a rule provider for actor checks. | | `WithRuleProvider(provider, schemes)` | Registers a rule provider for specified schemes. | | `WithCalendars(...)` | Registers work calendars by name. | | `SetDefaultCalendar(name)` | Selects one registered work calendar as the default. | | `WithLocalizationProvider(...)` | Registers an external localization provider. | | `WithProcessLogger(...)` | Registers a process log provider. | | `WithExternalParametersProvider(...)` | Registers an external parameter provider. | | `WithPlugin(...)` | Registers a plugin with Workflow Runtime. | | `WithPlugins(schemes, plugins)` | Registers several plugins for specified schemes. | | `AsSingleServer()` | Selects the single-server service runner and timer manager. | | `AsMultiServer()` | Selects the multi-server service runner and timer manager. | | `RegisterAssemblyForCodeActions(...)` | Registers an assembly for code actions and, by default, Designer types. | | `CodeActionsDebugOn()` | Enables code action debug mode. | | `StartAsync()` | Starts runtime services and compiles global code actions. | | `ShutdownAsync()` | Stops the API and timers after active API calls finish. | ## Use the process API Workflow Runtime provides the application-facing operations for a process instance. A common sequence creates the instance, obtains commands available to an identity, and executes one of those commands: ```csharp filename="ProcessOperations.cs" using System; using System.Linq; using System.Threading.Tasks; using OptimaJet.Workflow.Core.Model; using OptimaJet.Workflow.Core.Runtime; public static class ProcessOperations { public static async Task CreateAndExecuteAsync( WorkflowRuntime runtime, string schemeCode, string identityId) { Guid processId = Guid.NewGuid(); await runtime.CreateInstanceAsync(schemeCode, processId); var commands = await runtime.GetAvailableCommandsAsync(processId, identityId); WorkflowCommand command = commands.FirstOrDefault(); if (command is not null) { await runtime.ExecuteCommandAsync( command, identityId, identityId); } return processId; } } ``` The facade groups related operations on the same `WorkflowRuntime` instance instead of exposing its internal executor, scheme updater, or subprocess manager. Table: Common process methods | Method | Role | |----------------------------------------------------|-----------------------------------------------------------------------------| | `CreateInstanceAsync(schemeCode, processId)` | Creates and initializes a process instance. | | `GetAvailableCommandsAsync(processId, identityId)` | Returns commands available to an identity. | | `ExecuteCommandAsync(command, identityId, ...)` | Executes the selected command. | | `GetProcessStatusAsync(processId)` | Returns the persisted process status. | | `GetCurrentStateNameAsync(processId)` | Returns the current state name. | | `GetCurrentActivityNameAsync(processId)` | Returns the current activity name. | | `SetStateAsync(SetStateParams)` | Sets an allowed target state using the supplied options. | | `SetPersistentProcessParameterAsync(...)` | Stores one persistent process parameter. | | `ResumeAsync(...)` | Continues a process without executing the activity used as the start point. | | `DeleteInstanceAsync(processId)` | Deletes the process instance and its child subprocesses. | For direct state changes and pre-execution, use the dedicated guides. They explain the options and execution rules that do not belong in this introductory concept. ## Observe runtime events Workflow Runtime raises events when process execution or the runtime lifecycle changes. The synchronous events below have asynchronous counterparts with the `Async` suffix. ```csharp filename="RuntimeEvents.cs" using System; using OptimaJet.Workflow.Core.Runtime; public static class RuntimeEvents { public static void Subscribe(WorkflowRuntime runtime) { runtime.OnProcessActivityChanged += (_, args) => { Console.WriteLine( $"{args.ProcessId}: {args.CurrentActivityName}"); }; runtime.OnWorkflowError += (_, args) => { Console.Error.WriteLine( $"{args.ProcessInstance.ProcessId}: {args.Exception.Message}"); }; } } ``` Table: Common runtime events | Event | Raised when | |----------------------------|------------------------------------------------| | `OnWorkflowError` | A workflow execution error occurs. | | `OnProcessActivityChanged` | The current activity of a process changes. | | `OnProcessStatusChanged` | The persisted process status changes. | | `OnSchemaWasChanged` | The scheme of a process changes. | | `OnRuntimeStart` | Workflow Runtime has started. | | `OnRuntimeShutdown` | Workflow Runtime begins shutting down its API. | For all configuration options and API groups, use the WorkflowRuntime guide and Runtime Settings reference. These pages keep detailed API material out of the introductory concepts section. ## Workflow Runtime and scheme A scheme is a process definition that describes activities, transitions, commands, and other workflow elements. Workflow Runtime uses the parsed scheme when it creates a process instance or executes that process. The scheme provides the definition; Workflow Runtime provides the API and coordinates the components that execute it. ## See also - WorkflowRuntime: Configure WorkflowRuntime and use its process APIs. - Runtime Settings: Review the available Workflow Runtime settings. - Pre-execution: Use the advanced API to simulate automatic process execution. ## Frequently asked questions **Is Workflow Runtime a separate service?** No. `WorkflowRuntime` is a class in Workflow Engine Core. Application code creates and configures an instance, then calls its public API directly. **What must be configured before Workflow Runtime starts?** Workflow Runtime requires a workflow builder and a persistence provider before `StartAsync()`. Other providers and plugins are added only when the process definitions or integration require them. **What does starting Workflow Runtime do?** `StartAsync()` starts the configured runtime services and compiles global code actions. Call `ShutdownAsync()` during application shutdown so the runtime can stop accepting API calls, wait for active calls, and stop timers. **Which Workflow Runtime server mode should I use?** Use `AsSingleServer()` for a single-server environment and `AsMultiServer()` for a multi-server environment. Each method configures the matching service runner and timer manager. **How do I react to a workflow execution error?** Subscribe to `OnWorkflowError`. If the handler needs to perform asynchronous work, subscribe to `OnWorkflowErrorAsync` instead. The example in [Observe runtime events](#observe-runtime-events) shows the synchronous event.