Workflow core is the engine layer. It defines activities, execution contexts, scheduling primitives, inputs and outputs, variables, bookmarks, serialization, execution pipelines, flowchart behavior, and the core runner.
Start in [src/modules/Elsa.Workflows.Core](../../src/modules/Elsa.Workflows.Core).
## Feature Wiring
[WorkflowsFeature](../../src/modules/Elsa.Workflows.Core/Features/WorkflowsFeature.cs) registers the core services:
-`IActivityInvoker`
-`IWorkflowRunner`
-`IActivityTestRunner`
-`IActivityVisitor`
-`IWorkflowGraphBuilder`
-`IWorkflowStateExtractor`
-`IActivitySchedulerFactory`
- workflow and activity execution pipelines
- activity registry, descriptor, factory, and lookup services
- storage drivers
- serializers
- incident strategies
- UI hint handlers
- identity and hashing services
The feature also configures default workflow and activity pipelines. The umbrella [ElsaFeature](../../src/modules/Elsa/Features/ElsaFeature.cs) calls `WithDefaultWorkflowExecutionPipeline()` and `WithDefaultActivityExecutionPipeline()`.
## Activities
Core activity abstractions live in [Abstractions](../../src/modules/Elsa.Workflows.Core/Abstractions):
-`Activity`
-`Activity<T>`
-`CodeActivity`
-`WorkflowBase`
-`Behavior`
-`Trigger`
Built-in activities live in [Activities](../../src/modules/Elsa.Workflows.Core/Activities). Important families:
- State machine: [Activities/StateMachine](../../src/modules/Elsa.Workflows.Core/Activities/StateMachine/Activities). Named states with trigger-driven transitions. See [Activities And Authoring](activities-and-authoring.md) for the execution model.
Activities are described by `IActivityDescriber` and registered in `IActivityRegistry`. Workflow management adds activities to the available designer/API surface.
## Execution Contexts And State
Core execution state lives under [State](../../src/modules/Elsa.Workflows.Core/State) and [Models](../../src/modules/Elsa.Workflows.Core/Models). Important concepts:
-`WorkflowExecutionState`: high-level status and state model.
-`ActivityIncident`: fault or incident details.
-`WorkflowInput`: input passed into a workflow run.
-`ActivityOutputs` and `ActivityOutputRecord`: activity output capture.
Execution context extension tests live under [test/unit/Elsa.Workflows.Core.UnitTests/Extensions/ActivityExecutionContextExtensions](../../test/unit/Elsa.Workflows.Core.UnitTests/Extensions/ActivityExecutionContextExtensions).
## Inputs, Outputs, And Expressions
Inputs and outputs are modeled through:
-`Input<T>` and `Input`
-`Output<T>` and `Output`
-`InputDefinition`
-`OutputDefinition`
-`InputDescriptor`
-`OutputDescriptor`
-`Argument` and `ArgumentDefinition`
Expression handling bridges core workflows with language providers through [Expressions](../../src/modules/Elsa.Workflows.Core/Expressions) and the separate expression modules. `DefaultActivityInputEvaluator` evaluates inputs before activity execution.
## Scheduling Inside A Workflow
Core scheduling is about which activity work item runs next. Key services:
The runtime persists and indexes bookmarks/triggers. Core activities create bookmarks and signals; runtime services decide how they are stored and resumed.
Pipeline extension methods live under [Extensions](../../src/modules/Elsa.Workflows.Core/Extensions) and middleware under [Middleware](../../src/modules/Elsa.Workflows.Core/Middleware). Pipelines are configured by `WorkflowsFeature`.
## Commit Strategies
Commit strategies determine persistence boundaries. Related files:
Workflow JSON type resolution uses the shared `ISerializationTypeRegistry` from `Elsa.Common.Serialization`, not expression type aliases. Register workflow-serializable payload types through `SerializationTypeOptions`; keep `ExpressionOptions` for expression/type metadata only.
New workflow JSON writes preferred aliases when a type is registered. Compatibility reads also accept explicitly registered legacy names, including selected CLR names from older persisted workflow JSON. Unknown CLR names are rejected rather than loaded dynamically. Polymorphic object reads also reject abstract, interface, open generic, and unsupported collection targets unless the resolver can map a known collection interface to a concrete collection type.
Public API payloads that expose workflow JSON type identifiers should emit values from `ISerializationTypeRegistry`. For example, incident strategy descriptors return the alias that workflow JSON accepts, while registered legacy CLR names remain readable during the compatibility window.
Change workflow core only when you are changing engine semantics, activity contracts, execution state, serialization, core activity behavior, or flowchart behavior. If the change is about persisted definitions, API DTOs, background dispatch, or a module-specific transport, start in management, API, runtime, or the extension module instead.