Skip to main content

Submissions

A submission is a request to the runtime to run a workflow. The simplest submission runs one workflow with default settings; more advanced shapes let you submit multiple labware groups or join an in-flight execution that's still accepting work.

The simple case

from orca.runtime.run_modes import WorkflowRunMode

submission = await runtime.submit_workflow(
"my_assay",
variables={"dilution_factor": 4.0},
mode=WorkflowRunMode.PURE_SIM,
)

This creates a fresh execution, with one labware group containing one of each thread the workflow declares.

Run modes

The mode keyword is required on every submission — there is no deployment-level fallback. Three values, chosen per submission:

ModeDevices behind the workflowUse it for
WorkflowRunMode.PURE_SIMPure software simulators. No driver code paths exercised; no hardware contact.Authoring and iterating on workflows on a laptop. The fastest mode.
WorkflowRunMode.DEVICE_SIMReal driver code against PyLabRobot Chatterbox simulators. Same code path that runs against real hardware, with the I/O stubbed.Validating driver behavior, integration testing, dry runs before a hardware deploy.
WorkflowRunMode.LIVEReal hardware drivers talking to real instruments.Production runs.

Before each execution starts, the runtime validates every device declared in the topology against the requested mode. Submitting LIVE against a topology with disconnected hardware fails fast with DEVICE_OFFLINE instead of part-way through the run.

Labware groups

A LabwareGroup is a logical bundle of labware that move through a workflow together. submit_workflow always runs a single default group. To submit multiple groups, use the lower-level runtime.submit(...), which takes a WorkflowTemplate (not a name) plus groups and batch_mode:

from orca.runtime.submission import BatchMode

template = build.system.get_workflow_template("my_assay")

submission = await runtime.submit(
template,
groups=[
LabwareGroup(id="g1", members=[
LabwareGroupMember(thread_template_name="plate_journey", ...),
]),
LabwareGroup(id="g2", members=[
LabwareGroupMember(thread_template_name="plate_journey", ...),
]),
],
mode=WorkflowRunMode.PURE_SIM,
)

mode is required here too. Each group spawns its own copy of every required thread. Groups can share final receivers if a labware template is declared SHARED_ACROSS_GROUPS, useful for workflows where multiple sample plates converge on one final analysis plate.

TODO: full LabwareGroup / LabwareGroupMember field reference.

Sharing labware across groups

A labware template can be flagged SHARED_ACROSS_GROUPS so all groups in a submission converge on the same physical instance:

from orca.resource_models.sharing import GroupSharing

final_plate = PlateTemplate(
"final_plate",
Cor_Falcon_96_wellplate,
group_sharing=GroupSharing.SHARED_ACROSS_GROUPS,
)

Two orthogonal flags on a labware template control sharing, both defaulting to the isolated value:

FlagValuesEffect
group_sharingGroupSharing.PER_GROUP (default) / SHARED_ACROSS_GROUPSWithin one submission: each group gets its own instance, or all groups share one.
submission_batchingSubmissionBatching.ISOLATED (default) / BATCHABLEAcross submissions: whether a later JOIN_EXISTING submission may join an in-flight receiver.

Both are silent no-ops in the default single-group + STANDALONE shape. The behavior only activates when the submission opts in (multiple groups for SHARED_ACROSS_GROUPS, batch_mode=BatchMode.JOIN_EXISTING for BATCHABLE).

Batching: joining an in-flight execution

By default, each submission creates a fresh execution. Pass batch_mode=BatchMode.JOIN_EXISTING (the BatchMode enum, not the string) to merge into a still-accepting execution of the same workflow:

from orca.runtime.submission import BatchMode

submission = await runtime.submit(
template,
groups=[...],
batch_mode=BatchMode.JOIN_EXISTING,
mode=WorkflowRunMode.PURE_SIM,
)

The runtime looks for an active execution of the workflow whose phase is still ACCEPTING and injects your groups into it. Fallback behavior:

  • No live execution for this workflow: JOIN_EXISTING falls through to a fresh build, exactly like STANDALONE.
  • The existing execution is DRAINING (its operator called close_execution): the call raises. Resubmit as STANDALONE to start a new execution.

This is the mechanism for staged submissions: kick off a long-running multi-plate assay and add more plates to it as samples arrive over hours. batch_mode and groups live only on runtime.submit(...); submit_workflow does not take them.

Closing an execution

To stop an execution from accepting new submissions but let in-flight threads finish:

phase = runtime.close_execution(execution_id)

close_execution is synchronous and returns the resulting ExecutionPhase. The execution moves to DRAINING; new JOIN_EXISTING submissions targeting it are rejected, while live threads continue to completion.

To abort an execution outright (cancels all threads):

await runtime.abort_execution(execution_id)

abort_execution is async and is the raw, single-call abort primitive: it cancels every thread immediately. The two-call, confirmation-gated operator stop is a separate first-class runtime method, runtime.stop_execution(execution_id, confirm=False): the first call pauses the execution immediately and arms the abort (recoverable via resume), and a second call with confirm=True performs it. It is exposed on the orca daemon REST (POST /operations/stop-execution) and CLI (orca execution stop --confirm), not only on a hosted deployment.

Terminal phase

When an execution's threads all reach a terminal state, the runtime rolls the execution up to a single terminal phase:

  • COMPLETED only if every thread completed.
  • FAILED if the execution task raised, or if any thread ended in the crash-only FAILED status (a thread whose task died on an unhandled error). FAILED takes precedence over ABORTED in the rollup.
  • ABORTED if any thread was aborted or stopped (a clean task return is not enough; ABORT_THREAD and a cooperative stop both return without raising).

Where to go next

  • Runtime — the runtime that accepts submissions.
  • Recovery — what happens when a submitted execution hits an incident.