Skip to content

Control Flow

Pipelines aren't always a straight line. Sometimes you need to run two things at once, choose between paths, or repeat a step for each item in a list. That's what control flow is for.

The good news: you don't need to configure anything for the basic case. Steps just run in order, one after another. Control flow is only needed when you want something different from that default.

Sequential execution (the default)

Implemented

Steps run in declaration order. The second step starts when the first finishes. No configuration needed.

yaml
steps:
  - name: fetch_profile
    action: ai
    prompt: "Describe the career history of {{ input.person_name }}"

  - name: write_bio
    action: ai
    prompt: "Write a LinkedIn bio based on this profile: {{ fetch_profile.text }}"

write_bio waits for fetch_profile to complete, then uses its output. That's it.

Parallel branches

Spec Only

But what if two steps don't depend on each other? Running them sequentially wastes time. Use parallel to run them simultaneously.

yaml
steps:
  - name: research
    parallel:
      - name: search_web
        action: ai
        prompt: "Find recent news about {{ input.topic }}"

      - name: search_papers
        action: ai
        prompt: "Find academic papers about {{ input.topic }}"

  - name: synthesize
    action: ai
    prompt: |
      Synthesize these sources:
      News: {{ search_web.text }}
      Papers: {{ search_papers.text }}

search_web and search_papers run at the same time. synthesize waits for both to finish before starting.

Not yet implemented

Parallel execution is defined in the spec but not yet implemented in the JigSpec runtime. Steps run sequentially even when listed in a parallel block. This is on the roadmap.

Conditional routing

Spec Only

What if you need to choose which path to take based on data? Use condition.

yaml
steps:
  - name: classify
    action: ai
    prompt: "Classify this ticket as 'bug', 'feature', or 'question': {{ input.message }}"

  - name: route
    use: condition
    when:
      - if: "{{ classify.text }} == 'bug'"
        then: handle_bug
      - if: "{{ classify.text }} == 'feature'"
        then: handle_feature
      - else: answer_question

  - name: handle_bug
    action: ai
    prompt: "Write a bug report template for: {{ input.message }}"

  - name: handle_feature
    action: ai
    prompt: "Write a feature request for: {{ input.message }}"

  - name: answer_question
    action: ai
    prompt: "Answer this question helpfully: {{ input.message }}"

The condition step evaluates the when clauses in order. The first match wins. else is the fallback.

Not yet implemented

Conditional routing is defined in the spec but not yet implemented in the JigSpec runtime. This is on the roadmap.

Loops

Spec Only

What if you need to apply the same step to every item in a list? Use loop.

yaml
steps:
  - name: extract_items
    action: ai
    prompt: "Extract the line items from this invoice as a JSON list: {{ input.invoice_text }}"
    output_schema:
      items:
        - description: string
          amount: number

  - name: categorize_each
    use: loop
    over: "{{ extract_items.data.items }}"
    as: item
    max_loops: 50
    step:
      name: categorize
      action: ai
      prompt: "Categorize '{{ item.description }}' as: office, travel, software, or equipment"

For each item in the list, the inner step runs with item bound to that element. The loop collects all results.

Output: categorize_each.results — an array of each iteration's output.

The max_loops field is a safety limit. If the input list is longer than max_loops, the pipeline fails with a clear error rather than running indefinitely.

Not yet implemented

Loops are defined in the spec but not yet implemented in the JigSpec runtime. This is on the roadmap.

Start simple

Most pipelines only need sequential execution. Reach for parallel, conditional, and loops only when the simpler approach has a real cost — an extra second of latency, an untaken branch, a repeated prompt.

Released under the Apache 2.0 License.