The four outcomes
Retry intent is internal to the engine. It triggers re-execution inside the retry loop and is never visible in edge
condition expressions. Retryable failures emit stage.retrying events while the node is still active, then finish as one of the four outcomes above.How handlers produce outcomes
Each node type has its own rules for which outcomes it can return:Retry loop
When a handler returns a retryable failure, the engine enters the retry loop. If retry attempts remain (per the node’s retry policy), the handler re-executes after a backoff delay. If attempts are exhausted, the final outcome depends onallow_partial:
allow_partial
When allow_partial=true and the retry loop exhausts all attempts on a retryable failure, the outcome is promoted to partially_succeeded instead of failed. This lets the workflow continue past nodes that could not fully succeed.
partially_succeeded rather than failing the run.
See Retry policies for the available presets and backoff settings.
Succeed on failure
When a node’s effectiveon_failure policy is succeed, a failed outcome with no explicit recovery route is promoted to succeeded. This is applied after the retry loop, so retries still happen normally — only the final outcome changes. The original failure details stay on the stage.completed event and in the checkpoint, and the outcome’s notes record the promotion.
on_failure="succeed" for nodes whose failure should never block the workflow — optional scans, best-effort cleanup steps, or informational commands where the output matters more than the exit code. An explicit condition="outcome=failed" edge still takes priority; the promotion applies only when no explicit route matches. The policy applies only to failed and leaves partially_succeeded unchanged. See Failed-node routing policy for the full set of policies.
auto_status=true is the deprecated spelling of on_failure="succeed". Fabro still accepts it as an alias, and validation reports an auto_status_deprecated warning with the replacement. Unlike the old attribute, the alias no longer promotes partially_succeeded outcomes.Goal gate interaction
Node outcomes and workflow status are separate. A node can finish withfailed
and the workflow can still reach exit and complete successfully if routing
handles that outcome. Mark a node with goal_gate=true when its failure must
make the workflow fail.
Nodes marked with goal_gate=true are checked when the workflow reaches the exit node. A goal gate is satisfied if its last outcome was succeeded or partially_succeeded. Any other outcome (failed, skipped) causes the workflow to fail, even though execution reached the exit.
This means allow_partial=true on a goal gate node lets the gate pass even if the node exhausted its retries — the promoted partially_succeeded outcome counts as passing. Likewise, a succeeded outcome promoted by on_failure="succeed" satisfies the gate.
See Goal gates for retry target resolution and failure behavior.
Outcome in edge conditions
The four externally-visible statuses can be used in edgecondition expressions via the outcome key: