Back to Blog Series
Part 3: Data Flow DSLStep 3 of 15TemplatingDSLData Flow

Building Fluxo's Templating Language for Workflow Nodes

How I implemented Fluxo's expression engine, built-in functions, syntax validation, and safe value interpolation across all node configs.

Why this part is here in the storyline

Learn how data moves between nodes through Fluxo's expression and template engine.

Artem Moshnin, Lead Software EngineerFebruary 8, 202612 min
Series Progress3/15

Workflows only become useful when nodes can share data. A trigger produces a payload. An AI node produces text. A transform node reshapes it. An HTTP node sends it. If every node required custom glue code to connect outputs to inputs, Fluxo would be a developer tool, not a product.

So Fluxo includes a templating and expression language that works across node configurations. It lets users reference upstream outputs inside fields using double-brace expressions, and it keeps those references safe and debuggable.

Section 1

Expression model

#expression-model

Fluxo supports double-brace expressions in node fields. For example, a Slack message body can include an expression that pulls the title produced by an upstream node. A webhook can include an expression that reads a field from the trigger payload. The syntax stays consistent across the product.

Under the hood, I implemented this using expr-eval with restricted operators and a curated function library. This is a deliberate middle ground: expressive enough for real automation, but constrained enough to remain safe and predictable.

Important behavior choices:

  • expression parsing is deterministic
  • unresolved simple paths degrade gracefully
  • full-template rendering and single-expression value mode are both supported

That single-expression mode is critical because an expression that resolves to an array should stay an array, not become a string.

Section 2

Built-in function runtime

#built-in-function-runtime

Users need common transformations without leaving the product. Fluxo includes a curated standard library:

  • String (upper, lower, replace, concat, and more)
  • Array (len, first, last, contains, and more)
  • Math (round, min, max, and more)
  • Date (now, formatDate, formatTime)
  • Utility (default, isEmpty, json)

These functions are available both for runtime execution and documentation/reference tabs in product docs.

Section 3

Validation strategy

#validation-strategy

Templating only works if errors are understandable. Fluxo splits validation into two layers:

  • syntax validation (balanced braces, parseable expression)
  • reference validation (known variables and allowed roots)

Fluxo also detects unknown functions and invalid references before execution where possible. The goal is to shift failures left: a user should discover broken expressions while configuring a node, not during a production run.

Section 4

Why this mattered for the rest of Fluxo

#why-this-mattered-for-the-rest-of-fluxo

This template engine powers almost every node family:

  • AI prompts
  • HTTP request bodies and params
  • outbound communication payloads
  • transform/filter/conditional logic
  • human review content and context resolution

Because interpolation and validation are centralized, Fluxo gets consistent behavior and fewer category-specific bugs. It also enables better UX: autocomplete, reference browsing, and consistent validation messages are possible because there is one engine.

Section 5

Edge behavior I intentionally designed

#edge-behavior-i-intentionally-designed

Real automation produces real edge cases. Some behaviors I intentionally designed:

  • strict comparison operators normalize to parser-supported forms
  • legacy json-expression form stays supported for backward compatibility
  • string literal stripping avoids false positives in reference scanning

The goal was a pragmatic DSL that is expressive enough for production automation while still safe and debuggable for non-compiler users.