# Workflow Control (/docs/nodes/utility/workflow-control)

End a workflow's own automation once its job is done. The current run finishes, future scheduled and webhook runs stop, and the workflow records why.



Workflow Control lets a workflow switch its own automation off. Place it after the step that completes the job: a one-time swap, the last order of a plan, a threshold that only needs to fire once. When the node runs, the current execution finishes normally and no further cron ticks or webhook deliveries are admitted. The workflow keeps its graph, its cron expression and its history; only automation stops.

Without it, a "run once" workflow keeps ticking. Every tick is an execution that loads state, sees the job is done, and stands down. Workflow Control replaces that idle loop with a durable record on the workflow itself.

Configuration [#configuration]

| Field     | Type                         | Required | Description                                                                                                                                                                                    |
| --------- | ---------------------------- | -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| operation | `endAutomation`              | Yes      | The only operation today. Shown in the config dialog, not chosen.                                                                                                                              |
| reason    | string                       | No       | Recorded on the workflow and shown on the dashboard. Templates are allowed, for example `Exit filled at {swap.price}`. Trimmed and capped at 200 characters. Default: `Ended by the workflow`. |
| onFailure | `failRun` or `finishAndWarn` | Yes      | What happens if automation cannot be ended. Default `failRun`.                                                                                                                                 |

End automation [#end-automation]

The node acts on the workflow it runs in. It cannot name another workflow, and it reads its identity from the execution, never from its own config.

The reason resolves strictly. If it references a variable no upstream node produced, the node fails instead of ending automation with a blank reason. In an editor preview or a copilot rehearsal the node writes nothing and returns `preview: true`.

Ending is idempotent. A retry of the same node, or a second Workflow Control node on the same route, finds automation already off and reports `alreadyOff: true` without writing anything. A workflow that was paused for a problem, for example after repeated failures, is left as it is so you still see the pause.

Ending is generation-checked. Every run records the automation generation it was admitted under, and every user toggle bumps that generation. If you turn automation off and on again while an older run is still in flight, that run's end node sees a newer generation, writes nothing, and reports `staleGeneration: true`. An older run can never switch off automation you have since re-armed.

Failure policy [#failure-policy]

**Fail the run** (`failRun`) is the default for a node you place by hand. If the node cannot end automation, the run fails, so you learn immediately that "stop when X" did not stop.

**Finish and warn** (`finishAndWarn`) records the error on this node's output and lets the run complete. Use it after a step that already settled, such as a broadcast swap, so a bookkeeping problem never marks a completed trade as failed. Copilot recipes set this policy on every Workflow Control node they emit.

Either way, when the end fails while automation is still on, the workflow records a warning that stays on the dashboard until a later end succeeds or you toggle automation yourself. The workflow keeps ticking and retries the end on each tick that reaches the node.

What you see afterwards [#what-you-see-afterwards]

The editor header shows "Ended by the workflow" with the reason and when it happened. This is a neutral state, not the red "Automation paused" you see after a failure streak. The workflow list shows **Finished** in place of Paused.

Turning automation back on is an explicit re-arm. The confirm names the reason and warns that a one-time action can execute again if its condition still holds. Run from the editor keeps working on an ended workflow and shows the same warning first; confirming runs the graph as designed without turning automation back on, and its own checks decide what happens.

In copilot recipes [#in-copilot-recipes]

The copilot places this node for you in two vetted recipes. The Zcash exit's price variant ends automation right after the one-time swap, and again on any later tick that finds the exit already done. A canvas DCA plan ends automation on the tick after its last order fills. Both use the finish-and-warn policy. A Zcash exit built before this node existed is refused at accept time with a prompt to build it again.

Output [#output]

```json
{
  "success": true,
  "operation": "endAutomation",
  "ended": true,
  "alreadyOff": false,
  "preview": false,
  "staleGeneration": false,
  "reason": "Exit filled at 41.20"
}
```

Exactly one of `ended`, `alreadyOff`, `preview` and `staleGeneration` is true on a successful call. On a recorded failure under `finishAndWarn`, the output carries `success: false`, `error` and `softFailed: true` instead. Downstream nodes reference the output through the node's response name, for example `{workflowControlResponse.ended}`.

Limits [#limits]

* App instances cannot contain this node. Apps own their lifecycle through their plan controls, so an app graph with a Workflow Control node is refused when the app starts or updates.
* Inside a ForEach loop body the node ends automation on the first iteration and does nothing after. The editor warns; place it after the loop.
* Re-enabling from a node is not possible. Only you can arm an ended workflow again.

Next steps [#next-steps]

* [Storage](/docs/nodes/utility/storage) - the in-run flag that guards a one-time action while a run is still settling
* [Condition](/docs/nodes/utility/condition) - route to Workflow Control only on the outcome that completes the job
