Workflows and runs
- A workflow is the definition: the steps, inputs, and configuration.
- A run is a single execution of a workflow against specific inputs.
Running a workflow
1
Find the workflow
List your workflows to get the
id of the one you want to run.2
Create a run
Trigger a run with the inputs the workflow expects.
3
Check run status
Poll the run to follow its progress and read its output when it completes.
Runs are asynchronous. Creating a run returns immediately with a run record; poll
GET /v1/workflow-runs/{id} (or use a webhook trigger) to track completion.Conditional branch steps
A branch step runs one of two arms based on a condition, so a workflow can take different paths at run time — for example, escalate to human approval only when a score is low, or skip a report step when an optional input was not provided.- The condition is a single CEL expression that must evaluate to a boolean.
- The step has two arms —
thenandelse— and each arm is an ordinary list of steps. - Exactly one arm runs. Steps in the arm that did not run are recorded as skipped, and downstream references reaching into a skipped subtree render as empty rather than failing the run.
input— the run’s inputs.steps— outputs of steps that ran strictly before the branch. It cannot see either arm’s own children, since neither has run when the condition is evaluated.triggeredBy— the Metal user ID that started the run. It is empty when the run was system-triggered.now— the current time.- Inside an iterator,
input.itemis the current work item and the branch is evaluated once per item. The separateiteratorroot carries frame metadata:itemIndex,stepId,childStepId, andchildStepIndex.
has(input.<key>) to test whether an optional input was supplied, and "<stepId>" in steps to guard a reference to a step that may not have run.
Nesting and validation
- Branches can nest inside their own arms, and inside iterators. Nesting is capped at 3 branch levels deep, counted from the workflow root — an iterator does not reset the count.
- Step IDs must be unique across the entire step tree, not just within one arm.
- A cross-arm reference — one arm reading a step in the other — is rejected at authoring time, because the two never both run. A reference made after the branch to a step inside an arm is allowed but flagged as conditional.
- Inside an iterator, arm children are restricted to inline-executable step types (
agent,completion,tool,generateDocument,executeCode, and nestedbranch);humanInLoopanditeratorare rejected inside a branch that itself sits in an iterator. - Plain message-approval
humanInLoopsteps are allowed in a branch arm; structured-review approval is not.
Workflow inputs
Each input in a workflow’s schema is either required or optional:- Required inputs must be supplied on every run. The Run form disables Run until each required field has a value, and names the specific fields that are still missing.
- Optional inputs may be left blank. A blank optional field is omitted from the run payload entirely rather than sent as
""or[], which matters for typed fields like resource IDs where an empty string is not a valid value. - Inputs supplied by a trigger (webhook or event) and inputs meant for manual runs only are surfaced by the server’s effective input schema and handled separately from author-supplied fields — you do not need to fill them in yourself when creating a run against a triggered workflow.
Managing runs
Beyond creating and reading runs, you can:- Retry a failed run:
POST /v1/workflow-runs/{id}/retry - Re-run with the same inputs:
POST /v1/workflow-runs/{id}/rerun - Cancel an in-progress run:
POST /v1/workflow-runs/{id}/cancel - List runs for a workflow:
GET /v1/workflows/{id}/runs
Versioning
Workflow definitions are versioned. You can list versions (GET /v1/workflows/{id}/versions) and restore a previous version (POST /v1/workflows/{id}/versions/restore) if a change needs to be rolled back.

