Gates and approvals
A gate is a leg of a pipeline that does no work. It decides whether the legs after it may run. Every gate has exactly one way of being answered:
- by data: an expression over the pipeline’s inputs and earlier legs’ outputs, decided the moment those exist;
- by a person: the pipeline pauses until someone approves or rejects.
A third source adds gates the pipeline author didn’t write: policies in the environment.
flowchart LR
E[estimate] --> D{data gate}
D -- true --> W[the leg that spends]
D -- false --> S[pipeline stops]
P[pull plan] --> H{person}
H -- approve --> X[the leg that changes something]
H -- reject --> S2[pipeline stops]
A gate answered by data
Section titled “A gate answered by data”A data gate has a predicate:. When the legs it depends on finish, the
predicate is evaluated. If it is true the gate passes at once, recorded with
the verdict data, and nobody is asked. If it is false the pipeline stops:
the gate fails closed, and the legs after it never start.
From the public serving/batch-inference pipeline, which prices a job before
spending anything:
steps: - id: estimate task: cost/tokens with: # abridged model: $input.model rows: $input.rows
- gate: cost depends_on: [estimate] predicate: steps.estimate.usd <= input.max_cost_usd
- id: infer flow: batch-infer depends_on: [cost]Because nobody approves a data gate, nobody can approve a run past it. Use one for anything a number can decide: a cost limit, a minimum count of new rows, a “no regression” check.
A gate answered by a person
Section titled “A gate answered by a person”A person gate has no predicate:. When it becomes ready, the pipeline pauses
and the gate appears in the console’s Approvals panel. From the public
dataset_readiness/api-and-admit pipeline, which pulls data from an external
API only after someone has approved the request:
steps: - gate: approve-pull show: - input.connection - input.base_url - input.path - input.max_rows
- id: pull task: ingest/api depends_on: [approve-pull]show:lists what the approver sees next to the decision: inputs or outputs of earlier legs, written as<step>.<field>. Entries that aren’t in that form are rejected when the pipeline loads, so an approver never faces a field that can’t resolve.approvers:names who is asked. A gate without one takes the pipeline’sgovernance.approvers.- The pause is durable. The gate’s state lives in the pipeline’s record, so a restart of the control plane resumes the pipeline at the same pause.
- Approving releases the gate and records who approved, when, and any rationale. Rejecting cancels the pipeline.
A gate can’t have both predicate: and approvers:: the pipeline is refused
at load with “a gate is answered by data OR a human, never both”. If you need
both, write two gates, the data gate first. Then a person is only asked about
runs the numbers already allow.
Who decides
Section titled “Who decides”The decision is recorded under the identity of the person signed in, never a
name typed into the request. approvers: names who is asked: it is shown on
the gate and in the notification. Today it doesn’t restrict who can decide:
any signed-in member of the workspace can approve or reject, and the record
shows who did.
Gates an environment adds
Section titled “Gates an environment adds”A policy can require a gate that isn’t in the pipeline file and that the author
can’t remove. Policies are attached to an environment. A policy whose
applies_to.pipeline_legs globs match a leg is applied when the pipeline is
planned, before anything runs:
require_hitlinserts a person gate immediately before every matching leg;denyrefuses the launch outright, naming the policy.
name: cost-before-trainapplies_to: pipeline_legs: ["training/*"] environments: [production]rules: - effect: require_hitl reason: a person approves every training leg in productionThe inserted gate carries the name of the policy that added it, so the approver and the audit trail see why it exists. A leg that already sits behind a person gate isn’t gated twice.
Approvals inside a flow
Section titled “Approvals inside a flow”Some operators are risky enough that they ask for approval themselves: the operator’s manifest marks it as requiring approval, or the environment’s profile and policies do. Every operator call passes this check, whichever pipeline it runs in. When an approval is required, that step of the flow pauses until someone decides, and the decision lands in the same Approvals panel. One queue, wherever the gate came from.
- Cost and budgets: estimates, series budgets and cost gates.
- Runs and the record: where every decision is kept.
- Pipeline and flow YAML: every gate field.