Concepts
A job is a claimable runtime record that Mobius creates when a worker action step becomes ready to execute in a run. Workers long-poll to claim jobs one at a time, heartbeat to hold the lease, and call complete to report the outcome. The action log records every state transition.
The model
Each job has:
- A step identity — the
step_nameand parentrun_idthat identify which step in which run the job represents. - Parameters — resolved inputs for the step, derived from the workflow spec and prior step outputs.
- A queue — the routing label that targets the job to workers subscribed to that queue. Steps that omit a queue use
default. - A lease fence — the
worker_idandattemptpair that prevents double-execution. Heartbeat and complete calls are rejected with 409 if the fence does not match the current lease holder. - An attempt counter — starts at
1. When a job fails andattempt < max_attempts, Mobius creates a new job for the same step withattemptincremented by one.
Claiming, heartbeating, and completing a job
# 1. Claim the next pending job (long-poll for up to 10 s)
curl -X POST "$API_BASE/v1/projects/$PROJECT/jobs/claim" \
-H "Authorization: Bearer $MOBIUS_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"worker_id": "worker-1",
"queues": ["default"],
"wait_seconds": 10
}'
# Response includes job_id, step_name, action, parameters, attempt,
# and heartbeat_interval_seconds.
# 2. Heartbeat to extend the lease (repeat at heartbeat_interval_seconds cadence)
curl -X POST "$API_BASE/v1/projects/$PROJECT/jobs/$JOB_ID/heartbeat" \
-H "Authorization: Bearer $MOBIUS_API_KEY" \
-H "Content-Type: application/json" \
-d '{"worker_id": "worker-1", "attempt": 1}'
# 3. Complete the job with base64-encoded output
curl -X POST "$API_BASE/v1/projects/$PROJECT/jobs/$JOB_ID/complete" \
-H "Authorization: Bearer $MOBIUS_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"worker_id": "worker-1",
"attempt": 1,
"status": "completed",
"result_b64": "eyJzdW1tYXJ5IjogImRvbmUifQ=="
}'claim returns 204 when the poll window closes with no available jobs. When complete is called with status: completed, the workflow engine decodes result_b64 and may pass it as input to downstream steps. If a heartbeat response contains directives.should_cancel: true, stop processing and call complete with status: failed — the run has received a cancellation request.
Lifecycle
| State | Entered when | Left when |
|---|---|---|
pending | Workflow engine creates the job for a ready step | Worker claims it |
claimed | Worker calls POST .../jobs/claim | Worker calls complete, or the lease expires |
completed | Worker calls complete with status: completed | — (terminal) |
failed | Worker calls complete with status: failed | — (terminal; if attempt < max_attempts, a new job is created for the same step) |
Where you see it
- API — the Jobs tag group exposes
claimJob,heartbeatJob,completeJob, andemitJobEvents. - Worker registry — each successful claim call registers or refreshes the calling worker. Query registered workers via
GET /v1/projects/{project}/workers.