DAG orchestrator - Node.js

Compose containers
into a graph.

A DAG workflow engine on top of light-run. Define nodes (containers) and links (data + conditions); light-process runs the graph with fan-out, cycles, retries and schema-validated outputs.

Runtime
Node >=20
Talks to
light-run HTTP
Surface
SDK + CLI + HTTP
License
AGPL-3.0 copyleft
when ok:truescore > 0.8ingestnode:24transformpythonvalidatenode:24scorepythonreportnode:24storepython
Fig. 01 - ingest fans out; score routes the result.light-process / graph
what you get

Describe a graph of containers. Get back structured, validated results.

01 / nodes

Each step is a container.

A node is an image + entrypoint with an optional input/output JSON Schema. It runs on light-run, reads its input on stdin, and writes its result to a known file. Any language, any image.

02 / links

Wire outputs to inputs, conditionally.

A link carries one node's output into the next, optionally gated by a condition (equality, comparison, exists, regex, and/or). Merge several parents into one child. Inject static data along the way.

03 / control flow

Fan-out, cycles, and retries.

Entry nodes run in parallel batches. Back-links create loops bounded by maxIterations. A node failure stops the run with a structured error. Cancellation propagates an AbortSignal down to the container.

04 / networks & services

Run-scoped networks and sidecars.

Declare networkDefs to provision per-run Docker networks, and services (e.g. a proxy holding an API key) that run alongside the DAG. A node reaches a service by hostname without the secret ever entering it.

quick start

A few nodes, one execute, and your graph runs.

Build a workflow in the SDK (or as workflow.json), point it at a light-run instance with LIGHT_RUN_URL, and execute.

Run it from code, the CLI, or the HTTP control plane.

npm install light-process
example.ts
import { Workflow, LightRunClient } from 'light-process';
const wf = new Workflow({ name: 'pipeline' });
wf.addNode({ id: 'fetch', image: 'node:24-alpine', entrypoint: 'node fetch.js' });
wf.addNode({ id: 'parse', image: 'python:3.12-alpine', entrypoint: 'python parse.py' });
wf.addLink({ from: 'fetch', to: 'parse', when: { ok: true } });
const result = await wf.execute({ url: '...' }, { runner: new LightRunClient() });
result.success     // true if every node exited 0
result.results     // per-node output, validated against each schema
security model

Isolation inherited. Secrets stay where you put them.

Inherited sandbox
Every node runs through light-run -> light-runner: dropped capabilities, PID limits, memory/CPU budgets, isolated networks, optional gVisor. Configure them on the runner.
Secret isolation
A node receives only the env var names it declares, resolved from the server env. A service holds its API key alone; workload nodes reach it by hostname and never carry the secret.
Run-scoped networks
networkDefs are created before the DAG and torn down after, named per run. Two concurrent runs get isolated networks; bare names are never deleted.
Schema validation
Node inputs and outputs are validated against their JSON Schema. A malformed payload fails the node instead of silently propagating downstream.
Bounded loops
Back-links require maxIterations; a cycle without it is rejected at build time. Runaway graphs cannot spin forever.
Auth on the control plane
The HTTP server can require a bearer token on every route, and forwards its own token to light-run. No token = open server with a startup warning.
Does not cover -light-process holds workflow-level identity, so this is where caching/memoization belongs (not in light-run). The sandbox itself is light-runner's responsibility; light-process never weakens it.
ecosystem

Three tools. Each does one thing.

light-runner

Spawn one container, return exit code and files.

The execution primitive. Domain-agnostic, zero orchestration. The bottom of the stack.

Loading
light-run

CLI and HTTP surface around light-runner.

POST code, run it in a container, fetch artifacts. Stateless wrapper. light-process talks to it over HTTP.

Loading
light-process

DAG orchestration, retries, fan-out.

When one container is not enough. Composes runs into pipelines with conditions, concurrency, run-scoped networks, sidecars, and structured outputs.

Loading