Skip to content
All docs

Building

Working with data: saved values, expressions and data nodes

Browse and manage persistent saved values in Data, then use storage steps, expressions and data nodes to transform and reuse them in workflows.

8 min read

Most automations need a little data work between the trigger and the action: do some maths, pick between two messages, pull a value out of some text, or reshape a list. NoriaFlow lets you do all of this without code, with expressions in any field, and a handful of dedicated data nodes.

Saved values in the Data catalogue

Open Data in the dashboard to browse persistent values your workflows can reuse: lists, records, rankings and other supported storage types. Search by name or filter by type; More filters includes workflow, source and expiration. Open a value to inspect it, review linked workflows and edit supported user-managed data in the page.

Choose Add data, select its type, give it a name and fill in its value, then save. In the target workflow, use the current storage node definitions to select that saved name and read or update it. Return to Data to inspect the value after a real run. Before changing or deleting an existing value, review its known workflow usage; this list can be incomplete.

Saved values survive a workflow run until changed, removed or expired. A temporary step variable, simulation input and execution output belong to that workflow or execution and are not entries in this catalogue. Saving or restoring a graph revision does not restore stored values.

Show managed service data reveals state maintained by workflows and connections. These entries are read only; update the responsible workflow or connection instead of trying to edit them here. If the inventory reports that older data is not fully indexed, the displayed results do not prove that no other values exist. Check again refreshes the inventory; it does not promise a completion time.

This page is separate from the removed Memory/DATA wiring layer. Use ordinary FLOW paths, output references and current storage nodes; do not enable format 2 or create historical DATA links.

Example: keep a list for the next run

This example uses two workflows in your own account and needs no Discord connection.

  1. Open Data → Add data. Set Name to next-run-tasks and Type to List. Add a few task entries with the visual value editor.
  2. Open Automatic expiration. Set Expires after (seconds) to 86400 to keep this example for 24 hours, or leave it empty to keep the list until you delete it. Choose Create saved item.
  3. In workflow A, add a Manual trigger and Collect entries across runs (Collection). Set Operation to Add: append an entry, Collection key to next-run-tasks and Value to a new task. If you want each add to restart the 24-hour expiry, set Expire after (seconds, optional) to 86400 in this step.
  4. Simulate to inspect the proposed output, then publish and perform a real manual run to save the new task. A simulation does not persist the append.
  5. In workflow B, add a Manual trigger and the same Collection step. Choose List: get all entries and the exact same Collection key, next-run-tasks. Read its result output to reuse the list in later steps. Both workflows use the same saved list in your account.
  6. Return to Data, search for next-run-tasks, open it and check the entries and expiration. Editing its value here affects later real runs; saving the value keeps the existing expiration. To adjust expiry through a workflow, use the storage step's documented expiry option.

An identical name in another person's account refers to that person's separate data. It does not share your list. Only add a channel or server ID to the key when you deliberately want separate lists for those resources.

Expressions in any field

Anything you put inside {{ }} is a full expression, not just a single variable. That makes any text field a mini formula bar.

Arithmetic: combine numbers from earlier nodes:

{{ price * qty }}
{{ action_2.response.total / 100 }}

Comparisons and choices. Pick an outcome with a ternary (condition ? then : else):

{{ score > 5 ? "win" : "lose" }}
{{ member.is_booster ? "💎 VIP" : "Member" }}

Membership. Check whether a value is in a list or a string:

{{ "mod" in roles }}
{{ "@everyone" in message.content }}

Functions: call helpers right inside the braces:

{{ length(roles) }}            number of items
{{ includes(roles, "mod") }}   true / false
{{ round(price * 1.2) }}       rounded number
{{ min(a, b) }}  {{ max(a, b) }}

You can still pipe the text and date helpers you already know with | (for example {{ user.name | capitalize }}), and combine them freely with expressions. The field autocompletes available paths and underlines typos before you ship.

Values that change per environment

A workflow often needs the same shape with different values: a test channel while you build, the real one once it is live. Instead of editing every step, put those values in an environment and read them by name.

Open Settings → Environments. You get three sets (Development, Staging and Production) each holding two kinds of entry:

  • Values, read as {{env.NAME}}: hostnames, tenant ids, feature switches.
  • Resource aliases, read as {{resources.NAME}}. A stable name for an id that differs per environment, such as a channel or a role.
{{env.API_URL}}/orders          the endpoint changes, the step does not
{{resources.announce_channel}}  a test channel here, the real one in production

One environment is Active at a time, and that is what both Test runs and live runs resolve against. Switching it changes every step at once.

The panel also reads your graph: it lists every {{env.…}} and {{resources.…}} your steps use and marks the ones the current environment does not supply, with a count on each environment. A value missing in Production is therefore visible while you are still working in Development. Before a request quietly goes nowhere.

Environments are for portable, non-secret configuration. API keys, tokens and passwords belong in Connections, where they are encrypted and never stored inside the workflow itself.

The data nodes

When a single expression isn't enough, reach for a data node. You'll find these grouped under Data in the Add-a-node panel.

