Read the workflow as a document
Triggers, steps, branches, approvals, and runtime policy stay visible without tracing framework calls or navigating a canvas.
Workflow Orchestration Markup Language
Describe triggers, steps, branches, approvals, and runtime policy in familiar HTML-inspired markup, then write the work in real JavaScript. WOML runs it through a durable, self-hosted engine built for workflows that need to survive retries, restarts, and long-running execution.
curl -fsSL https://woml.org/install | bash npm install --global woml-cli bun add --global woml-cli pnpm add --global woml-cliWhat WOML is
Visual tools make small automations approachable, but large canvases become difficult to review and reuse. Code-first engines are powerful, but the workflow shape often disappears inside an SDK. WOML keeps structure in readable markup and business logic in real JavaScript.
The idea in one file
Each WOML tag adds a node to the canvas. As the workflow grows, connections compete for space while the source remains an ordered document you can search, diff, and review.
<woml>
<workflow id="process-order">
<triggers>
<webhook id="order" path="/orders" auth="none" />
</triggers>
<steps>
<step id="normalize">
<script>return { total: context.payload.total };</script>
</step>
<parallel id="checks">
<step id="stock">
<script>return { available: true };</script>
</step>
<step id="risk">
<script>return true;</script>
</step>
<step id="fraud">
<script>return { clear: true };</script>
</step>
</parallel>
<choose id="route">
<when test="{{context.steps.risk}}">
<step id="fulfill">
<script>return { status: "accepted" };</script>
</step>
<result value="{{context.steps.fulfill}}" />
</when>
<otherwise>
<step id="reject">
<script>return { status: "rejected" };</script>
</step>
<result value="{{context.steps.reject}}" />
</otherwise>
</choose>
<parallel id="aftercare">
<step id="notify">
<script>return { sent: true };</script>
</step>
<step id="audit">
<script>return { recorded: true };</script>
</step>
<step id="metrics">
<script>return { counted: true };</script>
</step>
</parallel>
<step id="finish">
<script>return context.steps.route;</script>
</step>
<fork id="distribution" join="all">
<branch id="emailLane">
<step id="emailReceipt">
<script>return { queued: true };</script>
</step>
<step id="trackEmail">
<script>return { tracked: true };</script>
</step>
</branch>
<branch id="warehouseLane">
<step id="reserveShipment">
<script>return { reserved: true };</script>
</step>
<step id="updateInventory">
<script>return { updated: true };</script>
</step>
</branch>
<branch id="analyticsLane">
<step id="publishMetric">
<script>return { published: true };</script>
</step>
<step id="archiveOrder">
<script>return { archived: true };</script>
</step>
</branch>
</fork>
</steps>
</workflow>
</woml>Why WOML
Triggers, steps, branches, approvals, and runtime policy stay visible without tracing framework calls or navigating a canvas.
Write normal expressions, loops, modules, Fetch, and managed service calls inside a step. WOML handles the durable structure around that code.
A .woml file is ordinary text with meaningful diffs. Teams can review workflow changes through the same pull-request process as application code.
Run WOML on your machine or infrastructure. Durable history stays in a state store you control instead of a required hosted automation platform.
Most workflow tools optimize for either visual simplicity or engineering power. WOML is designed to keep both: readable workflow structure for the whole team and real JavaScript whenever the automation needs it.
| Tool | How you build workflows | Readable by the whole team | Self-hosted | Logic without a ceiling |
|---|---|---|---|---|
| WOML | Markup + JavaScript | ✅ Clear, document-like structure | ✅ | ✅ Inline JavaScript, modules, and services |
| n8n | Visual canvas | ⚠️ Easy at first; harder as the canvas grows | ✅ | ⚠️ Code and custom nodes |
| Zapier | Visual canvas | ⚠️ Friendly for smaller automations | ❌ | ⚠️ Platform actions and code steps |
| Temporal | Code with language SDKs | ❌ Primarily readable by engineers | ✅ | ✅ Full programming languages |
| AWS Step Functions | JSON/YAML with ASL | ❌ Requires ASL and AWS knowledge | ❌ | ⚠️ Extended through AWS services and functions |
| Apache Airflow | Python DAGs | ❌ Primarily readable by Python/data teams | ✅ | ✅ Python and operators |
WOML's difference: it combines document-like readability, self-hosted ownership, and full JavaScript flexibility in the same workflow file.