the path · 02
Parallel fan-out + merge — the core DAG pattern.
run itnika try 02-parallel-fanout
02-parallel-fanout.nika.yaml
# SPDX-License-Identifier: Apache-2.0# yaml-language-server: $schema=https://nika.sh/spec/v1/workflow.schema.json## 02 · Parallel fan-out + merge — the core DAG pattern.## You never write "run these in parallel". You write what each task NEEDS,# and the shape of the graph falls out: three tasks that need nothing from# each other are three tasks the engine may run at once. Concurrency is a# consequence of the dependencies, not an instruction.## Demonstrates ·# - implicit parallelism · no deps between three tasks → one wave, run together# - `const:` · a fixed value baked into the file, never caller-supplied# - `with:` value edges · what a task binds is what it waits for# - `${{ tasks.<id>.output }}` · reading an upstream result## DAG shape · angle ─┐# cost ─┼─→ synthesize# risk ─┘## Run · nika run examples/02-parallel-fanout.nika.yamlnika: v1workflow: id: parallel-fanout# The dry twin, on purpose: this file teaches SHAPE, and the twin makes the# shape visible — it echoes each prompt back, so `synthesize`'s output shows# the three upstream answers arriving inside it. Swap in any real model# (`--model ollama/qwen3.5:4b`) and only the prose changes, never the graph.model: mock/echopermits: {} # pure compute · no file, no host, no program (see 01)const: topic: "adopting Rust for a backend rewrite"tasks: # No task below names another, so the engine puts all three in wave 1 and # runs them concurrently. `nika check` prints the waves it derived — read # that plan before you reach for a knob to make something parallel. angle: infer: prompt: "Give the strategic angle on · ${{ const.topic }}" max_tokens: 512 cost: infer: prompt: "Give the cost angle on · ${{ const.topic }}" max_tokens: 512 risk: infer: prompt: "Give the risk angle on · ${{ const.topic }}" max_tokens: 512 # The merge. `with:` does two jobs at once: it aliases the upstream outputs # to short local names, and — because a binding IS a dependency — it is what # puts this task in wave 2. Bind three tasks, wait for three tasks. synthesize: with: a: ${{ tasks.angle.output }} c: ${{ tasks.cost.output }} r: ${{ tasks.risk.output }} infer: prompt: | Synthesize one recommendation from three analyses. Strategy · ${{ with.a }} Cost · ${{ with.c }} Risk · ${{ with.r }} max_tokens: 1024# The return value · read it with `--output json` (see 01).outputs: recommendation: ${{ tasks.synthesize.output }}nika-spec@6ac29351a · sha256 4ce21f64ba0e40ac…