Create a Custom Provider

Custom providers let a project add a notification destination without expanding WOML's built-in vendor list.

Define the provider

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({
        method: "POST",
        url: "https://messaging.example.com/messages",
        headers: { authorization: `Bearer ${props.apiToken}` },
        json: { destination: props.destination, text: notification.message },
        idempotency: { header: "Idempotency-Key", value: notification.idempotencyKey }
      });
      return { messageId: String(response.data.id) };
    </script>
  </provider>
</woml>

Import it with <module name="company-chat" from="./company-chat.woml" /> and use <company-chat ... /> inside <notify>.

Only kind="notification" is public. The provider transports notification.message and approval action URLs; Rust still owns delivery identity and the decision. Custom providers cannot create hidden control flow or accept child tags.

Import and use the provider

WOML
<imports>
  <module name="company-chat" from="./providers/company-chat.woml" />
</imports>

Use the imported tag inside notification scope:

WOML
<notify>
  <company-chat
    api-token="{{secrets.COMPANY_CHAT_TOKEN}}"
    destination="approvals"
  />
</notify>

Kebab-case prop names become lower camel case in the provider script. A prop marked secret="true" accepts only an exact secret reference.

Forward approval actions correctly

The bounded notification binding contains message content, actions, and an idempotency key. A real approval provider must transport the supplied Approve and Reject action URLs or equivalent callback values without inventing its own decision authority.

Use the notification idempotency key with a provider-supported idempotency header to avoid duplicate messages after a safe retry. Return a bounded message identity so WOML can record delivery outcome.

Understand the extension boundary

Custom notification providers make project-specific integrations such as Microsoft Teams or an internal chat service possible today. They do not add new trigger tags, arbitrary structural control flow, or child markup. Provider triggers and general structural custom tags remain future extension work.

Treat provider files as trusted project code and validate them with the importing workflow before deployment.