Secure Process Execution

Use services.process.run() to run an operator-approved local program from a step. It is useful for tests, build tools, database utilities, and infrastructure commands. Process execution is disabled until an operator grants it.

Run a supervised command

Place this step inside a workflow's <steps>:

WOML
<step id="runTests" name="Run project tests">
  <script>
    const result = await services.process.run({
      executable: "bun",
      args: ["test"],
      cwd: ".",
      timeout: "5m",
      output: { stdout: "capture", stderr: "capture", maxBytes: 65536 }
    }, { name: "project-tests" });
    return { passed: result.exitCode === 0 };
  </script>
</step>

executable is a policy alias, not an arbitrary path. Arguments are literal strings; WOML does not invoke a shell. A non-accepted exit code fails the step. Avoid returning captured output unless another step needs it, because step results become durable context.

Grant only the needed authority

For a reviewed foreground test, use a temporary alias grant:

Terminal
woml test workflow.woml --allow-process bun

For background or production operation, use an operator-owned Process Policy:

Terminal
woml run workflows/ --process-policy ./process-policy.json --background

The policy pins aliases to executables and bounds working directories, environment names, concurrency, time, and output. A workflow cannot enlarge those limits. Keep the executable and policy files outside the workflow author's control.

Failure and recovery boundary

WOML cancels or times out the contained process tree and stores bounded outcome metadata. It cannot prove an interrupted external command had no side effect. If the result is uncertain, recovery fails closed rather than replaying blindly.