Even with good memories and trust scores, one big problem remains: which memories should actually be used for this specific question?
That is the job of the arbitration layer. Think of it as a traffic cop standing between the stored memories and the AI's reasoning process.
The Problem Without Arbitration
When a question comes in, the system might pull twenty different memories that seem relevant. Without arbitration, the language model gets overwhelmed with too much information - some of it useful, some of it distracting, some of it contradicting other pieces. The model has to do all the filtering work itself, and it does this poorly.
What Arbitration Does
The arbitration layer looks at several dimensions simultaneously for each candidate memory:
Semantic similarity - how closely does this memory actually match what is being asked?
Trust score - has this memory proven reliable in past interactions?
Recency - is this still current, or has the situation likely changed?
Contradiction detection - does this conflict with other high-scoring memories being considered?
After evaluating these dimensions, the layer decides what to keep, what to ignore, and how much importance to give each remaining piece. Only after this filtering happens does the language model see the chosen memories.
Here is the actual scoring function. Each candidate gets a DebateScore breakdown before the winner is selected:
// packages/agents/src/arbitration.ts
//
// Blends four dimensions; coefficients sum to 1.0 so total stays in [0, 1].
export function scoreDebateCandidate(
result: AgentResult,
forecast?: ArbitrationRiskForecast
): DebateScore {
const memoryAlignment = Math.min(1, result.retrievedMemories.length / 5)
const coherence = result.proposal.length > 0 && result.reasoning ? 1 : 0.6
const predictedReward = forecast
? result.confidence * 0.65 + forecast.confidence * 0.35
: result.confidence
const riskPenalty = forecast
? result.riskScore * 0.55 + forecast.riskScore * 0.45
: result.riskScore
return {
coherence,
predictedReward: clamp(predictedReward),
memoryAlignment,
riskPenalty: clamp(riskPenalty),
total: clamp(
coherence * 0.25 + predictedReward * 0.3 + memoryAlignment * 0.25 + (1 - riskPenalty) * 0.2
),
}
}
export function arbitrate(results: ReadonlyArray<AgentResult>): ArbitrationDecision {
const scored = results.map((result) => ({
...result,
score: result.score ?? scoreAgentResult(result),
}))
const winner = [...scored].sort((left, right) => right.score - left.score)[0]
return {
winnerId: winner.agentId,
// NOTE: article omits winnerType field present in source: winnerType: winner.agentType,
winnerProposal: winner.proposal,
confidence: winner.confidence,
allScores: scored.map((r) => ({ agentId: r.agentId, score: r.score })),
}
}Note the memoryAlignment term: an agent that retrieved five supporting memories scores 0.25 points higher on that dimension than one that retrieved none. This directly incentivizes grounding proposals in memory rather than guessing.
Why This Matters
Without the arbitration layer, the AI would be overwhelmed with too much information. With it, the AI only listens to what actually matters for the specific question being asked.
This is the component that turns raw memory retrieval into genuine reasoning support. It is the difference between a system that has memories and a system that uses them intelligently.