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.
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.
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.
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.
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.
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.