Coordination is the art of harmonizing individual actions toward collective goals. Like an orchestra where each musician plays their part in perfect synchrony, multi-agent systems achieve remarkable outcomes through sophisticated coordination mechanisms that ensure agents work together effectively for the benefit of all.
In multi-agent systems, coordination addresses the challenge of managing interdependencies between agents' activities. Without coordination, agents might work at cross-purposes, duplicate efforts, or create conflicts that prevent the system from achieving its goals.
Coordination becomes necessary when:
A central coordinator agent manages all coordination decisions. This approach provides global optimization but creates a single point of failure and scalability bottleneck.
class CentralCoordinator {
constructor() {
this.agents = new Map();
this.tasks = [];
this.schedule = [];
}
registerAgent(agent) {
this.agents.set(agent.id, {
agent: agent,
capabilities: agent.getCapabilities(),
currentLoad: 0,
status: 'available'
});
}
allocateTasks(tasks) {
// Central coordinator makes all allocation decisions
const allocation = new Map();
for (const task of tasks) {
const bestAgent = this.findBestAgent(task);
if (bestAgent) {
allocation.set(task.id, bestAgent.id);
bestAgent.currentLoad += task.estimatedEffort;
}
}
return this.executeAllocation(allocation);
}
findBestAgent(task) {
let best = null;
let bestScore = -Infinity;
for (const [id, agentInfo] of this.agents) {
if (!agentInfo.agent.canPerform(task)) continue;
const score = this.scoreAgent(agentInfo, task);
if (score > bestScore) {
bestScore = score;
best = agentInfo;
}
}
return best;
}
scoreAgent(agentInfo, task) {
// Score based on capability match, current load, and availability
const capabilityScore = this.matchCapabilities(
agentInfo.capabilities,
task.requirements
);
const loadScore = 100 - agentInfo.currentLoad;
return capabilityScore * 0.7 + loadScore * 0.3;
}
}
// 弘益人間: Central coordination for global optimization
Agents coordinate through peer-to-peer interactions without a central authority. This provides better scalability and robustness but may not achieve global optimization.
class DecentralizedAgent {
constructor(id) {
this.id = id;
this.neighbors = [];
this.state = { tasks: [], resources: {} };
}
async coordinateWithNeighbors(task) {
// Decentralized coordination through local interactions
const proposals = [];
for (const neighbor of this.neighbors) {
const proposal = await this.negotiateWithNeighbor(neighbor, task);
if (proposal) proposals.push(proposal);
}
return this.selectBestProposal(proposals);
}
async negotiateWithNeighbor(neighbor, task) {
// Peer-to-peer negotiation
const canHelp = await neighbor.canAssist(task);
if (canHelp) {
const cost = await neighbor.calculateCost(task);
return { neighborId: neighbor.id, cost: cost };
}
return null;
}
// Consensus through local voting
async reachLocalConsensus(decision) {
const votes = await Promise.all(
this.neighbors.map(n => n.vote(decision))
);
const favor = votes.filter(v => v === true).length;
const total = votes.length;
return favor / total > 0.5; // Majority consensus
}
}
// 弘益人間: Decentralized coordination empowering all agents
Negotiation allows agents to reach agreements through iterative proposal and counter-proposal exchanges.
Agents make successive concessions until agreement is reached or negotiations fail.
class NegotiatingAgent {
constructor(id, initialPosition, minAcceptable) {
this.id = id;
this.position = initialPosition;
this.minAcceptable = minAcceptable;
this.concessionRate = 0.1;
}
async negotiate(otherAgent, issue) {
let round = 0;
const maxRounds = 10;
while (round < maxRounds) {
// Make proposal
const myProposal = this.makeProposal(issue);
const theirProposal = await otherAgent.receiveProposal(myProposal);
// Check if proposals overlap (agreement zone)
if (this.isAcceptable(theirProposal)) {
return this.formAgreement(myProposal, theirProposal);
}
// Make concession
this.makeConcession(theirProposal);
round++;
}
return null; // Negotiation failed
}
makeProposal(issue) {
return {
agent: this.id,
issue: issue,
value: this.position,
round: this.currentRound
};
}
isAcceptable(proposal) {
return proposal.value >= this.minAcceptable;
}
makeConcession(theirProposal) {
// Move toward their position
const gap = theirProposal.value - this.position;
this.position += gap * this.concessionRate;
// Don't go below minimum
this.position = Math.max(this.position, this.minAcceptable);
}
formAgreement(myProposal, theirProposal) {
// Split the difference
return {
agents: [this.id, theirProposal.agent],
agreedValue: (myProposal.value + theirProposal.value) / 2,
timestamp: Date.now()
};
}
}
// 弘益人間: Fair negotiation benefiting all parties
Real-world negotiations often involve multiple interconnected issues. Agents can make trade-offs across issues to reach better agreements.
When agents must make collective decisions, voting mechanisms aggregate individual preferences into group decisions.
| Method | Description | Pros/Cons |
|---|---|---|
| Plurality | Option with most votes wins | Simple but can elect minority preference |
| Majority | Option with >50% votes wins | Ensures broad support, may require runoff |
| Unanimous | All agents must agree | Strong consensus, but slow and blocking |
| Weighted | Votes have different weights | Reflects expertise/stake, less democratic |
| Ranked Choice | Agents rank preferences | Captures nuanced preferences, complex |
| Borda Count | Points based on rankings | Rewards consensus choices |
class VotingSystem {
constructor(method = 'majority') {
this.method = method;
this.votes = [];
}
collectVotes(agents, proposal) {
this.votes = agents.map(agent => ({
agentId: agent.id,
vote: agent.vote(proposal),
weight: agent.getVotingWeight()
}));
}
// Majority voting
majorityVote() {
const favor = this.votes.filter(v => v.vote === true).length;
const total = this.votes.length;
return favor / total > 0.5;
}
// Weighted voting
weightedVote() {
const favorWeight = this.votes
.filter(v => v.vote === true)
.reduce((sum, v) => sum + v.weight, 0);
const totalWeight = this.votes
.reduce((sum, v) => sum + v.weight, 0);
return favorWeight / totalWeight > 0.5;
}
// Ranked choice voting
rankedChoiceVote(candidates) {
let remaining = [...candidates];
const ballots = this.votes.map(v => v.rankings);
while (remaining.length > 1) {
const counts = this.countFirstChoices(ballots, remaining);
const total = ballots.length;
// Check if anyone has majority
for (const [candidate, count] of counts.entries()) {
if (count / total > 0.5) {
return candidate;
}
}
// Eliminate candidate with fewest first-choice votes
const minCandidate = this.findMinCandidate(counts);
remaining = remaining.filter(c => c !== minCandidate);
}
return remaining[0];
}
// Borda count
bordaCount(candidates) {
const points = new Map();
candidates.forEach(c => points.set(c, 0));
for (const vote of this.votes) {
const rankings = vote.rankings;
for (let i = 0; i < rankings.length; i++) {
const candidate = rankings[i];
const pts = candidates.length - i - 1;
points.set(candidate, points.get(candidate) + pts);
}
}
return this.findMaxCandidate(points);
}
}
// 弘益人間: Democratic decision-making for collective benefit
Distributed consensus algorithms ensure agents agree on system state despite failures and network issues.
Raft is a consensus algorithm designed for understandability. It ensures that a cluster of agents agrees on a sequence of values (log entries).
class RaftAgent {
constructor(id, peers) {
this.id = id;
this.peers = peers;
this.state = 'follower'; // follower, candidate, or leader
this.currentTerm = 0;
this.votedFor = null;
this.log = [];
this.commitIndex = 0;
}
// Start election when election timeout expires
startElection() {
this.state = 'candidate';
this.currentTerm++;
this.votedFor = this.id;
let votesReceived = 1; // Vote for self
// Request votes from all peers
for (const peer of this.peers) {
const response = peer.requestVote({
term: this.currentTerm,
candidateId: this.id,
lastLogIndex: this.log.length - 1,
lastLogTerm: this.log[this.log.length - 1]?.term || 0
});
if (response.voteGranted) votesReceived++;
}
// Become leader if majority votes received
if (votesReceived > (this.peers.length + 1) / 2) {
this.becomeLeader();
} else {
this.state = 'follower';
}
}
becomeLeader() {
this.state = 'leader';
console.log(`Agent ${this.id} became leader for term ${this.currentTerm}`);
// Send heartbeats to maintain leadership
this.sendHeartbeats();
}
// Leader sends append entries (heartbeat/replication)
sendHeartbeats() {
for (const peer of this.peers) {
peer.appendEntries({
term: this.currentTerm,
leaderId: this.id,
entries: [], // Empty for heartbeat
leaderCommit: this.commitIndex
});
}
}
// Follower receives append entries
handleAppendEntries(request) {
if (request.term < this.currentTerm) {
return { success: false, term: this.currentTerm };
}
this.currentTerm = request.term;
this.state = 'follower';
// Append new entries to log
this.log.push(...request.entries);
// Update commit index
if (request.leaderCommit > this.commitIndex) {
this.commitIndex = Math.min(
request.leaderCommit,
this.log.length - 1
);
}
return { success: true, term: this.currentTerm };
}
}
// 弘益人間: Consensus ensuring system integrity for all
PBFT provides consensus even when some agents behave maliciously, as long as less than 1/3 are faulty.
Market mechanisms use economic principles to coordinate agent behavior through supply, demand, and pricing.
class Auctioneer {
constructor() {
this.auctions = new Map();
}
// English Auction (ascending price)
async englishAuction(item, startPrice, minIncrement) {
let currentBid = startPrice;
let currentWinner = null;
let bidders = this.getBidders(item);
let noBidRounds = 0;
while (noBidRounds < 3) {
const bids = [];
for (const bidder of bidders) {
const bid = await bidder.considerBid(item, currentBid);
if (bid > currentBid + minIncrement) {
bids.push({ bidder: bidder.id, amount: bid });
}
}
if (bids.length === 0) {
noBidRounds++;
} else {
noBidRounds = 0;
const highestBid = Math.max(...bids.map(b => b.amount));
currentBid = highestBid;
currentWinner = bids.find(b => b.amount === highestBid).bidder;
}
}
return { winner: currentWinner, price: currentBid };
}
// Sealed-bid (First-price)
async sealedBidAuction(item) {
const bidders = this.getBidders(item);
const bids = await Promise.all(
bidders.map(b => b.submitSealedBid(item))
);
const highestBid = Math.max(...bids.map(b => b.amount));
const winner = bids.find(b => b.amount === highestBid);
return { winner: winner.bidder, price: winner.amount };
}
// Vickrey Auction (Second-price sealed-bid)
async vickreyAuction(item) {
const bidders = this.getBidders(item);
const bids = await Promise.all(
bidders.map(b => b.submitSealedBid(item))
);
bids.sort((a, b) => b.amount - a.amount);
return {
winner: bids[0].bidder,
price: bids[1].amount // Pay second-highest price
};
}
// Dutch Auction (descending price)
async dutchAuction(item, startPrice, decrementRate) {
let currentPrice = startPrice;
const bidders = this.getBidders(item);
while (currentPrice > 0) {
for (const bidder of bidders) {
if (await bidder.acceptsPrice(item, currentPrice)) {
return { winner: bidder.id, price: currentPrice };
}
}
currentPrice -= decrementRate;
await this.sleep(100); // Time between decrements
}
return null; // No winner
}
}
// 弘益人間: Market mechanisms for efficient resource allocation
When agents create individual plans, these plans must be coordinated to avoid conflicts and exploit synergies.
class PlanCoordinator {
constructor() {
this.agents = [];
this.globalPlan = [];
}
async coordinatePlans(agentPlans) {
// Detect conflicts between plans
const conflicts = this.detectConflicts(agentPlans);
if (conflicts.length === 0) {
return this.mergePlans(agentPlans);
}
// Resolve conflicts through negotiation
for (const conflict of conflicts) {
await this.resolveConflict(conflict, agentPlans);
}
return this.mergePlans(agentPlans);
}
detectConflicts(plans) {
const conflicts = [];
for (let i = 0; i < plans.length; i++) {
for (let j = i + 1; j < plans.length; j++) {
const conflict = this.checkPlanConflict(plans[i], plans[j]);
if (conflict) {
conflicts.push({
agents: [plans[i].agentId, plans[j].agentId],
type: conflict.type,
details: conflict.details
});
}
}
}
return conflicts;
}
checkPlanConflict(plan1, plan2) {
// Check for resource conflicts
const resourceConflict = this.checkResourceConflict(plan1, plan2);
if (resourceConflict) return resourceConflict;
// Check for temporal conflicts
const temporalConflict = this.checkTemporalConflict(plan1, plan2);
if (temporalConflict) return temporalConflict;
// Check for goal conflicts
const goalConflict = this.checkGoalConflict(plan1, plan2);
if (goalConflict) return goalConflict;
return null;
}
async resolveConflict(conflict, plans) {
const [agent1, agent2] = conflict.agents;
const plan1 = plans.find(p => p.agentId === agent1);
const plan2 = plans.find(p => p.agentId === agent2);
if (conflict.type === 'resource') {
// Time-share or prioritize
await this.negotiateResourceSharing(plan1, plan2, conflict);
} else if (conflict.type === 'temporal') {
// Reschedule one plan
await this.reschedulePlan(plan1, plan2, conflict);
} else if (conflict.type === 'goal') {
// Find compromise
await this.negotiateGoals(plan1, plan2, conflict);
}
}
mergePlans(plans) {
// Create global schedule from individual plans
const merged = [];
for (const plan of plans) {
for (const action of plan.actions) {
merged.push({
agent: plan.agentId,
action: action,
startTime: action.startTime,
endTime: action.endTime,
resources: action.resources
});
}
}
// Sort by start time
merged.sort((a, b) => a.startTime - b.startTime);
return merged;
}
}
// 弘益人間: Coordinated planning for collective success
Swarm coordination enables large numbers of simple agents to achieve complex collective behaviors through local interactions.
class SwarmAgent {
constructor(id, position) {
this.id = id;
this.position = position;
this.velocity = { x: 0, y: 0 };
this.neighbors = [];
}
// Reynolds' Boids algorithm for flocking
updateVelocity(allAgents) {
const neighbors = this.findNeighbors(allAgents, 50);
const separation = this.separate(neighbors);
const alignment = this.align(neighbors);
const cohesion = this.cohere(neighbors);
// Combine behaviors with weights
this.velocity.x += separation.x * 1.5 + alignment.x * 1.0 + cohesion.x * 1.0;
this.velocity.y += separation.y * 1.5 + alignment.y * 1.0 + cohesion.y * 1.0;
// Limit speed
const speed = Math.sqrt(this.velocity.x ** 2 + this.velocity.y ** 2);
const maxSpeed = 5;
if (speed > maxSpeed) {
this.velocity.x = (this.velocity.x / speed) * maxSpeed;
this.velocity.y = (this.velocity.y / speed) * maxSpeed;
}
}
// Avoid crowding neighbors
separate(neighbors) {
const steer = { x: 0, y: 0 };
for (const neighbor of neighbors) {
const dx = this.position.x - neighbor.position.x;
const dy = this.position.y - neighbor.position.y;
const dist = Math.sqrt(dx * dx + dy * dy);
if (dist > 0 && dist < 25) {
steer.x += dx / dist;
steer.y += dy / dist;
}
}
return steer;
}
// Align with neighbors' average velocity
align(neighbors) {
if (neighbors.length === 0) return { x: 0, y: 0 };
const avgVel = neighbors.reduce(
(sum, n) => ({
x: sum.x + n.velocity.x,
y: sum.y + n.velocity.y
}),
{ x: 0, y: 0 }
);
return {
x: avgVel.x / neighbors.length - this.velocity.x,
y: avgVel.y / neighbors.length - this.velocity.y
};
}
// Move toward average position of neighbors
cohere(neighbors) {
if (neighbors.length === 0) return { x: 0, y: 0 };
const avgPos = neighbors.reduce(
(sum, n) => ({
x: sum.x + n.position.x,
y: sum.y + n.position.y
}),
{ x: 0, y: 0 }
);
return {
x: avgPos.x / neighbors.length - this.position.x,
y: avgPos.y / neighbors.length - this.position.y
};
}
}
// 弘益人間: Emergent coordination through simple local rules