Parallel
Run multiple agents concurrently and get typed results as a named record.
parallel() runs a named map of agents concurrently and returns all results as a typed record. Use it when agents are independent, reviewing content, analyzing from different angles, or gathering data from multiple sources.
import { parallel } from "@use-crux/ai";
import { agent } from "@use-crux/core/agent";
const result = await parallel({
id: "parallel-parallel-1",
agents: {
factCheck: factCheckerAgent,
style: styleReviewerAgent,
seo: seoAnalyzerAgent,
},
context: { content: articleDraft },
model: claude35,
});
result.results.factCheck.output; // typed from factCheckerAgent's output schema
result.results.style.output; // typed from styleReviewerAgent's output schema
result.results.seo.output; // typed from seoAnalyzerAgent's output schema
result.durationMs; // total wall-clock time (= slowest agent)How it works
- All agents start executing at the same time (
Promise.all) - Each agent receives the same
context - When all finish, results are returned as a
Record<name, AgentResult<typed>>, each result is typed from the agent's output schema - Each result is an
AgentResultwith.agentId,.output,.durationMs
Total time is the duration of the slowest agent, not the sum.
Using results
Results are returned as a named record, so you access each agent's output by name with full type safety:
const { results, durationMs } = await parallel({
id: "parallel-parallel-2",
agents: { factCheck: factCheckerAgent, style: styleReviewerAgent },
context: { content: draft },
model,
});
const approved =
results.factCheck.output.score > 0.8 && results.style.output.score > 0.7;
const feedback = [
...results.factCheck.output.issues,
...results.style.output.suggestions,
];Error handling
By default, parallel() uses fail-fast semantics, if any agent throws, the entire composition fails immediately.
For best-effort execution, use onError: 'continue':
const result = await parallel({
id: "parallel-parallel-3",
agents: { a: agentA, b: agentB },
context: { content: draft },
model,
onError: "continue",
});
// result.results contains successful agents' results
// result.settled contains discriminated results for all agents:
if (result.settled.a.status === "success") {
// result.settled.a.value is AgentResult
}
if (result.settled.b.status === "error") {
// result.settled.b.error is Error
}In continue mode, result.settled contains a discriminated union for each agent:
{ status: 'success', value: AgentResult }: agent succeeded{ status: 'error', error: Error }: agent failed
Fallback integration
Per-agent model fallbacks work naturally. Each agent's model can be wrapped with fallback():
import { fallback } from "@use-crux/core";
const reviewer = agent({
id: "reviewer",
prompt: reviewPrompt,
model: fallback([claude35, gpt4]), // try Claude first, fall back to GPT-4
});The composition's onError only triggers after all model fallbacks are exhausted.
Devtools
In the devtools timeline, parallel compositions appear as:
comp → parallel 3 agents
comp ← reviewer 1.2s
comp ← factCheck 0.9s
comp ← seo 1.8s
comp ← parallel 3/3 ok 1.8s