Conditional Choices

Use <choose> for ordered strict boolean decisions.

Result-producing choice

WOML
<choose id="route">
  <when test="{{context.steps.check.approved}}">
    <step id="accept"><script>return { status: "accepted" };</script></step>
    <result value="{{context.steps.accept}}" />
  </when>
  <otherwise>
    <step id="reject"><script>return { status: "rejected" };</script></step>
    <result value="{{context.steps.reject}}" />
  </otherwise>
</choose>

The first true <when> wins. Tests are exact references that must resolve to booleans; WOML does not coerce truthy values. A final <otherwise> is required.

With an id, every arm ends in <result> and the selected value becomes context.steps.route. Without an id, omit results and use the choice only to control execution.

Compute complex conditions in a preceding named script step.

Build a decision explicitly

First calculate the decision:

WOML
<step id="checkOrder" name="Check order">
  <script>
    return {
      approved:
        context.payload.inStock === true &&
        context.payload.riskScore < 70
    };
  </script>
</step>

Then route on the returned boolean:

WOML
<choose id="orderRoute" name="Route order">
  <when test="{{context.steps.checkOrder.approved}}">
    <step id="accepted">
      <script>return { status: "accepted" };</script>
    </step>
    <result value="{{context.steps.accepted}}" />
  </when>
  <otherwise>
    <step id="review">
      <script>return { status: "review" };</script>
    </step>
    <result value="{{context.steps.review}}" />
  </otherwise>
</choose>

<step id="respond">
  <script>
    return context.steps.orderRoute;
  </script>
</step>

Only the selected arm executes. Its result is published under context.steps.orderRoute, so respond does not need to know whether accepted or review ran.

Strict boolean behavior

test must be one exact reference whose runtime value is true or false. WOML does not treat non-empty strings, non-zero numbers, objects, or arrays as truthy. This prevents configuration-looking data from silently changing control flow.

Result-producing or control-only

Give <choose> an ID when downstream work needs one merged output. Every arm must then end with <result>. Omit the ID and results when the choice only controls whether route-specific work happens.

Always include one final <otherwise>. It documents and executes the fallback instead of leaving unmatched data ambiguous.