Compositions
Combine multiple agents into pipelines, parallel groups, voting consensus, or peer-to-peer swarms.
A single agent answers a single prompt. A composition combines multiple agents into a structured workflow — sequential chains, parallel fan-out, voting, or LLM-routed handoffs. All four compositions are built on the same agent abstraction, so an agent that works on its own works inside any composition.
What problem does this solve?
Most real LLM workloads aren't one-shot. You want to plan then execute, generate three drafts and pick one, fan out to specialists and merge, or let the model itself route the next step. Hand-coding these patterns leads to ad-hoc orchestration that's hard to test, hard to instrument, and hard to swap.
Crux gives you four named compositions with shared semantics — typed inputs, observable handoffs, instrumentation hooks, and onError policies. Switching from pipeline to consensus is a one-word change, not a rewrite.
When should I use which?
| Composition | Use when |
|---|---|
| Pipeline | One agent's output feeds the next. Plan → research → write. Deterministic order. |
| Parallel | Multiple agents do independent work on the same input. Fan-out to specialists, merge results. |
| Consensus | Multiple agents vote and you accept the answer if a quorum agrees. Quality-over-speed. |
| Swarm | The model itself decides who handles the next turn. Peer-to-peer triage / routing. |
When should I NOT use a composition?
- You have one agent. Don't wrap a single agent in pipeline-of-one.
- You need fully dynamic, code-driven branching that depends on application state, not LLM output. Use plain control flow.
- You want suspendable, resumable orchestration with persistence across restarts — that's Flows, not a composition.
Quick example: pipeline
import { agent, createPipeline } from '@crux/core/agent'
import { generate } from '@crux/ai'
import { openai } from '@ai-sdk/openai'
const researcher = agent({ id: 'researcher', prompt: researchPrompt })
const writer = agent({ id: 'writer', prompt: writePrompt })
const pipeline = createPipeline({ executor: (agent, opts) => generate(agent.prompt, opts) })
const result = await pipeline({
agents: [researcher, writer],
model: openai('gpt-4o'),
context: { topic: 'agentic workflows' },
})Each step's output is typed and accumulates into the context for the next step.
How this fits with the rest of Crux
- Agents are the unit you compose. An agent is a prompt + identity + optional tools and handoffs.
- Flows wrap compositions with suspend/resume semantics for long-running workflows.
- Blackboards let agents in any composition share typed state.