ByteChef LogoByteChef
AutomationWorkflows

Data Pills & Input Modes

Reference outputs from earlier steps with data pills, and switch fields between static, dynamic, and formula input modes.

When you configure a component, every property field can hold more than a typed-in constant. It can pull in the output of the trigger or an earlier component (a data pill), or compute a value with an expression. This page explains data pills and the three ways a field can accept input: static, dynamic, and formula mode.

Data Pills

A data pill is a reference to a piece of data produced earlier in the workflow — the trigger's payload or the output of a component that runs before the current step. Instead of hard-coding a value, you drop in a pill and ByteChef resolves it to the real value at run time.

Under the hood a pill is stored as a ${...} reference, for example:

  • ${mathHelper_1} — the whole output of the step named mathHelper_1.
  • ${trigger_1.body.email} — a nested field inside an earlier step's output.

The name in the reference is the node name, not the component name. Action nodes are named after their component (mathHelper_1, slack_1); the trigger node is always named trigger_1 whichever component provides it, so a webhook trigger's body is ${trigger_1.body...}.

You never have to type this syntax by hand — the editor inserts it for you and renders it as a colored pill — but it is what gets saved in the workflow's JSON.

Use the Data Pill Panel

  1. Click into a property field that supports dynamic input. The Data Pill Panel opens on the left, listing the trigger and every component that runs before the current one.
  2. Expand a component to see the fields available in its output.
  3. Click a field to insert it as a pill at the cursor position.

You can also type $ directly in the field to open an inline data-pill picker without using the panel.

Only steps that run before the current component appear in the Data Pill Panel. A component can never reference the output of a step that runs after it.

Make sure the output schema is available

Data pills are built from each step's output schema. If a component hasn't been tested and has no predefined schema, its fields won't show up as pills yet. Open the component's Output tab and use one of:

  • Test Action — runs the action and reads the real output structure.
  • Upload Sample Output Data — provide your own representative output.
  • Reset — show the structure with placeholder sample values.

See the Output section on the Workflows page for the full walkthrough.

Input Modes

Most property fields can be filled in one of three modes. The mode determines whether the value is a fixed constant, a value assembled from data pills, or a computed expression.

Static (constant) value

This is the default. You type a literal value — a number, a piece of text, a selection from a dropdown — and that exact value is used every time the workflow runs.

Use static input when the value never changes, for example a fixed subject line or a constant limit.

Dynamic value

Toggle the Dynamic switch on a field to turn it into a dynamic input. The field becomes a rich editor where you can mix typed text with data pills, so the value is assembled from earlier steps at run time.

  1. Turn on the Dynamic switch (or simply start typing $ in a supported field).
  2. Insert one or more data pills from the panel or the inline $ picker.
  3. Combine pills with literal text as needed, e.g. Hello ${trigger_1.body.firstName}, your order shipped.

The placeholder text in these fields reminds you of the shortcuts: use $ for data pills and = for an expression.

Formula (expression) mode

When a field needs a computed value — concatenating strings, formatting a date, doing arithmetic — start the field with an equals sign (=) to enter formula mode. The leading icon changes to an f(x) marker to show the field is now an expression.

In formula mode you can:

  • Reference data pills inside the expression, e.g. =concat(${trigger_1.body.firstName}, ' ', ${trigger_1.body.lastName}).
  • Call built-in functions. As you type a function name, an autocomplete list and a signature tooltip appear to guide you.

The autocomplete offers the full set of functions as you type. The complete catalog is grouped below by category.

String

FunctionPurposeExample
concatConcatenate strings (or lists) into one value=concat('Order #', ${trigger_1.body.id})
equalsIgnoreCaseCompare two strings ignoring case=equalsIgnoreCase(${trigger_1.body.status}, 'active')
formatFormat a date/time (or apply String.format) with a pattern=format(${trigger_1.body.createdDate}, 'yyyy-MM-dd')
indexOfFirst position of a substring=indexOf(${trigger_1.body.email}, '@')
lastIndexOfLast position of a substring=lastIndexOf(${trigger_1.body.path}, '/')
lengthLength of a string=length(${trigger_1.body.title})
splitSplit a string into a list by a delimiter=split(${trigger_1.body.tags}, ',')
substringExtract part of a string=substring(${step_1.code}, 0, 4)

