External Workers
Any step handler not registered as a built-in is automatically dispatched to the external worker queue. Workers poll for tasks via REST, execute them in any language, and report results back.
Flow
- 1.Engine encounters unknown handler name → creates worker task
- 2.Worker polls:
POST /workers/tasks/poll { handler_name: "process_image" } - 3.Worker executes, sends heartbeats every 15–30s for long-running tasks
- 4.Worker reports:
POST /workers/tasks/{id}/complete { output: {...} } - 5.Engine resumes workflow from where it left off
Properties
Pull-basedNo message broker needed. Workers poll at their own pace.At-least-onceHeartbeat timeout (60s) + reaper (30s interval) ensures no stuck tasks.Error classificationWorkers declare retryable vs permanent failures. Retryable deletes the task for re-dispatch; permanent marks the instance failed.Concurrent workersSKIP LOCKED prevents double-claiming. Scale horizontally by running more workers.
Heartbeat
Send POST /workers/tasks/{id}/heartbeat every 15–30 seconds for tasks that run longer than 60 seconds. Tasks without a recent heartbeat are reclaimed by the reaper and returned to the queue for re-dispatch.
Task queue routing
Assign steps to named queues. Dedicated worker pools poll their specific queue — useful for isolating high-priority, GPU-intensive, or region-specific workloads from general-purpose workers.
// Step with queue assignment
{
"type": "step",
"id": "render_video",
"handler": "video_renderer",
"queue_name": "gpu-workers"
}POST /workers/tasks/poll/queue
{
"queue_name": "gpu-workers",
"handler_names": ["video_renderer", "image_upscaler"]
}Workers that poll without a queue name claim from the default queue. Tasks claimed on the wrong queue are never released to other queues — they wait until the correct worker type polls.