Portal Community

The Stage Enum

// eNodeStage.cs
Unknown = 0
Initiated = 10
Entry = 100
EntryValidate = 200
PreValidationGuardRails = 250
PreProcess = 300
Process = 400
DoWork = 410        // internal sub-stage, only during Process (e.g. agent tool calls)
PostProcess = 500
PostValidationGuardRails = 550
Exit = 600
Error = 700
HIL = 800           // suspension-related, not part of the linear sequence
Suspended = 810
Completed = 10000

The Call Chain

Execute()                          // BaseNodeExecutor.Orchestrate.cs:15
├── resets NodeResult, OutputData = {}
├── OnExecute()                    // line 39, returns the stage sequence below
│   ├── report: Initiated          // "Starting" — carries scrubbed InputData today
│   ├── OnEntry()                  // → InitializeOutputDataFromInput() runs HERE
│   ├── report: Entry
│   ├── OnEntryValidate()
│   ├── report: EntryValidate
│   ├── OnPreValidationGuardRails()
│   ├── report: PreValidationGuardRails   (a "blocked" result short-circuits here)
│   ├── OnPreProcess()
│   ├── report: PreProcess                (a non-null result short-circuits here)
│   ├── OnProcess() → OnProcessExecution() → **executor's ExecuteInternalAsync()**
│   ├── report: Process
│   ├── OnPostProcess()
│   ├── report: PostProcess
│   ├── OnPostValidationGuardRails()      (a violation REPLACES the result here)
│   ├── report: PostValidationGuardRails
│   ├── OnExit()
│   └── report: Exit
├── OnSuccess() or OnError()        // based on result.IsSuccess
└── report: Completed or Error      // carries a safe scalar summary of the result
StageWhat actually happens there
InitiatedFirst report fired. Currently the only stage whose metadata includes inputData (scrubbed). See Metadata & Events.
EntryOnEntry() runs before this report fires — this is where InitializeOutputDataFromInput seeds OutputData (see Output Data), and where InputSnapshot gets scrubbed and stored on the runtime info.
EntryValidateNode-specific input validation hook.
PreValidationGuardRailsGuard rail checks before the node's main logic. A "blocked" verdict short-circuits the whole node here — OnProcess never runs.
PreProcessLast hook before the executor's real logic. A non-null result here also short-circuits (used by some nodes for early-exit conditions).
ProcessWhere ExecuteInternalAsync — the node-specific logic every node type implements — actually runs, via OnProcess → OnProcessExecution.
PostProcessPost-execution hook, runs regardless of success/failure.
PostValidationGuardRailsGuard rail checks on the output. A violation here replaces the node's result with a GuardrailsViolation result — this used to be computed and silently discarded; it's now actually applied.
ExitFinal hook before the result is returned upward.
Completed / ErrorFired from Execute() itself (not from OnExecute) — the very last thing that happens, after OnSuccess/OnError have run.
DoWork and HIL are not part of this linear chain DoWork is emitted from inside a node's own logic during Process (e.g. an AI agent reporting "calling tool X") via ReportExecutionProgressDoWorkAsync, gated by obs.EnableNodeInternalEvents. HIL/Suspended fire when a node's result routes to the waiting/pending port, registering suspension infrastructure rather than continuing the linear sequence.

What This Means for Debugging

If you need to know exactly when OutputData first exists for a node, it's the moment Execute() resets it (before OnExecute even starts) — not at Entry. If you need to know when a node's real logic ran, that's Process, specifically inside OnProcessExecution calling the concrete executor's ExecuteInternalAsync.