Skip to main content

Conditional Branching in Orchestrations

A branching orchestration with condition nodes; unreached nodes are recorded with status: "skipped". You route a condition node to one of two transform branches, run both, and list each run's node executions. No AI provider is required.

Prerequisites​

export SOAT_BASE_URL=http://localhost:5047

Step 1 — Log in as admin​

See Users for authentication.

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>"; a node whose only incoming edge is not traversed is recorded skipped. See Orchestrations — Node Types.

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​

urgent: true makes route emit "alert"; send_alert runs and queue_task is skipped. Trace schema: Orchestrations — Node Executions.

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

ALERT_RUN_ID=$(echo "$ALERT_RUN" | jq -r '.id')

echo "$ALERT_RUN" | jq '{status, result: .output}'

soat list-orchestration-run-node-executions \
--orchestration-run-id "$ALERT_RUN_ID" | jq '.data | map({node_id, status})'

Expected output:

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

queue_task shows status: "skipped", output: null, started_at: null.


Step 5 — Run the queue branch​

urgent: false makes route emit "queue"; send_alert is skipped and queue_task runs (Node Executions).

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

QUEUE_RUN_ID=$(echo "$QUEUE_RUN" | jq -r '.id')

soat list-orchestration-run-node-executions \
--orchestration-run-id "$QUEUE_RUN_ID" | jq '.data | 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​

Replace the transform nodes with agent nodes per branch: Orchestrate a Sonnet, Multi-Agent Orchestration.