Skip to content

<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.

PropTypeDefaultMeaning
childrenAmlRenderableemptyIndependent 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.

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.

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.

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.

<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().