Workflow runtime API and C#
Use the application-automation services for authorized process operations. The Workflow SDK contract is 7.1.0 and Engine is 5.2.0; YAML remains version 2. Configure a Definition and publish a revision before starting it. For the WebApp, see Using Workflows.
All HTTP routes are relative to WORKSPACE_API_BASE_URL. The installed Runtime
OpenAPI is authoritative; the generated reference
contains complete request, response, enum and error schemas.
Runtime commands from C#
Section titled “Runtime commands from C#”Inject IWorkflowInstanceAutomationCommandService and
IWorkflowInstanceAutomationQueryService from Moltaro.Package.NET.Workflow.Automation.
Generated projects register them automatically. Supported function contexts are
Action, Command, HttpEndpoint, Job and TriggerHandler; Validation and
BeforeSaveMutation are rejected. These services own a separate application
transaction and do not join a transaction opened on your generated EF context.
using Moltaro.Package.NET.Workflow.Automation;using Moltaro.Package.NET.Workflow.Instances;
public static async Task<string> StartReviewAsync( IWorkflowInstanceAutomationCommandService commands, string definitionId, string subjectId, string operationId, CancellationToken cancellationToken){ var result = await commands.StartAsync( new StartWorkflowInstanceRequest(definitionId, subjectId, operationId), cancellationToken); result.ThrowIfFailed(); return result.Data!.WorkflowInstanceId!;}The request waits for admission and its transaction to commit. Execution then
continues in the Worker. A successful Start receipt does not mean the instance
has completed. Keep the returned instance and command IDs. Use GetAsync(instanceId)
to inspect the instance and its ActiveNodes; GetCommandAsync(commandId) reads
the safe receipt state and error code. Command states are Ready, Processing,
Completed, Faulted and Skipped, with the first two non-terminal. Instance Running
includes waits; Faulted needs administrative recovery. Suspended retains a paused run. Completed and Canceled
are terminal instance states. Use bounded polling with backoff when waiting for
completion, and stop on a terminal state or your application’s timeout.
ListAsync(new WorkflowInstanceListRequest { ... }) returns one authorized page of
processes: the caller sees a process when it may view the Subject or administers
the Definition, and every filter (Definition, states, start range, waiting for
input, number search, RequiresMyAction), the sort allowlist and the count are
applied in the database before pagination (page size at most 100). Rows without
Subject View are technical: no Subject, node titles or choices. ListDefinitionsAsync()
lists Definitions usable as a list filter without configuration permissions.
GetExecutionViewAsync(instanceId) returns the process’s pinned graph (nodes,
outputs, authored positions and routes) together with aggregated execution facts:
visit counts per node, the unfinished visits, and how often each exact output was
traversed. It is authorized like GetAsync and uses the same technical projection
without Subject View; it never exposes admission rules, messages or command payloads.
To answer User Input, take the exact waiting visit’s ID and RowVersion and pass
new RespondWorkflowNodeRequest(choiceKey, visit.RowVersion, operationId) to
RespondAsync(instanceId, visit.Id, request). A node can be visited again, so
do not use NodeKey as the response identity. Available actions and choice keys
come from the runtime query; the command rechecks current authority.
Explicit Start and User Input share the same Responsible, inherited-permission or Security DSL evaluator and require current Subject View. Ordinary calls use the invoking user. Trusted Jobs and TriggerHandlers use the platform’s system execution mode; personal admission may be bypassed, but activation mode, precondition, choices and unfinished-instance restrictions still apply. Client actor IDs or flags cannot request that mode.
Implicit activation is exercised by changing a Subject through its application
commands. For example, creating an Entity through IEntityAutomationCommandService
publishes the real resource event. Inserting a WorkflowInstance through EF is not
activation. Delayed events use current record data and the Active revision at
admission. Settings do not backfill old records, and replaying an event cannot
restart a completed process.
Each due CRON occurrence enqueues a function job, which invokes the same runtime
facade. Correlate that function’s jobs/runs by ScheduleId; track Workflow progress
separately by its instance and command IDs. See asynchronous operations
for the function job/run contract.
Keep OperationId and payload unchanged for an exact retry. Reusing an operation identity for changed data conflicts. New starts conflict while any instance of the same Definition/Subject is Running, Faulted or Suspended, across revisions. New Active revisions do not alter an existing instance. Worker restart preserves Delay, User Input and durable event observations; strict transactional DevLog records each completed log visit once.
Runtime HTTP and administration
Section titled “Runtime HTTP and administration”The equivalent base route is /api/workspace/workflow/runtime on
WORKSPACE_API_BASE_URL:
| Method | Route | Purpose |
|---|---|---|
| GET | subjects/{definitionId}/{subjectObjectId} | Discover processes and manual start eligibility |
| POST | instances | Start with WorkflowDefinitionId, SubjectObjectId and OperationId |
| GET | instances | List authorized processes with filtering and pagination |
| GET | definitions | List Definitions available as process-list filters |
| GET | instances/{id} | Read instance and active visits |
| GET | instances/{id}/history?afterSequence=0&pageSize=50 | Read ordered history; pages are capped at 100 |
| GET | instances/{id}/execution-view | Read the pinned graph with aggregated visit and transition facts |
| POST | instances/{id}/node-instances/{visitId}/response | Answer the exact User Input wait |
| POST | instances/{id}/cancel | Administrative cancellation |
| POST | instances/{id}/retry | Recover a Faulted instance |
| POST | instances/{id}/suspend | Pause a Running or Faulted instance |
| POST | instances/{id}/resume | Restore the state remembered before suspension |
| GET | commands/{id} | Read safe command state |
The Definition Security tab assigns existing roles and groups as runtime administrators. Global administrators and Workflow Configuration Managers may edit these assignments. Only a global administrator or an administrator of this Definition may Cancel, Retry, Suspend or Resume. Runtime administration does not grant access to Subject fields or User Input. Administrators without Subject View receive a technical process projection without business data.
All four controls require Reason (trimmed, 1–2048 characters),
ExpectedInstanceRowVersion and a string OperationId (trimmed, 1–128 characters).
C# uses WorkflowInstanceAdministrationRequest; call SuspendAsync or
ResumeAsync on the command service. Preserve the exact request when retrying
after a lost response. A changed request needs a new OperationId and current version.
Suspend retains the same revision, visits, choices and timer deadlines. Time
continues: after Resume, an overdue timer proceeds and an unexpired timer waits
only its remaining time. PreSuspendStatus tells whether Resume will restore
Running or Faulted. Faulted still needs a separate Retry. New User Input responses
and Retry are unavailable while suspended; Cancel remains terminal.
Cancel and Suspend are available even while Workflow is disabled or the Subject
is unavailable. Resume and Retry require an available Subject and enabled module.
Archive/deletion faults Running processes while retaining history; an explicitly
suspended process keeps its pause and any original fault. Disabling/enabling
Workflow retains explicit suspension. Action hints (CanSuspend, CanResume,
CanCancel, CanRetry) reflect current eligibility, which each command rechecks.
Definition facades expose GetSecurityAsync and UpdateSecurityAsync. HTTP uses
GET/PUT workflow-definitions/{id}/security under the configuration base route.
Assignments use Definition RowVersion, OperationId and audit, independently of YAML.
Remove assignments before deleting a referenced role/group. Direct user assignments
are not supported.
The runtime executes Start, Delay, User Input, DevLog, If, Wait Event and End. The Workflow instances list, preview and details share the administration controls; the execution diagram retains current visits while showing suspension.
Instance numbers
Section titled “Instance numbers”Each runtime start assigns a stable WorkflowInstance.Number, such as WF-123.
The numeric suffix comes from one sequence shared by all Workflow Definitions
in the workspace. The Definition’s NumberPrefix defaults to WF-, allows an
empty string, and accepts up to 32 characters. Create and update configuration
requests expose this field; omitting it from an update preserves the current
prefix. Changes apply only to future instances.
Replay and technical Retry preserve the number. A new start gets a new suffix;
gaps are expected when a transaction rolls back. Direct EF writers must provide
a unique complete Number. Do not include the presentation-only # in storage.
Runtime query snapshots include Number, DefinitionName, RevisionNumber and
OutcomeName. Subject is a resource identity returned only when the caller can
view the record. Runtime administrators without record access receive the
technical projection. The WebApp opens an instance at
/workflow/workflow-instances/{id} without requiring configuration permissions.
Direct EF access
Section titled “Direct EF access”GeneratedWorkspaceContext exposes all Workflow tables, including
WorkflowDefinitions, WorkflowRevisions, WorkflowRevisionContents,
WorkflowOutcomes, WorkflowRevisionOutcomeReferences, WorkflowModuleSettings,
WorkflowWorkspaceRoleAssociations, WorkflowDefinitionCommandReceipts,
WorkflowInstances, WorkflowNodeInstances, WorkflowInstanceHistory,
WorkflowRuntimeCommands and WorkflowDefinitionRuntimeAdministrators.
The model also registers WorkflowObservation, WorkflowObservationSource and
WorkflowObservationReceipt; these internal execution records are accessed with
db.Set<T>(), not named generated DbSet properties. Prefer runtime queries over
reading observation internals.
The EF types are in Moltaro.Package.NET.Workflow.Schema and are already
registered by the generated workspace context.
For example, a function with an injected GeneratedWorkspaceContext db can read
unfinished process state:
using Microsoft.EntityFrameworkCore;using Moltaro.Workflow.Engine.Runtime;
var instances = await db.WorkflowInstances.AsNoTracking() .Where(row => row.WorkflowDefinitionId == definitionId && row.SubjectObjectId == subjectId && (row.Status == WorkflowInstanceStatusEnum.Running || row.Status == WorkflowInstanceStatusEnum.Faulted || row.Status == WorkflowInstanceStatusEnum.Suspended)) .ToListAsync(cancellationToken);Direct EF writes use normal Add, property assignment and SaveChangesAsync.
They do not execute a Workflow command, check Subject authorization or published
revision admission, append history, or send notifications. Use a transaction for
related state/history writes and replace RowVersion on updates to detect stale
writers. Configuration services are a separate level with their existing checks. Direct
history writers must lock the instance and advance LastHistorySequence in the
same transaction as the history insert; allocated positions must never be reused.
Prefer runtime commands for business transitions.
An instance pins a revision and stores the Subject object’s id; the Definition
owns its type. Running, Faulted and Suspended reserve the Definition/Subject pair across
revisions, so another unfinished instance is rejected by the database. Completed
and Canceled release that pair. A technically completed process has an explicit
business outcome, including failed or canceled business outcomes. Each node visit
has a distinct id, supporting repeated visits. Fork/join is not supported. Runtime times
are UTC DateTimeOffset; process values, visit results and event details use JSONB.
Wait Until runtime state
Section titled “Wait Until runtime state”Wait Until appears as one waitUntil visit with WaitKind = Event, an optional
fixed TimerDueAtUtc, and final OutputKey of satisfied or timeout. SQL checks
read current persisted state using the same actor-independent evaluator as If.
Events arriving between checking and waiting remain eligible; internal false
checks do not create additional visits or ordinary history entries.
WorkflowNodeSnapshot.EventProgress and WorkflowExecutionVisit.EventProgress
contain MatchedObservations and TotalObservations for an active event wait.
They expose no observed record identities or field values and are omitted from
technical-only projections without Subject View. Runtime services and HTTP use
the same projection. Workflow SDK 7.1.0 references Engine 5.2.0; YAML remains v2.
Move on Board results and recovery
Section titled “Move on Board results and recovery”One Move visit freezes its selection before effects and processes one card per continuation. Board movement, history/events, durable operation receipt and Workflow progress commit together under the instance fence. Business refusals are retained while remaining cards continue; technical errors retry the same pending attempt. Suspend retains progress; Cancel leaves completed moves in place.
Read GET instances/{id}/node-instances/{visitId}/board-move?page=1&pageSize=25
under the Workflow runtime route, or use SDK GetBoardMoveResultAsync.
Subject View is required. Items and VisibleCount reflect the reader’s current
SQL permissions before pagination. Progress is nullable when any source/card
dependency is hidden. Do not infer executed totals from an empty visible page.
OutputKey is the persisted Success/Failure decision, independent of visibility.
No target Entity fields are granted by Board Item View.
Boards SDK ExecuteMoveOperationAsync accepts a stable operation id and exact
Board pass. Same actor/payload replays a committed result after current View;
changed payload conflicts. It does not grant System execution to ordinary clients.