Consensus
Run multiple agents and determine a winner via voting with configurable quorum.
consensus() runs multiple agents (or the same agent multiple times) in parallel and picks a winner via voting. Use it when you need reliable classification, grading, or any decision where multiple opinions reduce error.
import { consensus } from '@crux/ai'
import { agent } from '@crux/core/agent'
const decision = await consensus({
agents: [classifier, classifier, classifier],
context: { ticket: supportTicket },
extract: (result) => result.output.category,
quorum: 'majority',
})
decision.result // 'billing' (winning category)
decision.votes // { billing: 2, shipping: 1 }
decision.agreement // 0.67
decision.details // all 3 agent resultsHow it works
- All agents run in parallel (built on top of
parallel()internally) extract()pulls a vote string from each agent's result- Votes are counted — the most frequent value wins
- Quorum is validated — if not met,
ConsensusErroris thrown - Returns the winning value, vote breakdown, all results, and agreement ratio
The extract function
extract() receives each agent's AgentResult and returns a string that represents the vote:
// Extract the category field from structured output
extract: (result) => result.output.category
// Extract from nested data
extract: (result) => result.output.sentiment.label
// Custom logic
extract: (result) => result.output.score > 0.8 ? 'pass' : 'fail'Quorum options
| Value | Behavior |
|---|---|
'majority' (default) | Winner must have > 50% of votes |
'unanimous' | All agents must agree (100%) |
number | Winner must have at least this many votes |
// Require all 3 agents to agree
await consensus({ ..., quorum: 'unanimous' })
// Require at least 2 votes
await consensus({ ..., quorum: 2 })When quorum is not met, a ConsensusError is thrown with the vote breakdown:
import { ConsensusError } from '@crux/core/agent'
try {
await consensus({ ..., quorum: 'unanimous' })
} catch (err) {
if (err instanceof ConsensusError) {
console.log(err.votes) // { billing: 2, shipping: 1 }
console.log(err.quorum) // 'unanimous'
}
}Tie-breaking
When multiple values have the same count, the first encountered value wins. For deterministic tie-breaking, use a custom extract() that normalizes values.
Different agents as voters
You can use different agents (not just the same one repeated) for diverse perspectives:
const decision = await consensus({
agents: [conservativeClassifier, aggressiveClassifier, balancedClassifier],
context: { ticket: supportTicket },
extract: (result) => result.output.category,
})Devtools
In the devtools timeline, consensus compositions show the agreement ratio:
comp → consensus 3 agents
comp ← classifier 0.9s
comp ← classifier 1.1s
comp ← classifier 0.8s
comp ← consensus 3/3 ok 1.1s 67% agree