Postgres-native job queue · no Redis · no BullMQ

A fault-tolerant orchestration engine for multi-step LLM agent workflows

Most agent demos show the happy path. This shows what happens when a worker crashes mid-step, two workers race for the same job, or a tool call fails — and proves the run still finishes correctly, exactly once, every time.

Try the live demo → View source
The problem

What "agent orchestration" demos usually skip

A worker process dies mid-step
Most demos just... don't test this. Here, a lock TTL expires and another worker automatically reclaims the orphaned step — no lost work, no manual intervention.
Two workers race for the same job
Without atomicity, two workers can both think they own a step and run it twice — silently corrupting state. This engine guarantees exactly one winner per claim.
A tool call fails transiently
A network blip shouldn't re-run everything before it. Only the failed step retries, with exponential backoff, up to a bounded number of attempts.
You need to know what actually happened
Every state transition — claim, success, retry, dead-letter — is written to an append-only audit log. Nothing is inferred after the fact.
How it works

From DAG submission to completion

1

You submit a DAG

POST a goal plus a list of steps, each with an optional dependsOn. Steps with no dependencies become ready immediately; everything else waits.

2

Workers claim steps atomically

Each worker polls Postgres with SELECT ... FOR UPDATE SKIP LOCKED inside a transaction — the same primitive companies like GitHub use for production job queues. Exactly one worker ever wins a given step, with zero blocking between workers.

3

Steps execute, fail, or get reclaimed

Success promotes dependent steps to ready. Failure schedules a retry with exponential backoff (capped, then dead-lettered). A worker that dies mid-step leaves an expiring lock — a reaper requeues it automatically.

4

Every transition streams live

Postgres LISTEN/NOTIFY bridges worker processes (separate OS processes) to the API server, which fans events out over WebSocket to anyone watching that run — see it below.

Correctness

Guarantees, and how they're enforced

GuaranteeMechanism
Exactly-one claim per stepFOR UPDATE SKIP LOCKED inside a transaction
No lost work on worker crash30s lock TTL + reaper requeues orphaned steps
No duplicate run creationidempotency key = runId:stepName via ON CONFLICT
Bounded retriesexponential backoff (1s→60s), dead-letter after max_attempts
Full auditabilityevery transition written to audit_log
DAG correctnessdependents promoted to ready only once all deps succeed
Usage

Run it yourself

docker compose up -d        # local Postgres
cp .env.example .env
npm install
npm run migrate
npm start                   # API + WebSocket server
npm run worker              # run 2-3x to see SKIP LOCKED in action

curl -X POST localhost:4000/runs -H 'Content-Type: application/json' -d '{
  "goal": "Research and summarize a topic",
  "steps": [
    { "name": "tool_call.fetch_data", "input": { "tool": "fetch_data" } },
    { "name": "llm_call.summarize", "input": { "prompt": "..." }, "dependsOn": ["tool_call.fetch_data"] }
  ]
}'

Full chaos test (kill a worker mid-run, watch it self-heal) and architecture notes are in the README.

Live demo

This is the real engine running right now, on this server. Edit the DAG below or submit as-is — you'll see steps go queued → executing → done in real time, including a simulated transient failure and retry.

⚙ engine status SKIP LOCKED queue · live ○ idle
Submit a run (DAG of steps)
Run ID
Submit a run to see the DAG execute live →