Workflow run
Included from Basic tier
A workflow run is one execution of a published workflow version: the run
record plus its tree of workflow steps (which may themselves spawn changes or
child workflow runs). JSON:API type: workflow_run.
The v2 OpenAPI document declares this resource's schema; the resource-field coverage gate holds this page to it.
Endpoints
| Route | Serves |
|---|---|
GET /api/workflow_runs | List, created_at desc then id desc. Default limit 100, max 10,000; 206 + meta.partial_response when trimmed. Default include=workflow_version. |
GET /api/projects/{project}/workflow_runs and …/workflows/{code}/runs | The same list scoped to a project or one workflow (node-path router). |
GET /api/workflow_runs/{id} | Show. Default include=workflow_version,steps. Runs of a soft-deleted subtree are hidden from lists but still served by id. |
POST /api/workflow_runs (and the node-path …/workflows/{code}/runs) | Create — or retry, when attributes.retry is true. The body may carry an inputs object, validated against the version's declarations before the run exists: unknown names, missing required inputs, type/enum mismatches and non-vault-reference secrets are named 422s pointing at inputs. |
POST /api/workflow_runs/plan (and the node-path …/workflows/{code}/runs/plan) | Plan without creating: the create body — inputs included — resolved and evaluated with no run row; 200 with a plan document — tier-1 verdicts (input-driven conditions evaluate concretely), tier-2 symbolic spans. Advisory: the run re-evaluates at step entry. |
DELETE /api/workflow_runs/{id} | Cancel: 204, or 422 Workflow run cannot be cancelled because it is already finalised. |
POST /api/workflow_runs/{id}/pause / /resume | Pause/resume; 422 named errors as for changes. |
GET /api/workflow_runs/{id}/log_lines, GET /api/workflow_run_log_lines | The run's log surfaces. A run-scoped read serves the whole tree's aggregation — the run's own lines plus every workflow step's nested change's lines (named divergence: this engine's workflow steps log through their nested changes, so upstream's run-only shape would read empty). Each line carries workflow_step_id and workflow_step_path (the step's name path in the run's tree) so per-step grouping and --step filtering work; a nested change's lines are attributed to the spawning workflow step (its change_id names the change). Keyset-paginated like change log lines: limit, filter[logged_at_gt]=<logged_at>#<id> and the 206 links.more continuation. A workflow_step_id scope narrows to one step (include_child_steps=true widens to its subtree). A nested workflow run's lines belong to that run's own id. |
List filtering is filter[<attribute>_eq]=<value> over the serialized
attributes; other predicates are a 400. The GUI's Activity and Workflows
screens read runs through the merged activity feed instead, whose richer
filter vocabulary (free text, timestamp windows, workflow_code_eq,
version_in, …) is documented in the change resource page's
"The activity feed" section (opschain docs resources/change). Reads are
authorised on /projects/{project_code}; pause/cancel on execute over
/projects/{project_code}/workflows/{workflow_code}. Pause availability is
advertised on the run document itself: links.pause appears while the run
is pausable (not finalised, not paused) and links.resume while it is
paused (the upstream serializer's conditional links).
Attributes
| Attribute | Type | Meaning / origin / null semantics |
|---|---|---|
step_tree | object/null | The resolved step tree stored at run creation; null when the row stores none. |
scheduled | boolean | True when a scheduled activity created the run. |
metadata | object | Caller-supplied metadata, stored at create, plus the server-owned opschain namespace the create lane stamps: the run's identity header and the requester provenance — opschain.requester_kind (user | agent), opschain.rationale, opschain.recommendation_id, and on an agent-originated run opschain.agent_id (the fleet member id), opschain.instance_id (the acting instance — the run's initiator), opschain.agent_code, opschain.agent_project, opschain.tier_at_creation, opschain.correlation_id — read back by the approvals inbox as the approval context (opschain docs resources/approval). |
rationale | string | Create attribute (POST /api/workflow_runs): why the run is raised, stored as opschain.rationale. Optional for a person; mandatory for an agent principal (422 Rationale can't be blank otherwise). At most 4000 characters. |
recommendation_id | string | Create attribute: the recommendation the run implements, stored as opschain.recommendation_id. |
created_by | string | Username of the creator. |
cancelled_by | array/null | Audited cancel transitions; null when never cancelled. |
skip_steps | array of strings | The create/retry request's skip mask. |
pause_state | string | "none", "pausing" or "paused" (the same active-leaf-or-wait rule as changes). |
status_code | string | The root workflow step's status — see the vocabulary below. "pending" until a root step row exists. |
paused | boolean | True while paused_at is set. |
paused_by | array | Ordered pause/resume audit trail from the audit:workflow_runs:pause/audit:workflow_runs:resume events. [] when never paused. |
created_at | string | Row creation time. |
started_at | string/null | Earliest step start across the run's steps; null until any step starts. |
finished_at | string/null | The root step's finish; null until finalised. |
updated_at | string | The run row's last update. |
paused_at | string/null | When the current pause began; null while not paused. |
project_name | string | Owning project's display name. |
workflow_code | string | The workflow's code. |
correlation_id | string | The chain handle; defaults to the run's own id. |
caused_by_event_id | string/null | The event that triggered the run, else null. |
initiated_by_type / initiated_by_id | string/null | The polymorphic initiator; null for user-created runs. |
chain_depth | integer | Hops from the chain's origin. |
maintenance_stamp | string/null | Present only on runs created under a maintenance override; absent otherwise. |
inputs | object | The run's recorded typed inputs: supplied values and evaluated defaults alike, resolved and validated at creation against the version's declarations. Secret-typed values serialize as ****** in every surface (the stored value is a vault reference, never a raw secret). Absent when the run carries no inputs. |
error_handled | boolean | true once a failure-path step (when: error()/always()) executed on this run's failed scope — the run still finalises error. Absent otherwise. |
The run's workflow steps additionally carry the step attributes the
step dictionary marks as shared — condition_verdicts,
estate_reads, content_reads, retry_attempts, error_handled, fan_out,
last_error_message (the reason the step last failed, verbatim — for a
change step whose nested change was refused at creation, the API's own
refusal: an invalid action file's validation error, an unknown or
missing required input) and outputs: a workflow change step's
rolled-up nested-run outputs (sensitive values redacted ******), the
document the workflow-scope steps.<name>.outputs.* namespace reads.
Status vocabulary
The run reports its root workflow step's status, from the shared state set:
pending, queued, running, waiting, success, skipped, error,
cancelled, aborted, system_error
plus the pseudo-statuses waiting, waiting_for_approval, rejected and
retry-pending computed the same way as for changes (see
opschain docs resources/change). pause_state: none, pausing,
paused.
How a workflow run differs from a change
- No git surface: a run has no
git_remote_name/git_rev/commit_sha— commits belong to the changes its change steps spawn. - No
action/step_nameand no approval attributes on the run itself:requires_approval_from,approved_byandrejected_bylive on the individual workflow steps, and the gates are workflow-step endpoints. - Carries
step_tree(resolved at creation) where a change carriesinitial_step_tree; nostate_timing/state_timing_summary,cluster_name,notify,starting_step,build_without_cacheorauto_continue_wait_steps. - Node naming is project-only (
project_name,workflow_code) — noenvironment_name/asset_name; the targets are per change step. - Show meta is always
{}(nowait_queue/blocking_queue).
Relationships and includes
| Relationship | Target type | Notes |
|---|---|---|
workflow_version | workflow_version | The version that ran. The list default include. |
workflow | workflow | The owning workflow. |
parent_workflow_step | workflow_workflow_step | Set when a parent run's workflow step spawned this run; data: null otherwise. |
root_step | workflow step types | The run's root workflow step; null data until one exists. |
steps | workflow step types | Every workflow step, ordered (parent, step_sequence); each ref carries its own STI wire type (workflow_noop_step, workflow_change_step, workflow_wait_step, workflow_workflow_step). |
override_properties | properties | Only when the create carried property overrides; otherwise data: null, links.related: null. |
Links: self
(/api/projects/{project}/workflows/{code}/runs/{id}), parent (the
project), log_lines.
Related pages
opschain docs resources/workflowandopschain docs resources/workflow_version— the definition this run executes.opschain docs resources/step— the workflow step family (and change steps).opschain docs resources/change— the change-run sibling.