Date & time

FunctionPurposeExample
nowCurrent instant=now()
timestampCurrent Unix timestamp=timestamp()
atZoneConvert an instant to a zoned date/time=atZone(${trigger_1.body.createdDate}, 'America/New_York')
parseDateParse a string into a date=parseDate(${trigger_1.body.date})
parseDateTimeParse a string into a date/time=parseDateTime(${trigger_1.body.timestamp})
plusDaysplusYearsAdd time to a temporal value (plusHours, plusMinutes, plusSeconds, plusMillis, plusMicros, plusWeeks, plusMonths, plusYears)=plusDays(${trigger_1.body.startDate}, 7)
minusDaysminusYearsSubtract time from a temporal value (minusHours, minusMinutes, minusSeconds, minusMillis, minusMicros, minusWeeks, minusMonths, minusYears)=minusMonths(${trigger_1.body.dueDate}, 1)

List

FunctionPurposeExample
addAdd an element to a list=add(${trigger_1.body.tags}, 'urgent')
addAllAppend all elements of one list to another=addAll(${step_1.items}, ${step_2.items})
containsWhether a list contains an element (or a string a substring)=contains(${trigger_1.body.tags}, 'vip')
flattenFlatten a list of lists into a single list=flatten(${step_1.groups})
joinJoin a list into a string with a separator=join(', ', ${trigger_1.body.tags})
rangeBuild a list of integers between two bounds=range(1, 10)
removeRemove an element from a list=remove(${trigger_1.body.tags}, 'draft')
setReplace the element at an index=set(${trigger_1.body.items}, 0, 'first')
sizeNumber of elements in a list=size(${trigger_1.body.items})
sortSort a list in natural order=sort(${trigger_1.body.scores})
toMapBuild a map from a list of key/value pairs=toMap(${step_1.entries})

Map

FunctionPurposeExample
putAdd or replace a key in a map=put(${step_1.record}, 'status', 'done')
putAllMerge all entries of one map into another=putAll(${step_1.record}, ${step_2.extra})
removeRemove a key from a map=remove(${step_1.record}, 'tempKey')

Type conversion

FunctionPurposeExample
booleanConvert a value to a boolean=boolean(${trigger_1.body.enabled})
byteConvert a value to a byte=byte(${trigger_1.body.code})
charConvert a value to a character=char(${trigger_1.body.code})
shortConvert a value to a short=short(${trigger_1.body.count})
intConvert a value to an integer=int(${trigger_1.body.quantity})
longConvert a value to a long=long(${trigger_1.body.id})
floatConvert a value to a float=float(${trigger_1.body.price})
doubleConvert a value to a double=double(${trigger_1.body.amount})

Utility

FunctionPurposeExample
configRead a configuration property value by name=config('some.property')
uuidGenerate a random UUID (version 4)=uuid()

Operators

Beyond the functions above, expressions support the standard operators for arithmetic, comparison, and conditional logic — combine them freely with data pills and functions.

OperatorPurposeExample
+ - * / %Arithmetic (+ also concatenates strings)=${trigger_1.body.price} * 1.2
== != > >= < <=Comparison=${trigger_1.body.total} >= 100
&& || !Logical and / or / not=${trigger_1.body.active} && ${trigger_1.body.total} > 0
? :Ternary — pick one of two values on a condition=${trigger_1.body.count} > 0 ? 'has items' : 'empty'
?:Elvis — fall back to a default when the left side is null=${trigger_1.body.name} ?: 'Anonymous'

To leave formula mode, clear the field and remove the leading =. To go back to a plain constant, turn the Dynamic switch off.

Which mode should I use?

  • Static — the value is the same on every run.
  • Dynamic — the value comes from the trigger or an earlier step, optionally mixed with fixed text.
  • Formula — the value must be computed or transformed before it is used.

How is this guide?

Last updated on

On this page