Documentation
DocsUsing withHuman

Approval pipelines

Define how requests are evaluated and when they reach human review.

Updated Oct 5, 2026

Approval pipelines allow you to write rules to approve requests, deny them or send them for human review.

The Approval pipelines concept explains how they fit into withHuman.

How rules apply

Every request starts in the entry pipeline. Use it for rules that apply to every request. Your organization has exactly one entry pipeline and it can't be archived.

You can create more pipelines, for example one for each team that owns a set of rules. A request only reaches another pipeline when a Delegate block hands it over. A request that is handed over is settled in that pipeline, and nothing after the Delegate block runs.

Loading diagram…

Diagram source
mermaid
flowchart TD
    request["Request from an agent instance"] --> entry["Entry pipeline"]
    entry -->|"Approve or deny"| entryDecision["Return decision to the agent"]
    entry -->|"Delegate block matches"| delegated["Delegated pipeline"]
    entry -->|"Ask a human or no decision"| entryReview["Human review"]
    delegated -->|"Approve or deny"| delegatedDecision["Return decision to the agent"]
    delegated -->|"Ask a human or no decision"| delegatedReview["Human review"]

An approval, denial or human-review outcome stops pipeline processing. If no pipeline decides, the request goes to human review.

Pipelines

Open Approval pipelines from the side menu to find them. The entry pipeline is at the top of the page. Below it is a table of your other pipelines. For each one, the Delegated from column shows which Delegate blocks send requests to it. Filter pipelines searches by name or key, and the status filter can include archived pipelines when there are any.

When a request needs human review and none of your rules says who should review it, it goes to your default reviewers. The If no decision is made card shows who they are. To pick a different escalation path, select Change default reviewers.

If you only manage some pipelines, you see just those.

Approval pipelines overview showing the entry pipeline, the delegated pipelines table and the default reviewers
Every request starts in the entry pipeline, and Delegate blocks hand matching requests to the pipelines below it. Select any screenshot to view it full size.

Creating a pipeline

Select New pipeline, then give it a Name and a Key. Delegate blocks name the pipeline by its key, and permissions can apply to it. You can rename a pipeline later, but you can't change its key, and a key is never reused, even after the pipeline is archived.

A new pipeline starts empty and active, and nothing hands requests to it yet. Add its blocks, then add a Delegate block to the entry pipeline, or to another pipeline, to send requests its way. Until its blocks decide, every request handed to it goes to human review.

To let a team own the pipeline, grant them pipeline permissions for it. See Permissions.

Archiving a pipeline

Select Archive pipeline from a pipeline's action menu. You can't archive the entry pipeline, or a pipeline that an active revision of another pipeline still delegates to. Remove those Delegate blocks and activate the change first.

An archived pipeline keeps its revisions, and requests already being evaluated finish with the rules they started with. It can't be made active again, no pipeline can delegate to it, and its key can't be reused. Archiving can't be undone.

Rules and blocks

A pipeline's rules are made up of blocks. Each block evaluates the request and can approve it, deny it, ask for human review or continue to the next block.

Select Edit pipeline, then Add block. Choose the type based on how the rule makes its decision.

BlockUse it to
Outcome blockEnd the pipeline with the outcome you choose. Every request that reaches it stops here and gets that outcome straight away, and no later block runs.
Webhook blockAsk an external service for an outcome.
AI Judge blockLet an AI model decide the request against a policy you write in plain language. Hosted edition only.
BranchRun a set of blocks only for requests that match a condition.
Delegate to pipelineHand requests that match a condition to another pipeline.

Branch and Delegate blocks choose requests with conditions on the request's fields. See Conditions for the available fields and comparisons.

Webhook blocks reference shared Webhook endpoints, which manage the external service's destination and signing secret separately from the pipeline.

Blocks run in their configured order and stop at the first approval, denial or human-review outcome. Their order matters: a block can't check a request that an earlier block has already decided.

A Branch block holds its own blocks and runs them only for requests that match its condition. Other requests skip it. A request that enters a branch finishes there: if none of its blocks decides, the request goes to human review and nothing after the branch runs.

Give each block a name that explains its rule. Drag blocks to reorder them. Their action menus also move, duplicate or remove them, including moving them into and out of branches.

Build your rules around the information in the request. Check the tool name when a rule should apply only to a particular tool.

The JSON editor is another way to edit the same pipeline; the examples here use the visual Blocks editor.

Tool and argument suggestions

Tool-name suggestions come from your agents' Tools catalogues, supplemented by recent requests you can read. You can build a rule before a discovered tool has sent its first request. Descriptions, sources and schema variants help you choose the right name.

