Flow Studio
Global Variables
Global variables are key-value pairs stored in ExecutionMemory.globalVariables. Any node in the execution can write a global variable and any other node can read it — regardless of graph topology. They persist for the full duration of the execution but are NOT accessible across executions.
SetGlobal and GetGlobal
// Any node can set a global variable
ctx.ExecutionMemory.SetGlobal("correlationId", Guid.NewGuid().ToString());
// Any node can read it — no need to be downstream of the writer
var correlationId = ctx.ExecutionMemory.GetGlobal<string>("correlationId");
// Overwrite is supported — last write wins
ctx.ExecutionMemory.SetGlobal("retryCount", 3);
ctx.ExecutionMemory.SetGlobal("retryCount", 4); // Now 4
// Read as untyped
var raw = ctx.ExecutionMemory.GetGlobal("retryCount"); // Returns object? (boxed int 4)
Difference from nodeOutputs
| Attribute | nodeOutputs | globalVariables |
|---|---|---|
| Key | nodeId (string) | Any string (variable name) |
| Who writes | BaseNodeExecutor (after ExecuteAsync returns) | Any executor directly via SetGlobal |
| Topology constraint | Only upstream nodes' output is meaningful | None — any node can read any global at any time |
| Typical use | Pass data downstream via workflow edges | Execution-wide shared state (flags, counters, context IDs) |
| HIL serialization | Yes — included in suspended state | Yes — included in suspended state |
Common Use Cases
// Use case 1 — Set a flag early, check it in a later branch
// (FeatureFlagNode sets the flag, downstream nodes check it)
ctx.ExecutionMemory.SetGlobal("premiumUser", isPremium);
// ... later, in a conditional node:
var isPremium = ctx.ExecutionMemory.GetGlobal<bool>("premiumUser");
// Use case 2 — Track a counter across loop iterations
var currentCount = ctx.ExecutionMemory.GetGlobal<int>("itemsProcessed");
ctx.ExecutionMemory.SetGlobal("itemsProcessed", currentCount + 1);
// Use case 3 — Propagate a correlation ID through all nodes
// (Set once at the start of the execution, used for tracing)
var corrId = ctx.ExecutionMemory.GetGlobal<string>("correlationId")
?? Guid.NewGuid().ToString();
ctx.ExecutionMemory.SetGlobal("correlationId", corrId);
ctx.Observability.Logger.LogInformation("Processing item {CorrelationId}", corrId);
Variable Naming Conventions
| Convention | Example |
|---|---|
| camelCase names | premiumUser, itemsProcessed, correlationId |
| Prefix for namespace isolation | billing.invoiceId, auth.userId |
| Avoid generic names | Use orderTotalUsd not total |
Accessing via Variable Scoping ($global prefix)
In the expression engine and variable scoping system, global variables set via SetGlobal are accessible using the $global.variableName prefix. See Guide32_VariableScoping for the full variable system.
// Expression engine references global variables with $global prefix
// Example: a condition expression in a gateway node
$global.premiumUser == true
// Another expression: multiply a total by a globally set tax rate
$global.taxRate * $output.invoice-node.subtotal
Global variables are ephemeral within the execution.
SetGlobal("key", value) is NOT the same as pinned data. When the execution ends, all global variables are gone. If you need a value in future runs, return it as pinnedData from NodeExecutionResult.Success instead.