Pause and resume a run
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.
Prerequisites
- A run in progress
- A workflow whose activities are
@stepfunctions (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:
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:
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:
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
| State | Meaning |
|---|---|
PAUSING | A pause is requested. The current step is still running. |
PAUSED | Held between steps. Nothing is executing. |
AWAITING_INPUT | Waiting 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.
@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_INPUTcannot be paused. The request is rejected with400 Cannot pause a run in state AWAITING_INPUT. - Providing the input lets the run carry on as normal. It never moves from
AWAITING_INPUTtoPAUSED. - 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:
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:
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.
Related
- 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