Skip to main content
<Parallel> groups its children and executes them concurrently. All children start at the same time (subject to the concurrency limit) rather than waiting for the previous child to complete.

Import

import { Parallel } from "smithers-orchestrator";

Props

PropTypeDefaultDescription
maxConcurrencynumberInfinityMaximum number of child tasks that can run simultaneously. When the limit is reached, remaining tasks wait until a running task completes before starting.
skipIfbooleanfalseWhen true, the entire parallel group and all its children are skipped. The component returns null and no child tasks are mounted.
childrenReactNodeundefinedThe tasks and control-flow components to execute concurrently.

Basic usage

<Workflow name="checks">
  <Parallel>
    <Task id="lint" output={outputs.lint}>
      {{ errors: 0 }}
    </Task>
    <Task id="typecheck" output={outputs.typecheck}>
      {{ passed: true }}
    </Task>
    <Task id="test" output={outputs.test}>
      {{ passed: true }}
    </Task>
  </Parallel>
</Workflow>
All three tasks — lint, typecheck, and test — start at the same time and run concurrently.

Limiting concurrency

Use maxConcurrency to control how many tasks run simultaneously. This is useful when tasks consume shared resources (API rate limits, database connections, CPU) and you want to avoid overloading them.
<Parallel maxConcurrency={2}>
  <Task id="analyze-repo-1" output="analyzeRepo1" agent={analyst}>
    Analyze repository alpha.
  </Task>
  <Task id="analyze-repo-2" output="analyzeRepo2" agent={analyst}>
    Analyze repository beta.
  </Task>
  <Task id="analyze-repo-3" output="analyzeRepo3" agent={analyst}>
    Analyze repository gamma.
  </Task>
  <Task id="analyze-repo-4" output="analyzeRepo4" agent={analyst}>
    Analyze repository delta.
  </Task>
</Parallel>
With maxConcurrency={2}, at most two agent calls run at the same time. As each completes, the next queued task starts.

Combining with Sequence

<Parallel> and <Sequence> compose naturally. You can nest sequential chains inside a parallel group:
<Workflow name="ci">
  <Parallel maxConcurrency={3}>
    <Sequence>
      <Task id="build-web" output="buildWeb">{{ ok: true }}</Task>
      <Task id="deploy-web" output="deployWeb">{{ ok: true }}</Task>
    </Sequence>
    <Sequence>
      <Task id="build-api" output="buildApi">{{ ok: true }}</Task>
      <Task id="deploy-api" output="deployApi">{{ ok: true }}</Task>
    </Sequence>
  </Parallel>
</Workflow>
The two <Sequence> groups run in parallel. Within each group, tasks run sequentially. deploy-web waits for build-web, but build-api does not wait for build-web.

Conditional skipping

<Parallel skipIf={!ctx.input.runChecks}>
  <Task id="lint" output="lint">{{ errors: 0 }}</Task>
  <Task id="test" output="test">{{ passed: true }}</Task>
</Parallel>
When skipIf is true, the component returns null and none of the child tasks are included in the execution plan.

Rendering

Internally, <Parallel> renders as a <smithers:parallel> host element (or null when skipped). Each child task within the group receives a parallelGroupId and parallelMaxConcurrency in its task descriptor, which the scheduler uses to manage concurrent execution.

Notes

  • When maxConcurrency is omitted or set to Infinity, all children start at the same time with no limit.
  • The parallel group completes when all children have finished (or failed, if continueOnFail is set on individual tasks).
  • <Parallel> can be nested inside <Sequence>, <Branch>, <Ralph>, or another <Parallel>.
  • An empty <Parallel> (no children) is valid and completes immediately.