Skip to content

Bound documents (context_bind)

Parse a JSON, XML, or YAML payload once per workflow run and query nested fields via path references — without a separate context_extract_* step for every field.

Source of truth: engine/services/orchestrator/app/workflow_runner.py (ContextBindWorkflowStep, parse_bound_path_ref, _resolve_input).

When to use

Situation Use
Many fields from the same trigger body context_bind + path refs
One or two scalar fields context_extract_json / context_extract_xml (simpler)
Branching on a single value extract → if.condition.context_key

Step: context_bind

- id: bind_request
  type: context_bind
  alias: request
  input_from: initial
  format: auto    # auto | json | xml | yaml
Field Required Description
id yes Step id
type yes context_bind
alias yes Logical document name (request, order, …)
input_from no initial (default on first step), previous, <step_id>, context:<key>
format no auto (default), json, xml, yaml

Behaviour:

  1. Resolves the source text (same rules as other steps).
  2. Parses it once into an in-memory document registry for this run.
  3. Passes the raw text through as this step's output (previous / outputs[step_id]).

Aliases must be unique within the workflow scope. Re-binding the same alias is a runtime error.

Path references

After binding, use path refs anywhere a step accepts a ref (log.values, context_set.value_from, service_call.payload_from, …).

Syntax

Form Example Notes
Explicit format + JSON Pointer request:json:/root/header/date Recommended for JSON
Shorthand JSON Pointer request:/root/header/date Uses bound document format
Dollar path (JSON) request:$.root.header.date Same rules as trigger payload:$.…
Explicit XML XPath request:xml://root/header/date/text() XPath expression after third :

JSON Pointer uses RFC 6901 paths starting with / (array indices are 0-based).

Not supported: wildcards, arbitrary dot paths without $. prefix (use $.a.b or /a/b).

Example workflow

Trigger body:

{"root":{"header":{"date":"2026-06-26","id":"42"}}}
name: inbound-example
steps:
  - id: bind_request
    type: context_bind
    alias: request
    input_from: initial
    format: json

  - id: log_header
    type: log
    level: info
    message: "date={date} id={id}"
    values:
      date: request:json:/root/header/date
      id: request:/root/header/id

  - id: branch_on_date
    type: if
    condition:
      context_key: header_date
      equals: "2026-06-26"
    then:
      - id: set_date
        type: context_set
        context_key: header_date
        value_from: request:json:/root/header/date

For if / when, either:

  • use a path ref in context_set.value_from first, then branch on the context key, or
  • keep using context_extract_json when you prefer explicit context_key names in conditions.

Format detection (format: auto)

Detection order:

  1. Leading { or [ → JSON
  2. Leading < → XML
  3. Try JSON parse
  4. Try YAML parse (mapping or sequence)
  5. Error if none match

Parallel scopes

Bound documents are shared across parallel lanes (shallow copy of the alias map). A context_bind in one lane is visible in others in the same workflow run. True per-scope document isolation is not implemented yet (see ADR 0003).

Validation

The orchestrator validator checks that:

  • every path ref (request:…) references an alias registered by an earlier context_bind in the same scope
  • aliases are not bound twice in the same scope

Unknown trigger.* context keys remain warnings (runtime-injected).