Start with Tool name set to equals or in. Argument suggestions then follow the possible tools in that condition group. Separate alternatives keep their own suggestions. Fields that apply to only some tools are labeled, and conflicting types remain visible.

A name condition matches every source that sends that name. It cannot distinguish two servers exposing the same approval name. Gateway suggestions use the name in approval requests, which can differ from the server-prefixed name advertised to the agent.

Choose an argument to see suitable comparisons and value suggestions. Numbers and booleans have typed controls; enums offer the schema's allowed values. All operators and manual names or paths remain available. Use the JSON editor for array-element predicates; the field picker does not generate wildcard paths. Complex schemas remain available in the agent's tool details, and external schema references are not fetched.

Warnings identify saved fields or comparisons that conflict with current definitions. They are advisory: a refresh never rewrites, deactivates or changes execution of your saved pipeline. When a schema is missing or incomplete, use manual conditions and test them with a representative request.

Example: Refund rules

Our Support assistant calls issue_refund, with amount in dollars and currency set to USD. We want the $500 limit to apply to every agent, so that rule belongs in the entry pipeline. The rules for smaller refunds belong to a Support pipeline that our support team owns.

We'll add these blocks, in order.

PipelineBlockWhenWhat it does
EntryBranch Deny refunds over $500Amount greater than 500An Outcome block denies the refund.
EntryDelegate Support assistant requestsAgent slug equals support-assistantContinues in the Support pipeline.
SupportBranch Approve refunds up to $20Amount at most 20An Outcome block approves the refund.
SupportBranch Review refunds over $20Amount greater than 20 and at most 500An Outcome block asks a human, using Payments review.

Each refund branch will also check that Tool name equals issue_refund and currency equals USD. We'll use All so the tool, currency and amount conditions must all match. That keeps these rules specific to USD refunds.

Support pipeline with a branch that approves refunds up to $20 and a branch that sends larger refunds to Payments review
The entry pipeline checks the $500 limit first, then hands Support assistant's requests to the Support pipeline, whose rules run in order.

Outcome blocks

Use an Outcome block to catch every request that earlier blocks have passed on. Select Add block, then Outcome block. Give it a name and reason, and choose Approve automatically, Deny automatically, or Ask a human. New Outcome blocks start with Ask a human. You can select an escalation path or inherit the pipeline default.

For example, put a branch that approves small refunds first, followed by an Outcome block named Review everything else. Choose Ask a human and your review path. Every request that reaches that block goes to those reviewers, including requests for other tools.

An Outcome block stops the pipeline. Blocks below it stay editable and show Unreachable, naming the Outcome block that prevents them running. Move or remove the Outcome block to let later blocks run. These warnings do not prevent saving or activating a valid revision. Unreachable blocks still undergo the same validation as every other block.

In the entry pipeline, an Outcome block outside any branch also decides the requests that a Delegate block below it would have handed over. Inside a branch, an Outcome block decides only the requests that match the branch; see Branch blocks.

The fallback card remains editable even when it is unreachable. Its default escalation path still applies to human outcomes that inherit it. If you have no Outcome block and no earlier block decides, requests still go to human review.

Human review

An Escalation path decides who is contacted and when a request needs human review. Select one on a block to use it for that block's human-review outcomes, or choose a default escalation path for the pipeline.

withHuman uses the first available option in this order.

  1. The escalation path chosen on the block that asked for a human. When no block in a branch decides, that's the branch's escalation path.
  2. The default escalation path of the pipeline the request was in.
  3. The default escalation paths of the pipelines that handed the request over, starting with the nearest and ending with the entry pipeline.
  4. Any authorized reviewer, if no path is selected.

The defaults also apply when all blocks finish without a decision. Blocks inside a branch don't inherit the branch's escalation path: one that asks for a human without its own path uses the defaults. Routing a request to someone doesn't replace their permission to decide it. See Escalation paths for how reviewers are contacted.

The agent's owner

Some agents are run by one person for themselves, such as a coding agent on a laptop. You can send their requests to the person who runs them instead of to a team. Wherever you choose an escalation path, choose The agent's owner. Under If the agent has no owner, keep Pipeline default or choose a path.

  • The owner is notified through their own notification settings, and only they can decide the request. It waits for them until they decide or it expires; it never moves on because they haven't answered.
  • Requests from agents without an owner, such as a support bot your organization runs, go to the fallback straight away: the path you chose, or else the pipeline default. So do requests whose owner is suspended or doesn't have permission to approve requests. With no default path either, any authorized reviewer can decide them.
  • If the owner is suspended or removed while a request is waiting, the fallback path takes the request over.
  • A block that chooses its own escalation path doesn't ask the owner, even when the pipeline default does.

