Portal Community

Full Pipeline with Guard Stages

StageOrdinalWhat Happens
Entry100Load node definition
EntryValidate200Parse config, resolve expressions, populate settings
PreGuardRails250All Pre-phase guards run. Blocked → execution stops, result = GuardrailsViolation
PreProcess300HIL suspension check
Process400ExecuteInternalAsync (your code)
PostProcess500Post-execution hooks
PostGuardRails550All Post-phase guards run. Blocked → result overridden to failure
Exit600Persist result, emit SignalR event

Pre-Execution Guard Flow

// BaseNodeExecutor.PreGuardRails.cs (simplified)
public virtual async Task<bool> OnPreGuardRails(
    NodeExecutionContext ctx,
    CancellationToken ct)
{
    if (_guardExecutor == null) return true;  // no guards registered

    var guardContext = new GuardRailExecutionContext
    {
        TenantId    = (long)elementContext.TenantId,
        UserId      = (long)elementContext.UserId,
        OperationId = elementContext.ProcessElementKey,
        Input       = elementContext.InputData,
        PhaseId     = "Pre"
    };

    // Run all registered Pre-phase guards
    var result = await _guardExecutor.ExecutePreAsync(guardContext, ct);

    if (!result.IsAllowed)
    {
        // Short-circuit: set result in runtime info, skip executor
        ctx.RuntimeInfo.ResultInfo.Result = new NodeExecutionResult
        {
            IsSuccess     = false,
            ErrorMessage  = "Guardrails check failed",
            OutputPortKey = "GuardrailsViolation"
        };
        return false;
    }
    return true;
}

Pre vs Post Phase Responsibilities

PhaseGuards Run HereCan Stop Execution
Pre Rate limiting, input validation, circuit breaker, quota check Yes — Blocked result prevents executor from running
Post PII detection, content policy, output schema validation Yes — Blocked result overrides the executor's result with a failure
Error Error enrichment, fallback logic No — runs for information/logging only

Guard Ordering

Guards execute in the order they are registered in DI (first-registered-first-run for same phase). The first guard to return Blocked stops the pipeline — remaining guards are not evaluated. Ensure high-priority guards (quota, rate limit) are registered before lower-priority ones (content policy).

Fail-Open Exception Handling If a guard throws an unhandled exception, the code logs a warning and continues (return true). This fail-open design ensures that a broken custom guard does not bring down all workflow executions. Only explicit Blocked results halt execution.