Reusable WOML definitions
<props> and <prop>
Props belong only in reusable definition files, outside the top-level reusable step/provider. They are invalid in runnable workflow documents.
WOML
<props>
<prop name="price" required="true" />
<prop name="api-token" required="true" secret="true" />
</props>| Attribute | Required | Meaning |
|---|---|---|
name | Yes | Kebab-case public attribute name; exposed as lower camel case under props. |
required | No | Boolean requirement declaration. |
secret | No | Requires an exact {{secrets.NAME}} invocation value and restricts exposure. |
Reusable custom step
Definition:
WOML
<woml>
<props>
<prop name="price" required="true" />
</props>
<step name="Calculate tax" description="Apply the project tax rule.">
<script>
return { total: Number(props.price) * 1.2 };
</script>
</step>
</woml>Import and invoke:
WOML
<imports>
<module name="calculate-tax" from="./calculate-tax.woml" />
</imports>
<steps>
<calculate-tax id="tax" price="{{context.payload.price}}" retry="3" />
<step id="finish"><script>return context.steps.tax;</script></step>
</steps>The invocation behaves as one normal durable step. It requires an invocation id, accepts ordinary retry attributes, publishes a result under that ID, and has its own reusable lifecycle.
<provider kind="notification">
WOML
<woml>
<props>
<prop name="api-token" required="true" secret="true" />
<prop name="destination" required="true" />
</props>
<provider kind="notification">
<script>
const response = await services.http.request({
url: "https://messaging.example.com/messages",
method: "POST",
headers: { authorization: `Bearer ${props.apiToken}` },
json: {
destination: props.destination,
text: notification.message,
actions: notification.actions
},
idempotency: {
header: "Idempotency-Key",
value: notification.idempotencyKey
}
});
return { messageId: String(response.data.id) };
</script>
</provider>
</woml>Only kind="notification" exists in v1. Provider-trigger extensions are not yet public. Use the imported custom tag directly inside <notify>. The script transports the bounded notification object; it does not own the approval decision. Custom tags cannot accept children or generate hidden control-flow structure.