Router Step

Router steps send each workflow run down the first branch whose condition matches. Use a Router when the workflow needs more than a pass/fail decision, such as routing invoices by value, document type, region, or exception category.

Use Router for new branching logic. Existing legacy Conditional steps continue to work, but Composer chat does not create or edit them.

How routing works

Each branch has a name and one predicate block. Like a Validation step, that block can use JavaScript code or an LLM-powered semantic check.

Branches run from top to bottom:

  1. The Router evaluates the first branch.
  2. If it matches, the run follows that branch and later branches are not evaluated.
  3. If it does not match, the Router evaluates the next branch.
  4. If no branch matches, the run follows the Else output. Leaving Else unconnected stops the workflow at the Router.

This makes branch order significant. Put the most specific or highest-priority conditions first.

Configure branches

  1. Add a Router node and connect an upstream step to it.
  2. Select Configure.
  3. Name the first branch, choose Code or Semantic, and define when it should match.
  4. Select Add branch for each additional route.
  5. Drag branches into evaluation order.
  6. On the workflow diagram, connect each named output and the Else output to downstream steps. Changes save automatically.

Code branches

Return true to select the branch or false to continue to the next branch. Return [boolean, "reason"] to include an explanation in the run result.

1const total = context.outputs.extract_invoice.total.value.amount;
2
3if (total == null) return [false, "No invoice total"];
4return [total >= 10000, `Invoice total is ${total}`];

Router code predicates accept boolean results only. Do not return a route name from the code—the matching branch already determines the route.

Router code uses the same context shape as Validation code blocks. In a multi-file workflow after a Collect step, use context.outputs.<step> for aggregate checks and context.files[i].outputs.<step> to associate an output with a specific file. The aggregate output arrays are not index-aligned with context.files, because routing may skip a step for some files.

Semantic branches

Write a yes-or-no criterion and optionally insert upstream values with {{ }} templates. Variables inside the templates are formatted and queried using JMESPath.

The applicant names in {{ outputs.extract_loan_application.applicant_names.value }} match the borrower names on the promissory notes in {{ outputs.extract_mortgage_package.promissory_note_borrower_names.value }}.

A yes result selects the branch. A no result continues to the next branch.

Build a Router with Composer chat

Workflow Composer can add the Router, inspect upstream variables, create code or semantic branches, reorder them, and connect every branch—including Else—to its destination.

For example:

After validate_invoice, add a Router named route_invoice with these branches in order:
1. High value: use code to match totals of at least 10,000 and route to finance_review.
2. Possible fraud: use a semantic check for suspicious vendor or invoice details and route to fraud_review.
Route everything else to send_response.

You can also target one branch without rebuilding the Router:

Change the High value branch threshold to 25,000, then move Possible fraud above it.

Name the upstream steps and fields when you know them. Composer checks the workflow’s available variables before writing predicates.

See Composer chat for permissions, approval modes, and chat history.

View run results

Open a completed workflow run and select the Router step. The result shows the selected route and each branch that was evaluated before the match. Code reasons and semantic reasoning appear with their branch results. If no branch matched, the result shows that the run followed Else.