UniteLabs
How-to

Pause and resume a run

Hold a running workflow at its next step boundary so an operator can intervene, then continue from that point.

Pause a run when an operator needs to step in part-way through: to look at a plate, check volumes, or inspect a seal. The run holds between steps. The step in progress finishes, and the next one waits until you resume.

Resume picks up exactly where the run stopped. Nothing that already ran is repeated.

An operator can request a pause at any time while a run is executing. If you already know when you write the workflow that a run must wait for a person, use HITL checkpoints instead. You declare those in the workflow, and they prompt for a specific action.

Prerequisites

  • A run in progress
  • A workflow whose activities are @step functions (see Pause points)

Pausing a run

In the app, open the run and click Pause.

The run's state shows how far the pause has gotten. It reports PAUSING while the current step finishes, then PAUSED once the run is held.

To pause through the API:

Terminal
curl -X POST "$BASE_URL/runs/$RUN_ID/status" \
  -H "Authorization: Bearer $TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{"status": "PAUSED"}'

Poll the status endpoint to see the pause requested, then applied:

Terminal
curl "$BASE_URL/runs/$RUN_ID/status" -H "Authorization: Bearer $TOKEN"
# {"status": "PAUSING", "statusSince": "..."}   <- requested, current step still running
# {"status": "PAUSED",  "statusSince": "..."}   <- held between steps

PAUSING lasts as long as the current step takes to finish: seconds for a plate move, minutes for a long incubation. On a PAUSING run, statusSince is the time the pause was requested.

Resuming

Click Resume, or:

Terminal
curl -X POST "$BASE_URL/runs/$RUN_ID/status" \
  -H "Authorization: Bearer $TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{"status": "RUNNING"}'

The run reports SCHEDULED for about a second while it picks up the request, then RUNNING. It continues with the step it was holding. The process stayed alive the whole time, so in-memory state (deck layout, tip tracking, anything your workflow computed) is exactly as you left it.

Run states

StateMeaning
PAUSINGA pause is requested. The current step is still running.
PAUSEDHeld between steps. Nothing is executing.
AWAITING_INPUTWaiting on an operator prompt the workflow author declared. Not a pause.

The platform sets PAUSING while a pause request takes effect. You can't request it yourself: a request sets PAUSED, RUNNING, or CANCELLED. A resumed run reports SCHEDULED until it's moving again, like any other run queued to start.

Pause points

A run can only hold at a boundary the workflow offers, and those boundaries are its @step functions. Steps compose. A transfer that calls an aspirate step and a dispense step can hold between the two, so how finely a run can pause depends on how the author split the workflow into steps.

A workflow with no @step functions has nowhere to hold. The platform records the pause but the run never applies it, so the run sits in PAUSING until you resume or cancel it.

Operator prompts and pauses

A run in AWAITING_INPUT is waiting on a prompt the author built into the workflow, and it needs a specific answer to continue. A pause is an operator's ad-hoc hold. The platform keeps the two apart:

  • A run that is AWAITING_INPUT cannot be paused. The request is rejected with 400 Cannot pause a run in state AWAITING_INPUT.
  • Providing the input lets the run carry on as normal. It never moves from AWAITING_INPUT to PAUSED.
  • Once it's running again, you can pause it as a new, separate hold.

What happens during a pause

The current command finishes. A pause never interrupts a command already executing on an instrument, so the aspirate in progress completes. There is no emergency stop, and pause is no substitute for one.

The deck stays as it is. A pause between an aspirate and a dispense leaves liquid in the tips. That's allowed on purpose, because sometimes it's exactly what you want (to check a liquid class for dripping, for example). Whether it's acceptable for your protocol at that moment is your call.

The run keeps its pod and process. Both stay alive for the whole hold. That's why a resume continues the run instead of replaying the workflow from the start.

Bounding a hold

By default, a hold lasts until someone resumes the run. A pause waits for a person, and the platform doesn't guess how long that takes.

Pass timeout, in seconds, to bound it instead. If the run is still held when the timeout expires, it fails:

Terminal
curl -X POST "$BASE_URL/runs/$RUN_ID/status" \
  -H "Authorization: Bearer $TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{"status": "PAUSED", "timeout": 3600}'

The run fails when the timeout expires, so use timeout only where an unattended run is worse than a failed one. If you don't plan to resume a run, cancel it instead of waiting for a timeout.

Canceling a held run

Cancel a held run like any other:

Terminal
curl -X POST "$BASE_URL/runs/$RUN_ID/status" \
  -H "Authorization: Bearer $TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{"status": "CANCELLED"}'

The run stops where it's held.

  • HITL basics: pause at a point you choose in code, prompting for a specific operator action
  • Runs: run states and what a run tracks

Last updated