Portal Community

What Are Expressions?

When a user configures a node in the designer, they can type a static value (e.g. alice@example.com) or an expression (e.g. @{output:form-1.email} or ${{ $output['form-1'].email }}). The expression engine resolves these at execution time against the current execution context.

Where Expressions Appear

Expression Syntax

Flow Studio uses a directive-based syntax identified by a leading @{ sigil. The expression engine parses and evaluates the directive body:

SyntaxResolves
@{output:{nodeId}.{field}}Output field from a completed node
@{input:{field}}Input data arriving at the current node
@{var:{name}}Workflow variable
@{context:tenantId}Tenant ID from execution context
@{context:executionId}Current execution ID
@{js: ... }Arbitrary JavaScript expression (Jint engine)

Engine Selection

The system uses a single primary expression evaluator: IExpressionEvaluator (default: ExpressionEvaluator backed by Jint). Custom evaluators can be registered for specialized use cases. The config expression resolver (IConfigExpressionResolver) iterates every config field and resolves it using the registered evaluator.

Resolution Lifecycle

  1. Node reaches the EntryValidate stage in the pipeline
  2. ExpressionContextFactory.Create() builds an EvaluationContext from the execution state
  3. IConfigExpressionResolver.ResolveAsync(config, context) resolves all expression fields
  4. The resolved config is stored in elementContext.ResolvedConfig
  5. BaseNodeExecutor.LoadConfigAsync() reads from ResolvedConfig
  6. ExecuteInternalAsync receives fully resolved values via the settings object
Executors Never See Raw Expressions By the time ExecuteInternalAsync is called, all expression strings have been replaced with their computed values. Your settings class reads concrete values — it never needs to evaluate expressions itself.