You don't need an escalation path to use it. The guided setup sets up your coding agents this way, with a path to you as the fallback. People can always approve their own agents' requests when routing reaches them.

Example: Payments review

Our refunds need the Payments team, even if other requests use a different default path. We'll select Payments review directly on the Outcome block in Review refunds over $20. That choice takes precedence over the pipeline defaults.

Pipeline testing

Test request evaluates a sample against your rules, including unsaved changes to the pipeline you're editing. Open it from the Approval pipelines page or a pipeline's action menu and enter a sample request.

Where the test starts depends on where you open it.

  • The Approval pipelines page. The test starts in the entry pipeline, just like a real request.
  • A pipeline's page. The test starts at that pipeline's first block. Pipelines that hand requests to it don't run.

When the sample matches a Delegate block, the test continues in the pipeline it names, using that pipeline's active rules. The Delegate block shows what that pipeline decided. Open the pipeline to see its own blocks.

The highlighted blocks show the route the sample takes, including which branches it entered or skipped. Read each block's outcome and reason to see why it continued or stopped. Later blocks are skipped after a final outcome, and a failed block shows its error.

Testing doesn't create an approval request or contact reviewers. It does make real calls to AI Judge models and webhook endpoints, so use sample data and an endpoint suitable for testing.

Example: A $75 refund

First, we'll save and activate the Support pipeline so the test includes it. Then we'll select Test request on the Approval pipelines page with this $75 request.

json
{
  "request": {
    "tool": "issue_refund",
    "arguments": { "amount": 75, "currency": "USD" },
    "agent_reasoning": "The customer was charged twice for the same order."
  },
  "agent": { "slug": "support-assistant", "name": "Support assistant" }
}

The request passes the $500 limit and is handed to the Support pipeline. It doesn't match the small-refund approval there, so it reaches Payments review. Changing just the amount shows which rule makes each decision.

AmountExpected result
$10The Support pipeline approves it.
$75The Support pipeline sends it to Payments review.
$600The entry pipeline denies it before the Support pipeline runs.
The $75 refund test passing the entry pipeline's $500 limit, handed to the Support pipeline and reaching Payments review
Our $75 request passes the $500 limit, is handed to the Support pipeline and reaches Payments review.

Drafts and activation

Each saved version of a pipeline is a revision. Only one revision is active at a time. The others remain available in its history.

Create revision saves the rules you're editing. Keep as draft leaves the active rules in place; Make active replaces them with the revision you just saved. Unsaved edits aren't a saved draft.

Editing normally starts from the latest saved revision, which may be newer than the active one. Check the revision label before changing existing rules.

Activation affects new requests. Requests already being evaluated keep their existing rules, and requests waiting for a reviewer aren't evaluated again.

Any escalation paths, webhook endpoints and pipelines the revision references must be active. Pipelines can't delegate to each other in a circle. If activation fails, the saved revision remains available as a draft.

The saved revision dialog offering Keep as draft and Make active
Saving and activating are separate steps.

Revision history and rollback

Revisions shows the pipeline's saved history. A revision's action menu lets you View its rules or Create new revision from this to use them as the starting point for an edit.

Use Activate for a newer saved revision or Roll back for an earlier one. Both change which revision handles new requests. Rolling back keeps the newer revisions in the history.

To remove all checks from a pipeline, remove its blocks and activate the empty revision. An empty entry pipeline sends every request to your default reviewers. An empty delegated pipeline sends every request handed to it for human review.

For a real request, use the Audit log to see which revisions and blocks ran and what they decided.

Pipeline revision history identifying the active revision and showing actions for an earlier revision
Revision history shows which rules are active and keeps earlier versions available.

Permissions

Permissions can apply to the whole organization or to particular pipelines. Access to one pipeline doesn't include the entry pipeline or any other pipeline. To let a team own a pipeline, grant them these permissions for that pipeline.

PermissionWhat it lets you do
pipeline.readView pipelines and their revisions.
pipeline.writeEdit, save and test pipeline revisions. With Organization scope, also create pipelines.
pipeline.activateActivate revisions, including rolling back to an earlier one, and archive pipelines.

Viewing escalation paths and webhook endpoints needs access to those resources too. Editing and activation are separate permissions, so someone can save a draft for a colleague to make active.