References and Templates
WOML attributes can contain exact typed references or string templates. They deliberately use a small grammar and are not JavaScript expressions. Business logic stays inside named scripts where it can be tested, explained, and returned as durable data.
Exact references
An exact reference preserves the referenced JSON type:
items="{{context.steps.load.orders}}"
test="{{context.steps.check.approved}}"The first may resolve to an array and the second must resolve to a boolean. Because the complete attribute is one reference, WOML preserves the referenced JSON type.
Exact references are appropriate for attributes such as items, test, <result value>, workflow-call payloads, and props when those contracts expect structured data.
String templates
Text around one or more references creates a string:
message="Order {{context.payload.orderId}} is ready"The value becomes text even when the referenced property is numeric or boolean. Use templates only in attributes that explicitly accept them, such as notification content. A template cannot be used where an array or strict boolean is required.
message="Order {{context.payload.orderId}} total is {{context.steps.total.amount}}"JavaScript belongs in scripts
These are not valid WOML expressions:
{{ context.payload.id }}
{{context.steps.total.value > 100}}
{{context.steps["total"]}}Whitespace, bracket access, optional chaining, operators, function calls, fallbacks, and array indexing are not supported inside declarative references.
Compute comparisons, membership, optional access, and transformations in a named script step:
<step id="checkEligibility">
<script>
const customer = context.payload.customer;
return {
approved:
customer?.active === true &&
["pro", "enterprise"].includes(customer.plan)
};
</script>
</step>
<choose id="route">
<when test="{{context.steps.checkEligibility.approved}}">
...
</when>
<otherwise>...</otherwise>
</choose>This produces a readable decision step and gives the boolean a stable durable identity.
Visibility is structural
References must point to data guaranteed to exist at the consumer's graph position. WOML rejects:
- A future sequential step.
- A concurrently running sibling.
- An internal output from a route that may not be selected.
- An iteration-local output after
<for-each>. - A missing property at runtime.
Use the stable result of <choose>, <switch>, <approval>, or <for-each> when later work needs output from structural control flow.
References validate access but do not create hidden scheduling edges. The workflow structure must already guarantee the producer runs before the consumer.
Secret references use a separate root
Attributes refer to secrets with exact syntax:
secret="{{secrets.ORDER_WEBHOOK_TOKEN}}"Scripts use JavaScript property access instead:
secrets.ORDER_WEBHOOK_TOKENDo not mix the two forms or dynamically enumerate secret names.