Flow Studio
NodeExecutionContext
NodeExecutionContext is the object passed to ExecuteInternalAsync. It is a thin wrapper that aggregates all the execution state the node executor needs: the element context, the orchestration processor, and runtime perf metrics.
NodeExecutionContext Shape
// BizFirst.Ai.ProcessEngine.Domain/Execution/NodeExecutionContext.cs
public class NodeExecutionContext
{
// The per-element context — node definition, config, tenant ID
public ProcessElementExecutionContext? ElementExecutionContext { get; set; }
// Allows calling back into the engine (run sub-flows, signal events)
public IOrchestrationProcessor? Processor { get; set; }
// DataSections — shortcut to the operating context data
public DataSections MyDataSections { get; set; }
// Runtime metadata — timing, stage tracking, result pre-emption
public NodeExecutionContextRuntimeInfo RuntimeInfo { get; set; }
}
ProcessElementExecutionContext — Key Fields
Access this via ctx.ElementExecutionContext:
// The most commonly used fields on ElementExecutionContext
ctx.ElementExecutionContext.TenantId // int — tenant owning this execution
ctx.ElementExecutionContext.ExecutionId // string — the workflow execution ID
ctx.ElementExecutionContext.NodeId // string — this node's ID on the canvas
ctx.ElementExecutionContext.Definition // ProcessElementDefinition — node definition
ctx.ElementExecutionContext.ResolvedConfig // merged + expression-resolved config JSON
ctx.ElementExecutionContext.ExecutionMemory // access to upstream node outputs
Common Context Access Patterns
protected override async Task<NodeExecutionResult> ExecuteInternalAsync(
NodeExecutionContext ctx, CancellationToken ct)
{
var elCtx = ctx.ElementExecutionContext!;
// Tenant and execution identity
var tenantId = elCtx.TenantId;
var executionId = elCtx.ExecutionId;
// Already-populated settings (cast to your settings type)
var s = (MyNodeSettings)settings!;
// Access the orchestration processor (e.g. to trigger sub-flows)
var processor = ctx.Processor;
// Runtime perf — start time, elapsed, etc.
var startedAt = ctx.RuntimeInfo.PerfMetrix.startedAt;
// Data sections — variables, global data, etc.
var variables = ctx.MyDataSections;
// ... your logic ...
}
eNodeStage Enum
The runtime tracks which pipeline stage is currently executing via ctx.RuntimeInfo.StatusInfo.Stage. This is informational — you do not need to set it:
| Stage | Ordinal | When |
|---|---|---|
| Initiated | 10 | Context created |
| Entry | 100 | Loading node definition |
| EntryValidate | 200 | Config parsed and validated |
| PreGuardRails | 250 | Rate limit, quota checks |
| PreProcess | 300 | HIL check, suspension test |
| Process | 400 | Your ExecuteInternalAsync |
| PostProcess | 500 | Post-execution hooks |
| PostGuardRails | 550 | Content policy |
| Exit | 600 | Result persistence + SignalR |
| Error | 700 | Error handler |
| Completed | 10000 | Pipeline finished |
Short-Circuiting the Pipeline
If a PreProcess stage (e.g. the HIL suspension check) needs to return a result without running your executor, it sets
ctx.RuntimeInfo.ResultInfo.Result to a non-null value. The Process stage then skips calling ExecuteInternalAsync and uses this result directly. This is how HIL nodes return a "waiting" status.