Conditions and Path Expressions¶
This page explains how to read values from JSON, XML, or step output and use them in if, when, repeat_until, and trigger filters.
Source of truth: engine/services/orchestrator/app/workflow_runnerv2.py (WhenCondition, TriggerFilter, context_extract_*, _resolve_input).
Mental model¶
flowchart LR
T[Trigger body → initial] --> S[service_call / other steps → outputs]
S --> E[context_extract_json / context_extract_xml]
E --> C[run context: string keys]
C --> I[if / when / until]
T --> F[trigger_filters payload:$.path]
- Payloads (trigger body,
service_callresponse, transform output) are strings passed along the step chain (initial,previous,outputs[step_id]). - Extract steps copy a fragment into the run context as a string (
context_key). if/when/untilcompare only context strings — they do not evaluate JSON Pointer, XPath, or$.paths directly.
The trigger JSON body is not automatically flattened into context keys. Use an extract step (or a trigger filter at workflow start) first.
if and when today¶
condition (and step-level when, repeat_until.until) use WhenCondition:
| Field | Required | Description |
|---|---|---|
context_key (alias variable) |
yes | Key in the run context |
equals |
exactly one of | String equality |
not_equals |
these three | String inequality |
one_of |
Value in list |
- id: branch_on_status
type: if
condition:
context_key: order_status
equals: "shipped"
then:
- id: notify
type: log
message: "Order shipped"
Notes:
- Comparisons are strict strings (
"6"≠6). - There is no built-in
initial.//alles[1]orinitial:json:/alles/1syntax incontext_keytoday.
Resolving input: input_from and refs¶
Steps that read a document (context_extract_json, context_extract_xml, for_each, json_set, service_call.payload_from, …) resolve the source via _resolve_input:
| Ref | Resolves to |
|---|---|
| (omitted) | initial on first step, else previous |
initial, trigger, trigger.payload |
Trigger/request body string |
previous |
Output of the immediately preceding step |
<step_id> |
Output stored for that step id |
context:<key> or var:<key> |
Value from run context |
After a service_call, the HTTP response body is stored as:
outputs[<step_id>]— useinput_from: <step_id>on a later stepprevious— if the extract step runs directly after the callcontext[<output_key>]— only ifoutput_keyis set on theservice_callstep
- id: fetch_order
type: service_call
capability_name: orders.lookup
path: /v1/orders/123
payload_from: initial
output_key: order_json # optional: also copy response into context
- id: read_status
type: context_extract_json
input_from: fetch_order # same as: previous (if no steps in between)
json_path: /status
context_key: order_status
- id: branch
type: if
condition:
context_key: order_status
equals: "CONFIRMED"
then:
- id: ok
type: log
message: "Order confirmed"
Alternative using output_key only (skip step-id ref on extract):
- id: fetch_order
type: service_call
...
output_key: order_json
- id: read_status
type: context_extract_json
input_from: context:order_json
json_path: /status
context_key: order_status
service_call does not parse JSON; the response must be valid JSON text for context_extract_json.
JSON: extract then branch¶
JSON Pointer (context_extract_json)¶
Use RFC 6901 JSON Pointer — always starts with /:
| Intent | Pointer | Indexing |
|---|---|---|
Field test |
/test |
— |
| Second array element | /alles/1 |
0-based (0 → first, 1 → second) |
| Whole array | /alles |
For for_each with items_path: /alles |
Example trigger: {"test": "1", "alles": ["4", "6"]}
- id: pick_second
type: context_extract_json
input_from: initial
json_path: /alles/1
context_key: second_alles
- id: is_six
type: if
condition:
context_key: second_alles
equals: "6"
then:
- id: found
type: log
message: "Second element is 6"
Not supported in extract paths: alles[1], $.alles[1], //alles.
Dollar path (trigger filters only)¶
At workflow start, invocation.trigger_filters can read the trigger body without an extract step:
invocation:
type: http
trigger_filters:
- property: payload:$.alles.1
equals: "6"
Syntax: payload: + $.segment.segment (dot-separated; numeric segments index arrays). No wildcards (*).
This does not apply to service_call output — only the initial trigger body when the run is accepted.
XML: extract then branch¶
Use context_extract_xml with XPath on XML text from initial, previous, or a step id:
- id: read_order_id
type: context_extract_xml
input_from: initial
xpath: //order/id/text()
context_key: order_id
- id: branch
type: if
condition:
context_key: order_id
equals: "42"
then: []
XPath position predicates are 1-based (//items/item[2] = second item). This differs from JSON Pointer array indices (0-based).
Trigger filters with payload:$.… require parseable JSON; XML trigger bodies need an extract step (or transform to JSON first).
Arrays: “any element equals …”¶
There is no alles[*] = "6" operator in if today. Patterns:
for_each + if per item¶
- id: loop_alles
type: for_each
input_from: initial
items_path: /alles
as_key: item
steps:
- id: check
type: if
condition:
context_key: item
equals: "6"
then:
- id: found
type: log
message: "Found 6"
one_of after extracting a single value¶
When you already have one scalar in context:
condition:
context_key: code
one_of: ["6", "9"]
Using output from multiple steps¶
| Pattern | When to use |
|---|---|
input_from: <step_id> |
Read a specific earlier step’s output string |
input_from: previous |
Previous step only |
input_from: context:<key> |
After context_set, output_key, or mirror_to_context |
collect |
Merge several step outputs into one JSON object/array, then extract |
- id: merge
type: collect
from_steps:
- fetch_a
- fetch_b
merge_mode: object
- id: use_merged
type: context_extract_json
input_from: merge
json_path: /fetch_a/status
context_key: status_a
RAW / plain text¶
- No
context_extract_rawor substring step in the orchestrator v2 runner. - RAW body is available as the full string via
initial/previous/ step output. - Options:
context_setwith a static value, aservice_callto a transform capability, or legacy transform steps where enabled.
invocation.payload_format: raw is mainly a dashboard/content-type hint, not a path language.
Bound documents (context_bind) — preferred for many fields¶
When you need multiple values from the same JSON/XML/YAML payload, bind it once and use path references instead of one extract step per field. See Bound documents.
- id: bind_request
type: context_bind
alias: request
input_from: initial
format: json
- id: log_header
type: log
message: "date={date}"
values:
date: request:json:/root/header/date
Planned extension (partial)¶
Direct path expressions on if / when without an intermediate context_set (e.g. condition.property: request:json:/status) are still a follow-up. Until then, bind + context_set or context_extract_* + context_key.
Quick reference¶
| Goal | Mechanism |
|---|---|
| IF on trigger JSON field | context_bind + path refs, or context_extract_json + if |
| Many fields from one JSON body | context_bind (see 11-bound-documents.md) |
IF on service_call JSON field |
input_from: <service_step_id> + extract + if |
| Filter run at HTTP trigger | trigger_filters with payload:$.path |
| IF on XML node | context_extract_xml + if |
| IF on “any array member” | for_each + nested if |
| Compare multiple allowed values | one_of on WhenCondition |