<Parallel />
<Parallel /> is AML’s explicit concurrency boundary for text-producing branches. It starts each branch through
component-local evaluate(), waits for all branches and their
cleanup, then contributes successful text in authored order.
import { Agent, AmlRuntime, Block, Parallel } from "@aml-jsx/sdk"
function CorrectnessLane() { return <Agent>Review correctness.</Agent>}
function SecurityLane() { return <Agent>Review security.</Agent>}
const result = await new AmlRuntime({ agentProvider }).evaluate( <Agent system="Synthesize only the supplied reviews."> <Parallel> <Block tag="correctness-review"> <CorrectnessLane /> </Block> <Block tag="security-review"> <SecurityLane /> </Block> </Parallel> </Agent>)The two lanes may finish in either order. The parent Agent starts only after both settle and receives their text in the
authored CorrectnessLane, SecurityLane order.
| Prop | Type | Default | Meaning |
|---|---|---|---|
children | AmlRenderable | empty | Independent branches evaluated concurrently. |
<Parallel> has no concurrency, retry, error callback, quorum, partial-result, or fail-fast cancellation prop.
maxConcurrentAgents remains the single limit for active Agent provider
calls in the evaluation domain.
Branches and ordering
Section titled “Branches and ordering”Each immediate child is one branch. Child arrays are recursively flattened so mapped workflows behave naturally:
<Parallel> {reviewKinds.map(kind => ( <ReviewLane kind={kind} /> ))}</Parallel>null, undefined, and booleans contribute no branch. A Fragment remains one branch, and the values inside it keep
ordinary sequential semantics:
<Parallel> <> lane-a: <Agent>Run lane A.</Agent> </> <> lane-b: <Agent>Run lane B.</Agent> </></Parallel>Branch output is isolated while work is active. Completion order never changes the rendered result order, and AML does not insert separators between branch strings. Use <Block /> when each branch should remain a distinct section:
<Parallel> {reviewKinds.map(kind => ( <Block tag={`${kind} review`}> ## {kind} review <Agent>Review {kind}.</Agent> </Block> ))}</Parallel>Without those Blocks, the first Agent’s final character and the next heading may be adjacent in the parent prompt.
Structured branch output
Section titled “Structured branch output”An Agent-owned schema remains valid inside a branch. Its
validated value contributes canonical JSON text like any other nested Agent result:
<Parallel> <Agent schema={LaneResult}>Review correctness.</Agent> <Agent schema={LaneResult}>Review security.</Agent></Parallel><Parallel> itself is a text-composition boundary. Do not pass a schema to evaluate(<Parallel>...</Parallel>, schema)
to collect several typed results. Use Promise.all([evaluate(branch, schema), ...]) in component code when JavaScript
needs named or schema-inferred branch values.
Failure semantics
Section titled “Failure semantics”One or more rejected branches produce the same exported ParallelError. Its failures array preserves authored branch
order and contains the zero-based branch index plus that branch’s original rejection:
import { ParallelError } from "@aml-jsx/sdk"
try { await runtime.evaluate(<Review />)} catch (error) { if (error instanceof ParallelError) { for (const failure of error.failures) { console.error(`Branch ${failure.branchIndex + 1} failed`, failure.cause) } }}<Parallel> uses wait-for-all semantics. It does not throw as soon as the first branch rejects, because enclosing
Sandbox and Workspace resources must remain available until every started branch completes cleanup. Caller cancellation
still propagates through the evaluation signal: active providers receive it, queued Agents do not start, and the boundary
waits for their resulting evaluations to settle.
Placement and descriptor isolation
Section titled “Placement and descriptor isolation”<Parallel> may appear wherever ordinary component text is valid, including inside an Agent, Sandbox, or Workspace. It
inherits the active Context, Sandbox, Workspace, cancellation, budgets, tracing, and Agent scheduler.
Each branch is its own nested evaluation. Direct <System>, <Tool>, <Mcp>, <Skill>, or <FollowUp> children do not
attach to an Agent surrounding <Parallel>; put Agent-owned descriptors inside that branch’s own <Agent>.
See the runnable concurrency example,
the evaluation model, and
evaluate().