Open-source, code-first workflow automation

If you can read HTML, you can build workflows, apps, and AI agents with WOML.

WOML is a code-first tool for automating tasks, powering backend apps, and building AI agents. Describe the steps in readable markup, add JavaScript for logic, and connect your tools, APIs, and services.

Build in your editor. Run on your computer or your own infrastructure.

curl -fsSL https://woml.org/install | bash

Build automated workflows, apps, and AI agents

Build automated workflows, web apps, and AI agents using clean markup and JavaScript. Execute locally or self-host on your own infrastructure with total control.

Workflows

Automate recurring tasks and multi-step processes. Start from schedules, webhooks, or events; run steps in sequence or parallel; and add conditions, retries, and human approvals in readable markup and JavaScript.

service-health.womlWOML source
<woml>  <workflow    id="service-health"    name="Service health"    description="Check public WOML endpoints and summarize their health."    version="1.0.0"  >    <config concurrency="1" timeout="2m" />     <triggers>      <interval id="poll" every="5m" on-missed="skip" />    </triggers>     <steps>      <parallel id="checks" name="Check endpoints" concurrency="3" on-error="wait-all">        <step id="website" name="Check woml.org" retry="3" retry-backoff="exponential">          <script>            const response = await services.http.request({              url: "https://woml.org",              responseType: "text",              timeout: "10s",              acceptedStatus: { minimum: 100, maximum: 599 }            }, { name: "check-woml-website" });             return { name: "website", status: response.status, healthy: response.ok };          </script>        </step>         <step id="repository" name="Check GitHub repository" retry="3" retry-backoff="exponential">          <script>            const response = await services.http.request({              url: "https://github.com/dali-benothmen/woml",              responseType: "text",              timeout: "10s",              acceptedStatus: { minimum: 100, maximum: 599 }            }, { name: "check-woml-repository" });             return { name: "repository", status: response.status, healthy: response.ok };          </script>        </step>         <step id="package" name="Check npm package" retry="3" retry-backoff="exponential">          <script>            const response = await services.http.request({              url: "https://registry.npmjs.org/woml-cli/latest",              timeout: "10s",              acceptedStatus: { minimum: 100, maximum: 599 }            }, { name: "check-woml-package" });             return { name: "package", status: response.status, healthy: response.ok };          </script>        </step>      </parallel>       <step id="report" name="Build health report">        <script>          const checks = [            context.steps.website,            context.steps.repository,            context.steps.package          ];           return {            healthy: checks.every((check) => check.healthy),            checkedAt: context.payload.triggeredAt,            checks          };        </script>      </step>    </steps>  </workflow></woml>
Execution diagram
Every 5 minutesInterval trigger
WebsiteHTTP check
GitHubHTTP check
npmHTTP check
Build health reportCombine the three results

Follow the scheduled checks through parallel execution and a combined result.

Animated example; no external calls.

Integrate any API, service, or local tool.

Call APIs, work with databases, and import local JavaScript or TypeScript modules. Add the integration your workflow needs without waiting for a built-in connector.

incident-response.womlWorkflow excerpt
<imports>  <module name="monitoring" from="./prometheus.ts" />  <module name="cluster" from="./kubernetes.ts" />  <module name="incidentAi" from="./incident-ai.ts" /></imports> <parallel id="evidence" concurrency="2">  <step id="metrics" name="Read Prometheus metrics">    <script>      return services.monitoring.readMetrics(        secrets.PROMETHEUS_URL, secrets.PROMETHEUS_TOKEN      );    </script>  </step>  <step id="workload" name="Inspect Kubernetes">    <script>      return services.cluster.inspect(        secrets.KUBERNETES_URL, secrets.KUBERNETES_TOKEN      );    </script>  </step></parallel> <step id="proposal" name="Diagnose the incident with an LLM">  <script>    return services.incidentAi.propose(      secrets.LLM_ENDPOINT, secrets.LLM_API_KEY, secrets.LLM_MODEL,      { metrics: context.steps.metrics, workload: context.steps.workload }    );  </script></step>
Connected services
< woml />incident-response.woml
  • Prometheusprometheus.ts
  • Kuberneteskubernetes.ts
  • AI modelincident-ai.ts

Build modular, reusable systems.

Break complex processes into modular workflows. Trigger them synchronously, run background jobs, or publish events across your system.

<woml>  <workflow id="modular-onboarding" name="Modular customer onboarding">    <triggers><manual id="start" /></triggers>    <steps>      <step id="customer" name="Prepare the customer">        <script>          return { id: "customer-001", email: "ada@onboarding.test" };        </script>      </step>      <step id="workspace" name="Wait for a workspace">        <script>          return services.workflows.call(            "provision-workspace", context.steps.customer,            { name: "provision-customer-workspace" }          );        </script>      </step>      <step id="welcome" name="Start the welcome workflow">        <script>          return services.workflows.start(            "send-welcome",            { ...context.steps.customer, workspaceId: context.steps.workspace.id },            { name: "start-customer-welcome" }          );        </script>      </step>      <step id="publish" name="Publish customer.created">        <script>          const event = await services.events.emit(            "customer.created",            { ...context.steps.customer, workspaceId: context.steps.workspace.id },            { name: "publish-created-customer" }          );          return {            customerId: context.steps.customer.id,            workspaceId: context.steps.workspace.id,            welcomeRunId: context.steps.welcome.runId,            subscribers: event.acceptedCount          };        </script>      </step>    </steps>  </workflow></woml>
Connected workflows
customer-onboarding.woml
  • provision-workspace.womlWait for a result
  • send-welcome.womlStart in the background
  • record-customer-event.womlSubscribe to customer.created

Track execution and handle failures.

Inspect active workflows, recent runs, queues, and approval waits from your terminal. Find failed runs and see where execution stopped without opening a separate dashboard.

customer-onboarding.woml — Terminal
Typing woml inspect.

Security, execution control, and deployment.

Keep credentials outside source, define execution policies, and run workflows on infrastructure you manage.

Security

  • Secrets stored outside workflow source.
  • Authenticated webhook inputs.
  • Redacted run inspection.

Execution control

  • Human approval steps.
  • Concurrency and rate limits.
  • Timeouts and cancellation.

Deployment

  • Run workflows from the CLI.
  • Supervise WOML with Docker or systemd.
  • Use the documented Kubernetes deployment setup.

Portability

  • Supported Linux, macOS, and Windows targets.
  • Local machines and your own servers.
  • Workflow source kept in your repository.

Automate complex work.
Keep the code. Keep control.