Skip to content
rfml-moe-hub

Core component · 03

Consensus arbitration

When two or more experts run, they return competing proposals. Arbitration is the protocol that folds those proposals into one committed result - deterministically, with a recorded support level and a list of dissenters, so every decision can be explained and replayed.

The proposal contract

Each engaged expert returns a Proposal. Beyond the answer itself, a proposal carries the metadata arbitration needs: self-reported confidence, the route weight the gate assigned it, and a stable digest used to group identical answers. An expert's voting power is its route weight times its confidence - the gate's trust, scaled by the expert's own.

proposal.pypython
# A Proposal is one expert's answer plus everything arbitration needs# to weigh, compare, and audit it.from dataclasses import dataclass, fieldfrom typing import Any@dataclass(frozen=True)class Proposal:    expert_id: str    payload: Any            # the actual answer (text, patch, tool call, ...)    confidence: float       # expert's self-reported certainty, 0..1    route_weight: float     # gate weight carried over from selection    cost: float             # tokens / wall-clock consumed    digest: str             # stable hash of payload, used for grouping    @property    def vote(self) -> float:        # an expert's voting power blends how the gate ranked it        # with how sure it is of its own answer.        return self.route_weight * self.confidence
Proposal
FieldTypeDescription
payloadAnyThe expert's actual answer - text, a patch, a tool call.
confidencefloatSelf-reported certainty in 0..1.
route_weightfloatNormalized gate weight carried over from selection.
digeststrStable hash of the payload; equal digests are treated as the same answer.
votefloatDerived voting power: route_weight × confidence.

Arbitration protocols

The protocol is declared at configuration time, never inferred from the proposals. Four ship in the box; each implements the same arbitrate(proposals) -> Decision interface.

weighted-quorum

Weighted quorum

Group identical answers, sum each group's voting power (route weight × confidence), and commit the heaviest group only if it clears the quorum threshold. The default - robust when experts can genuinely agree.

best for: factual answers, classification, tool-call selection

ranked-runoff

Ranked runoff

Each expert returns a ranked list rather than a single answer. The arbiter runs instant-runoff rounds, eliminating the lowest until one option holds a majority. Avoids splitting the vote across near-duplicate answers.

best for: ranked recommendations, candidate shortlists

synthesis

Synthesis

No single proposal wins; a designated synthesizer expert receives all proposals (weighted) and produces a merged answer. The merge step itself is logged as a proposal so the result stays auditable.

best for: long-form drafting, multi-part plans

first-quorum

First-to-quorum

Streaming variant: commit as soon as arriving proposals cross the quorum, cancelling the still-running experts. Trades a little accuracy for tail-latency wins.

best for: latency-critical, redundant experts

Weighted-quorum reference

The default protocol, in full. It groups proposals by digest, sums voting power per group, and commits the heaviest group only if it clears quorum. Tie-breaks are deterministic: highest single vote, then lexical expert id - so the same proposals always commit the same answer.

arbiter.pypython
# Arbiter: a set of proposals -> one committed Decision.from dataclasses import dataclassfrom collections import defaultdictclass UnderQuorum(Exception):    """Raised when surviving proposals can't meet the required quorum."""@dataclass(frozen=True)class Decision:    consensus: object    support: float          # fraction of total vote behind the winner    engaged: list[str]    dissenting: list[str]    protocol: str@dataclassclass WeightedQuorumArbiter:    quorum: float = 0.66    # winner must hold >= this share of total vote    def arbitrate(self, proposals: list[Proposal]) -> Decision:        if not proposals:            raise UnderQuorum("no proposals survived dispatch")        # group identical answers by digest, sum their voting power.        groups: dict[str, list[Proposal]] = defaultdict(list)        for p in proposals:            groups[p.digest].append(p)        total = sum(p.vote for p in proposals)        ranked = sorted(            groups.values(),            key=lambda g: (sum(p.vote for p in g), _tiebreak(g)),            reverse=True,        )        winner = ranked[0]        support = sum(p.vote for p in winner) / total        if support < self.quorum:            raise UnderQuorum(f"top answer held {support:.0%} < {self.quorum:.0%}")        dissent = [p.expert_id for g in ranked[1:] for p in g]        return Decision(            consensus=winner[0].payload,            support=support,            engaged=[p.expert_id for p in proposals],            dissenting=dissent,            protocol="weighted-quorum",        )def _tiebreak(group: list[Proposal]) -> tuple:    # deterministic: highest single vote, then lexical expert id.    top = max(group, key=lambda p: p.vote)    return (top.vote, top.expert_id)

Go data-plane arbiter

The production arbiter is the same algorithm in Go, with the identical tie-break ordering so a result never diverges between planes.

arbiter.gogo
// Go data-plane arbiter mirrors the reference tie-break exactly so a// dispatch commits the same answer in either plane.package arbiterimport "sort"type Decision struct {    Consensus any    Support   float64    Protocol  string}func WeightedQuorum(props []Proposal, quorum float64) (Decision, error) {    if len(props) == 0 {        return Decision{}, ErrUnderQuorum    }    groups := map[string][]Proposal{}    for _, p := range props {        groups[p.Digest] = append(groups[p.Digest], p)    }    type bucket struct {        digest string        vote   float64        top    Proposal    }    var bs []bucket    var total float64    for d, g := range groups {        var v float64        top := g[0]        for _, p := range g {            v += p.Vote()            if p.Vote() > top.Vote() {                top = p            }        }        total += v        bs = append(bs, bucket{d, v, top})    }    sort.Slice(bs, func(i, j int) bool {        if bs[i].vote != bs[j].vote {            return bs[i].vote > bs[j].vote        }        return bs[i].top.ExpertID < bs[j].top.ExpertID // stable tie-break    })    support := bs[0].vote / total    if support < quorum {        return Decision{}, ErrUnderQuorum    }    return Decision{Consensus: bs[0].top.Payload, Support: support,        Protocol: "weighted-quorum"}, nil}

Under-quorum fails loud

If the heaviest group can't reach quorum - because experts disagreed or too many dropped against their budget - the arbiter raises UnderQuorum instead of committing a weak majority. Handle it by escalating, retrying with a wider plan, or falling back to a single trusted expert.

Acting on a decision

A Decision reports its support - the share of total vote behind the winner - so callers can treat strong and weak consensus differently. Escalating a weak decision into a Peer-Consult session is a common pattern.

commit.pypython
from moe_hub import Arbiter# protocol is declared, never inferred from the proposals.arbiter = Arbiter(protocol="weighted-quorum", quorum=0.66)decision = arbiter.arbitrate(session.collect())if decision.support >= 0.9:    commit(decision.consensus)            # strong agreementelse:    escalate(decision, to="peer-consult") # weak: ask for a human or peer pass