List: reshape a list

Point the List node at a list and choose an operation:

  • Map: turn each item into something else.
  • Filter: keep only the items that match a condition.
  • Find: return the first item that matches.
  • Sort: order items by a value.
  • Unique: drop duplicates.
  • Group by: bucket items by a key.
  • Reduce: fold the list down to one value.
  • Aggregate: sum, average, min, max, or count in one step.
  • Slice: take a range of items.
  • Join: combine items into a single string.

Per-item expressions reference the current element as item and its position as index. In Reduce, acc is the running result.

Filter   →  item.points > 100
Map      →  item.name
Aggregate (sum)  →  item.amount
Reduce   →  acc + item.amount

Compute: build one or more values

The Compute node evaluates expressions and hands the results to the next node. Use it to assemble exactly the shape you need:

  • An object: { name: user.name, level: round(xp / 100) }
  • An array: [first.id, second.id]
  • A single value: price * qty * 1.2

One Compute node can hold several Name | Formula rows. Each formula is evaluated independently and becomes its own {{name}} for later nodes. Need a total, a label, and a discount computed from the same data? That's one Compute node with three rows, not three chained nodes.

Pick a value from data. Extract fields from an object

When a trigger or an HTTP response hands you a whole object (a webhook body, an API payload), the Pick a value from data node pulls out exactly the fields you need. Point it at the source object, then add as many Name | Path rows as you want. Each path (like user.profile.avatar_url or items.0.title) becomes its own {{name}}, with an optional fallback when the field is missing. One node covers all the values you need from that object.

Nested objects and arrays without typing JSON

Fields that expect JSON now have a visual tree builder, for example Merge Objects' two objects, a manual trigger's test payload, or a structured HTTP request body. Add a row, name the key, pick its type (text, number, boolean, object, array…), and nest as deep as you need. "Edit as JSON" is always one click away if you'd rather type it, and any existing raw-JSON config keeps working unchanged.

Regex: work with text patterns

The Regex node matches text against a regular expression in three modes:

  • Extract: pull out values using capture groups (an order number, a code, a mention). One node can hold several Name | Pattern rows, each matched against the same input and published as its own {{name}}.
  • Replace: swap matching text for something else (redact, reformat, clean up).
  • Match: test whether the text matches, so you can branch on it.

Date: handle dates and durations

The Date node covers the common date tasks:

  • Now: the current date and time.
  • Add / subtract: shift a date by a duration (in 7 days, 1 hour ago).
  • Difference: measure the gap between two dates.
  • Format: render a date in a readable form.
  • Compare: check whether one date is before or after another.

Complex data without code

Between expressions and the List, Compute, Regex and Date nodes, data work (maths, conditions, reshaping lists, extracting text, and handling dates) stays point-and-click from start to finish.

Next: see how it all fits together in triggers and actions, then test and debug your workflow.

Setup checks and next steps

  • Check the draft before activating it; saving edits and publishing them are separate actions.
  • Resolve missing parameters and connection errors in the workflow that reports them.

See the extension setup guide for adding and reusing services, the node reference for parameters, and testing and debugging for execution diagnostics.

Frequently asked questions

Can I do calculations inside a NoriaFlow field?

Yes. Anything inside {{ }} is a full expression, so you can write {{ price * qty }}, compare values with {{ score > 5 ? "win" : "lose" }}, check membership with {{ "mod" in roles }}, and call functions like length(...), includes(...), round(...), min and max, while keeping the workflow fully visual.

How do I transform a list without writing code?

Use the List node. It can Map, Filter, Find, Sort, Unique, Group by, Reduce, Aggregate (sum / average / min / max / count), Slice and Join a list. Per-item expressions reference each element as item and its position as index.

How do I extract part of a string in NoriaFlow?

Use the Regex node in Extract mode with a pattern and capture groups, or write an expression with the text helpers. Regex can also Replace text or Match a value against a pattern to branch on it.

Can I handle complex data without writing code?

Yes. Expressions plus the List, Compute, Regex and Date nodes cover maths, conditions, reshaping lists, extracting text and handling dates in a fully visual workflow.

Do I have to type raw JSON to build a nested object or array?

No. Any JSON-shaped field (Merge Objects, a manual trigger's test payload, or a structured HTTP request body) has a visual tree builder: add a row, pick its type, and nest as deep as you need. "Edit as JSON" is still one click away if you prefer typing it.

How do I use different values for testing and for production?

Open Settings → Environments. Each workflow keeps three sets of values (Development, Staging and Production) that steps read as {{env.NAME}} and {{resources.NAME}}. One is Active at a time and that is what runs resolve against, so switching target changes every step at once. The panel also lists every value your steps need and flags the ones an environment is missing. Secrets stay in Connections, never in an environment.

Can one node extract several values at once?

Yes. Pick a value from data, Compute, Regex (Extract mode) and Set Data all hold multiple name/value rows in a single node. Each row becomes its own {{variable}} for later steps, so you never need a chain of single-value nodes.