Skip to main content
Every node execution produces an outcome containing a status that drives edge routing, retry logic, and goal gate checks. This page defines the five statuses and the attributes that influence them.

The five statuses

StatusMeaning
successThe handler completed normally
failThe handler encountered an unrecoverable error
partial_successThe handler did not fully succeed but produced usable results — typically from retries exhausted with allow_partial=true
retryThe handler wants to re-execute — consumed by the retry loop and never appears in edge conditions
skippedThe node was not executed (e.g. a branch not taken in a parallel fan-out)
retry is internal to the engine. It triggers re-execution inside the retry loop and is never visible in edge condition expressions. The four externally-visible statuses are success, fail, partial_success, and skipped.

How handlers produce statuses

Each node type has its own rules for which statuses it can return:
HandlerProducesConditions
Commandsuccess, failsuccess when exit code is 0; fail otherwise
Agent / Promptsuccess, fail, partial_success, retry, skippedDefaults to success. The LLM can set any status via a routing directive JSON object in its response. Backend errors produce retry (if retryable) or fail.
Parallelsuccess, partial_success, failDepends on the join_policy. wait_all: success if no failures, partial_success if some branches failed. first_success / k_of_n / quorum: success if threshold met, else fail.
HumansuccessAlways succeeds — the user’s selection becomes a routing signal via preferred_label
ConditionalsuccessAlways succeeds — routing is handled by the engine’s edge selection
Start / Exit / WaitsuccessAlways succeed

Retry loop

When a handler returns retry status, 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 status depends on allow_partial:
┌─────────────┐
│ Run handler  │
└──────┬──────┘


  ┌──────────┐    success/fail/
  │ Status?  │───partial_success/───▶ Done (use as-is)
  └────┬─────┘    skipped
       │ retry

  ┌──────────────┐   yes    ┌──────────────┐
  │ Attempts     │─────────▶│ Backoff +    │──┐
  │ remain?      │          │ re-execute   │  │
  └──────┬───────┘          └──────────────┘  │
         │ no                                 │
         ▼                         ┌──────────┘
  ┌──────────────┐                 │
  │allow_partial?│                 │ (loops back to
  └──────┬───┬───┘                 │  "Run handler")
    yes  │   │ no                  │
         ▼   ▼
  partial_   fail
  success
Handler errors follow the same loop: retryable errors (transient infrastructure) re-execute if attempts remain; non-retryable errors (authentication, bad config) fail immediately without consuming retry attempts.

allow_partial

When allow_partial=true and the retry loop exhausts all attempts on a retry status, the outcome is promoted to partial_success instead of fail. This lets the workflow continue past nodes that could not fully succeed.
AttributeTypeDefault
allow_partialBooleanfalse
implement [
    label="Implement",
    retry_policy="standard",
    allow_partial=true,
    prompt="Implement the feature."
]
In this example, if the agent returns retry and all 5 standard-policy attempts are used, the node finishes with partial_success rather than failing the run. See Retry policies for the available presets and backoff settings.

auto_status

When auto_status=true, any non-success and non-skipped status is silently overridden to success after the handler completes. This is applied after the retry loop, so retries still happen normally — only the final outcome is overridden.
AttributeTypeDefault
auto_statusBooleanfalse
scan [
    label="Scan",
    shape=parallelogram,
    auto_status=true,
    script="find . -name '*.log' | head -20"
]
Use auto_status 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.

Goal gate interaction

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 success or partial_success. Any other status (fail, 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 partial_success counts as passing. See Goal gates for retry target resolution and failure behavior.

Outcome in edge conditions

The four externally-visible statuses can be used in edge condition expressions via the outcome key:
gate -> deploy  [label="Pass",    condition="outcome=success"]
gate -> fix     [label="Fix",     condition="outcome=fail"]
gate -> review  [label="Partial", condition="outcome=partial_success"]
gate -> skip    [label="Skipped", condition="outcome=skipped"]

// Common pattern: treat partial as passing
gate -> deploy  [condition="outcome=success || outcome=partial_success"]
gate -> fix     [condition="outcome=fail"]
See Transitions for the full edge selection logic and operator reference.