Skip to main content
Add approval: required to any step and the run pauses before that step, shows what is about to happen, and waits for a yes/no. This is how you trust a workflow with real-world actions — sending messages, creating issues, deploying — without giving up the final say.
At a terminal:
The preview shows resolved values — the actual message text, not ${...} templates. You approve what will happen, not the abstract definition.

Denying

Answering no stops the run cleanly before the step runs: nothing fired, nothing failed. The exit code is 3 (distinct from 1 for failures — a human verdict is not an error), and the trace records final_status: "denied".

Pre-approving gates

For CI or agent-operated runs, pre-approve specific gates by step name:
The flag is per-step and repeatable — there is deliberately no approve-everything form. Each pre-approval is recorded in the trace (resolved_via: flag), so you can always audit which gates a human answered live versus approved in advance.

Non-interactive runs pause — and you answer later

A run with no terminal (piped, launched from the web UI, or via the MCP server) cannot prompt. A gate reached without pre-approval pauses the run durably instead of failing — never hangs — and prints a resume token:
Nothing re-runs when you answer: the completed steps are kept, and the decision can come hours or days later, through either surface:
  • In the browser: pflow ui <workflow> --run <token> opens the paused run on the visual canvas. The paused step carries a ⏸ badge with an answer panel showing the step’s resolved values — click Approve or Deny (for an escalation: pick an option or type an answer) and watch the run continue in place.
  • From the terminal: pflow resume <token> --approve yes|no (escalations: --choose "<answer>"). pflow resume list shows every pending pause.
A deny still exits 3 with final_status: "denied" — a human verdict, not an error. Each answered pause produces a new attempt linked to the original run, so the decision trail stays auditable. A warning also fires at run start when the workflow has unapproved top-level gates. Use --dry-run to discover gates before running: gated steps are tagged […, approval] and summarized in a footer.

Escalations — the agent asks you

The second gate kind is raised by an agent step at runtime instead of declared by you. When an agent step discovers a decision it should not make alone, it returns an escalation object (question, options, recommendation) in its structured output — the run pauses, you choose (pick an option or type an answer), and your decision is written back into the step’s result for the workflow to act on, typically by re-running the agent with the decision via loop:. See pflow guide approval for the escalation contract, the re-fork recipe, and the full rules (batch steps can’t be gated — gate around them; loop steps prompt every iteration; cached steps never prompt).