You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
feat(workflows): stop a manual v2 run after a block, and workflows run --stop-after (#8622)
* feat(workflows): stop a manual v2 run after a block, and `workflows run --stop-after`
A manual v2 run can now name `run.stopAfterBlockId`; the run stops once that
block completes and downstream blocks do not execute. Combined with a block
entry on the same block, it re-runs exactly one block against a prior run's
persisted upstream outputs, server-side:
sim workflows run W --from-block X --source-run R --stop-after X --select-output X.result
Agents verifying an edit no longer re-run every upstream block (often a slow
LLM or API call) or toggle blocks off to skip them.
- Contract: optional `stopAfterBlockId` on the manual run selection.
- Application: both manual operations refuse a block missing from the saved
workflow or nested in a loop/parallel (the engine would otherwise run to the
end or stop after one iteration), before anything runs.
- Execute service: threads the trusted value to the sync and stream paths.
- CLI: `--stop-after <blockId>` implies --manual and rejects --async.
- E2E: test-workflow-stop-after-e2e.ts against a running app; the http-e2e job
gains a Redis service because hosted billing admits runs through a Redis
usage reservation.
* fix(workflows): refuse stop targets a run cannot reach, and run the E2E self-hosted
- The manual operations refuse a stop block the run cannot reach from its
entry (an upstream block would let the run finish everything after the
entry), and look blocks up as own properties.
- The executor fails a run whose stop block is absent from the workflow it
executes, instead of running everything; this closes the window between
validation and the executor's own draft load, for every caller.
- The CLI refuses an empty --stop-after rather than dropping it.
- CI: the stop-after E2E gets its own self-hosted app step; the SCIM suite
asserts PostgreSQL rate-limit storage, so Redis is not added to that app.
Fixture cleanup waits for run logs to finalize before deleting.
* fix(workflows): refuse a disabled stop block, or one reached only through one
The executor omits disabled blocks from its graph, so a disabled stop target,
or one whose only path runs through a disabled block, is never reached and
the run would finish everything after the entry.
* fix(workflows): the executor refuses a disabled stop block too
The serialized workflow keeps disabled blocks, but the DAG skips them, so a
disabled stop target would never be reached.
---------
Co-authored-by: Waleed Latif <waleed@sim.ai>
Copy file name to clipboardExpand all lines: apps/docs/content/docs/cli/reference.mdx
+1Lines changed: 1 addition & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -6704,6 +6704,7 @@ sim workflows run <workflowId> [options]
6704
6704
|`--mock-payload`| No | Use the selected trigger's server-derived mock payload; runs the current saved workflow state (implies --manual). |
6705
6705
|`--from-block <blockId>`| No | Run manually from this saved workflow block. |
6706
6706
|`--source-run <runId>`| No | Prior run whose persisted state supplies upstream outputs (requires --from-block). |
6707
+
|`--stop-after <blockId>`| No | Stop the run after this saved block; with --from-block on the same block, re-runs only that block (implies --manual). |
6707
6708
|`--follow`| No | Stream the run as it happens; progress on stderr, result on stdout. The stream reports only success and output, so the result omits the run id and timings a non-streaming run returns. |
6708
6709
|`--include-thinking`| No | Show model reasoning while following (requires --follow). |
6709
6710
|`--include-tool-calls`| No | Show tool calls while following (requires --follow). |
Copy file name to clipboardExpand all lines: apps/docs/content/docs/cli/workflows.mdx
+1Lines changed: 1 addition & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -642,6 +642,7 @@ sim workflows run <workflowId> [options]
642
642
|`--mock-payload`| No | Use the selected trigger's server-derived mock payload; runs the current saved workflow state (implies --manual). |
643
643
|`--from-block <blockId>`| No | Run manually from this saved workflow block. |
644
644
|`--source-run <runId>`| No | Prior run whose persisted state supplies upstream outputs (requires --from-block). |
645
+
|`--stop-after <blockId>`| No | Stop the run after this saved block; with --from-block on the same block, re-runs only that block (implies --manual). |
645
646
|`--follow`| No | Stream the run as it happens; progress on stderr, result on stdout. The stream reports only success and output, so the result omits the run id and timings a non-streaming run returns. |
646
647
|`--include-thinking`| No | Show model reasoning while following (requires --follow). |
647
648
|`--include-tool-calls`| No | Show tool calls while following (requires --follow). |
Copy file name to clipboardExpand all lines: apps/docs/openapi-v2-workflows.json
+16Lines changed: 16 additions & 0 deletions
Original file line number
Diff line number
Diff line change
@@ -12615,6 +12615,11 @@
12615
12615
"additionalProperties": false
12616
12616
}
12617
12617
]
12618
+
},
12619
+
"stopAfterBlockId": {
12620
+
"description": "Saved workflow block after which the run stops; downstream blocks do not execute. Must not be inside a loop or parallel. With a block entry naming the same block, re-runs only that block against the source run.",
'Manual entry mode. Omit to enter through the workflow trigger; a block entry requires an exact source run.'
1299
1299
),
1300
+
stopAfterBlockId: z
1301
+
.string()
1302
+
.min(1,'run.stopAfterBlockId cannot be empty')
1303
+
.optional()
1304
+
.describe(
1305
+
'Saved workflow block after which the run stops; downstream blocks do not execute. Must not be inside a loop or parallel. With a block entry naming the same block, re-runs only that block against the source run.'
1306
+
),
1300
1307
})
1301
1308
.strict(),
1302
1309
])
@@ -1412,6 +1419,13 @@ export const v2ExecuteWorkflowBodySchema = z
0 commit comments