Run a workflow
Two paths. orca run is the simple one — fire-and-forget a single-group, standalone submission. For multi-group or batched submissions, drop down to orca submission submit.
orca run
orca run <workflow> --run-mode <PURE_SIM|DEVICE_SIM|LIVE> [options]
--run-mode is required on every submission. There is no deployment-level fallback. The 12-row v3.4 resolver combines this with each device's topology sim_override at dispatch time.
| Run mode | What it means |
|---|---|
PURE_SIM | Software simulation. No driver calls, no Chatterbox. Fast. |
DEVICE_SIM | Real driver wrapping a Chatterbox sim backend. Driver code path runs, no hardware. |
LIVE | Real driver wrapping the real hardware backend. |
Quick patterns
# Fire-and-forget
orca run smc_assay --run-mode PURE_SIM
# Block until terminal, give up after 2 minutes
orca run smc_assay --run-mode PURE_SIM --wait --timeout 120
# Pass workflow variables
orca run smc_assay --run-mode DEVICE_SIM --vars plate_count=2,reagent_batch=L7
# LIVE submission against devices with sim_override
orca run smc_assay --run-mode LIVE --confirm
Flags
| Flag | Required? | Effect |
|---|---|---|
--run-mode | yes | PURE_SIM / DEVICE_SIM / LIVE. No default. |
--wait | no | Block until the execution is terminal (completed / failed / aborted). |
--timeout <s> | with --wait | Seconds before the CLI gives up (default 300). The execution KEEPS RUNNING — timeout only stops the CLI from waiting. Exit code 50. |
--poll <s> | with --wait | Polling interval (default 0.5s). |
--vars KEY=VAL,KEY2=VAL2 | no | Per-submission variable overrides. Best-effort typing: true/false → bool, integer → int, else float, else string. |
--profile <path> | no | Path to a JSON deployment profile loaded into the execution before any thread ticks. Local-only; with --backend cloud exits with EXIT_USAGE. |
--confirm | LIVE + sim_override | Acknowledges the LIVE_SUBMISSION_WITH_SIM_OVERRIDES_UNACKNOWLEDGED gate. Without it the runtime refuses. |
Output
$ orca run smc_assay --run-mode PURE_SIM
submitted execution 7a3f1c0e (smc_assay)
With --wait the CLI polls and then emits a key-value summary on terminal:
execution 7a3f1c0e
workflow: smc_assay
status: completed
error:
--json form returns the full ExecutionDetailDTO — same shape as GET /api/executions/<id>.
Pitfalls
--wait --timeout 60is NOT a kill switch. It abandons the CLI's poll loop but the execution keeps running. To actually stop an execution useexecution stop.--run-mode LIVEagainst any device with topologysim_overrideis refused unless--confirmis passed. The refusal includes the override list so you know exactly which devices the LIVE submission would skip.--profileis local-only. Passing it with--backend cloudexits non-zero with a clean redirect — the cloud REST surface does not accept profile paths.--varsis per-submission. It overrides defaults from the workflow'sVariableDefinition. To set defaults for every future submission usevar set-global.
orca submission submit — multi-group + batched
run is single-group, STANDALONE batch-mode. For everything richer, use submission submit:
# Multi-group: N samples per submission, each in its own group
orca submission submit smc_assay --run-mode PURE_SIM \
--groups-file groups.json
# Batched: join an in-flight ACCEPTING execution of the same workflow
orca submission submit smc_assay --run-mode PURE_SIM \
--groups-file groups.json --batch-mode JOIN_EXISTING
The workflow name is a positional argument, not --workflow. The group spec is a plain path via --groups-file (or inline JSON via --groups-json); there is no @file syntax. The file is a single LabwareGroupDTO object or a JSON array of them.
| Flag | Effect |
|---|---|
<workflow> (positional) | The registered @orca.workflow template name. |
--run-mode | Same as run: PURE_SIM / DEVICE_SIM / LIVE. Required. |
--groups-file <path> | Multi-group spec file: one LabwareGroupDTO object or a list of them. |
--groups-json <json> | Same spec inline as a JSON string. Mutually exclusive with --groups-file. |
--batch-mode STANDALONE|JOIN_EXISTING | Default STANDALONE (one fresh execution per submission). JOIN_EXISTING finds an ACCEPTING execution of the same workflow and threads onto it. |
--vars KEY=VAL,... | Submission-scope variable overrides. Same typing rules as run. |
--operator-id <id> | Optional operator id recorded on the submission. |
--profile <name> | Optional deployment-profile name recorded for audit. |
--confirm | Acknowledges the LIVE + sim_override gate, same as run. |
List + detail
orca submission list # all submissions on this runtime
orca submission list --execution <exec-id> # one execution's submissions
orca submission detail <submission-id> # one submission's threads + state
ID prefixes work on detail — first 8 hex chars resolve as long as they're unique.
Pitfalls
JOIN_EXISTINGwith no ACCEPTING execution exits CONFLICT (30). It does NOT silently fall back to STANDALONE. To create a fresh execution, drop--batch-modeor passSTANDALONE.- Groups are independent submissions in the same wave. Each
LabwareGroupDTOgets its own thread spawns. Groups that declareGroupSharing.SHARED_ACROSS_GROUPSon their labware templates converge on shared physical labware — read the template flags before assuming isolation.
Run one method in isolation
To exercise a single method without its surrounding workflow (testing, recovery rehearsal), use method execute:
orca method execute <workflow> <method> \
--labware-start <json> --labware-end <json> \
[--vars <json>] --run-mode <PURE_SIM|DEVICE_SIM|LIVE> [--confirm]
The workflow and method names are positional. --labware-start / --labware-end are JSON maps declaring where the method's labware begins and ends. --run-mode is required (same modes and --confirm gate as run). Works against both backends.
Track an execution
Once submitted, these read-only verbs follow its progress:
orca execution list # all executions
orca execution detail <id> # full snapshot
orca execution threads <id> # thread roll-up
orca execution thread detail <id> <thread-id> # one thread, all fields
execution list takes no filters — it lists every execution known to the loaded system (id, workflow, status, error). Narrow the result yourself with --json | jq if the count is large. detail is the main view: workflow, status, thread counts, and any error.
States
execution list and execution detail report from two different vocabularies.
execution list shows a coarse ExecutionState:
| State | Meaning |
|---|---|
running | Active: accepting, draining, or stopping, with live threads. |
completed | Every thread terminal, no crash or abort. |
failed | Terminal because a thread crashed with an unhandled error (crash-only). An operator-recoverable error-pause is NOT failed; it stays non-terminal until recovered or the thread actually crashes. |
aborted | Terminal via execution stop or unload --force. |
execution detail shows the finer ExecutionPhase:
| Phase | Meaning |
|---|---|
accepting | Live; can take more submissions (JOIN_EXISTING). |
draining | close was called: no new submissions, running threads finish. |
stopping | A confirmed stop is aborting the execution. |
completed / failed / aborted | Terminal, same meanings as the list states above. |
Pause is not a status on either surface; it is a separate latch. execution detail surfaces error-paused threads in its per-thread block, not as the execution status.
Pitfalls
listreturns all executions, including terminal ones, and has no server-side filters. Pipe--jsonthroughjqto narrow by status if the count is large.thread detailonly returns the per-thread snapshot; broader execution context (variables, reservations) lives on the parent. Useexecution detail <id>for those.