Skip to main content

Conditional Branching in Orchestrations

This tutorial shows how to build a branching orchestration using condition nodes. When a run completes, every node that was not reached is recorded with status: "skipped" — giving you a complete execution trace regardless of which path ran.

You will define an orchestration whose condition node routes to one of two transform branches, then run both branches and inspect node_executions. No AI provider is required.

Prerequisites

  • SOAT running locally. Follow the Quick Start guide to bring the stack up with Docker Compose.
  • New to orchestrations? Read Key Concepts and the Orchestrations module before diving in.
  • CLI installed and configured, or SDK set up. See CLI or SDK.
  • For production hardening (secrets, env vars), see Configuration.
  • Server is at http://localhost:5047.
export SOAT_BASE_URL=http://localhost:5047

Step 1 — Log in as admin

See Users for authentication details.

ADMIN_TOKEN=$(soat login-user --username admin --password Admin1234! | jq -r '.token')
export SOAT_TOKEN=$ADMIN_TOKEN

Step 2 — Create a project

All orchestrations belong to a project.

PROJECT_ID=$(soat create-project --name "triage-demo" | jq -r '.id')
echo "Project: $PROJECT_ID"

Step 3 — Create the orchestration

The graph has three nodes:

NodeTypePurpose
routeconditionEvaluates urgent from input state and emits "alert" or "queue"
send_alerttransformRuns only on the alert branch
queue_tasktransformRuns only on the queue branch

Edges carry condition: "<label>" to select which branch the engine traverses after route completes. A node whose only incoming edge is not traversed is recorded as skipped when the run finishes. See Orchestrations — Node Types for the full condition node reference.

ORCH_ID=$(soat create-orchestration \
--project-id "$PROJECT_ID" \
--name "content-triage" \
--nodes '[
{
"id": "route",
"type": "condition",
"expression": {"if": [{"var": "input.urgent"}, "alert", "queue"]}
},
{
"id": "send_alert",
"type": "transform",
"expression": {"cat": ["ALERT: ", {"var": "input.topic"}]},
"state_mapping":{"state.result":{"var":"output.result"}}
},
{
"id": "queue_task",
"type": "transform",
"expression": {"cat": ["QUEUED: ", {"var": "input.topic"}]},
"state_mapping":{"state.result":{"var":"output.result"}}
}
]' \
--edges '[
{"from": "route", "to": "send_alert", "condition": "alert"},
{"from": "route", "to": "queue_task", "condition": "queue"}
]' | jq -r '.id')
echo "Orchestration: $ORCH_ID"

Step 4 — Run the alert branch

Pass urgent: true. The engine evaluates the route condition, emits "alert", traverses only the send_alert edge, and records queue_task as skipped. See Orchestrations — Node Executions for the full execution trace schema.

ALERT_RUN=$(soat start-orchestration-run \
--orchestration-id "$ORCH_ID" \
--input '{"urgent": true, "topic": "Server is down"}')

echo "$ALERT_RUN" | jq '{status, result: .output, executions: .node_executions | map({node_id, status})}'

Expected output:

{
"status": "succeeded",
"result": null,
"executions": [
{ "node_id": "route", "status": "completed" },
{ "node_id": "send_alert", "status": "completed" },
{ "node_id": "queue_task", "status": "skipped" }
]
}

The queue_task node appears in the trace with status: "skipped", output: null, and started_at: null — confirming it was never executed.


Step 5 — Run the queue branch

Pass urgent: false. Now route emits "queue", send_alert is skipped, and queue_task runs.

QUEUE_RUN=$(soat start-orchestration-run \
--orchestration-id "$ORCH_ID" \
--input '{"urgent": false, "topic": "Update documentation"}')

echo "$QUEUE_RUN" | jq '.node_executions | map({node_id, status})'

Expected output:

[
{ "node_id": "route", "status": "completed" },
{ "node_id": "send_alert", "status": "skipped" },
{ "node_id": "queue_task", "status": "completed" }
]

Next Steps

To apply this pattern to a real pipeline, replace the transform nodes with agent nodes pointing at specialized agents for each branch. See Orchestrate a Sonnet and Multi-Agent Orchestration for examples that wire agents into an orchestration graph.