Effective communication is the foundation of collaboration. Just as human societies thrive through shared language and understanding, multi-agent systems achieve collective goals through standardized communication protocols that enable agents to coordinate, negotiate, and cooperate for the benefit of all.
Communication is the cornerstone of multi-agent systems. Without effective communication mechanisms, agents cannot coordinate their actions, share information, or collaborate to solve complex problems. Agent communication languages (ACLs) provide the standardized syntax and semantics necessary for agents to understand each other.
Unlike traditional inter-process communication, agent communication protocols must handle:
FIPA-ACL (Foundation for Intelligent Physical Agents - Agent Communication Language) is the most widely adopted standard for agent communication. Developed by FIPA in the late 1990s, it provides a comprehensive framework for agent interaction.
Every FIPA-ACL message consists of multiple parameters that define the communication act:
// FIPA-ACL Message Structure
interface FIPAMessage {
performative: string; // Type of communicative act
sender: AgentIdentifier; // Sender agent ID
receiver: AgentIdentifier[]; // One or more receivers
content: any; // Message content
language: string; // Content language (e.g., 'fipa-sl')
ontology: string; // Domain ontology
protocol: string; // Interaction protocol
conversationId: string; // Conversation identifier
replyWith: string; // Reply identifier
inReplyTo: string; // Reference to previous message
replyBy: Date; // Deadline for reply
}
// Example FIPA-ACL message
const message: FIPAMessage = {
performative: 'request',
sender: { name: 'buyer-agent-001', address: 'http://mas.example.com/buyer001' },
receiver: [{ name: 'seller-agent-042', address: 'http://mas.example.com/seller042' }],
content: {
action: 'provide-quote',
item: 'laptop',
quantity: 5,
maxPrice: 1000
},
language: 'fipa-sl',
ontology: 'ecommerce-ontology',
protocol: 'fipa-request',
conversationId: 'conv-12345',
replyWith: 'req-67890',
replyBy: new Date('2025-12-26T10:00:00Z')
};
// 弘益人間: Clear communication for mutual benefit
FIPA-ACL defines 22 standard performatives (communicative acts). The most commonly used include:
| Performative | Purpose | Example Use |
|---|---|---|
| INFORM | Share information | "Temperature is 25°C" |
| REQUEST | Ask agent to perform action | "Please send status report" |
| QUERY-IF | Ask if proposition is true | "Is task completed?" |
| PROPOSE | Make a proposal | "I can deliver for $50" |
| ACCEPT-PROPOSAL | Accept a proposal | "I accept your offer" |
| REJECT-PROPOSAL | Reject a proposal | "Price too high" |
| AGREE | Agree to perform action | "I will complete by 5pm" |
| REFUSE | Refuse to perform action | "Cannot complete request" |
| FAILURE | Report action failure | "Task failed due to error" |
| CFP | Call for proposals | "Need quotes for delivery" |
class FIPAAgent {
constructor(id) {
this.id = id;
this.messageHandler = new Map();
this.setupHandlers();
}
setupHandlers() {
// Handle different performatives
this.messageHandler.set('inform', this.handleInform.bind(this));
this.messageHandler.set('request', this.handleRequest.bind(this));
this.messageHandler.set('query-if', this.handleQuery.bind(this));
this.messageHandler.set('propose', this.handlePropose.bind(this));
this.messageHandler.set('cfp', this.handleCFP.bind(this));
}
async sendInform(receiver, content) {
return this.sendMessage({
performative: 'inform',
sender: this.id,
receiver: [receiver],
content: content,
language: 'fipa-sl'
});
}
async sendRequest(receiver, action) {
return this.sendMessage({
performative: 'request',
sender: this.id,
receiver: [receiver],
content: { action: action },
protocol: 'fipa-request',
conversationId: this.generateConversationId()
});
}
handleInform(message) {
console.log(`Received information: ${JSON.stringify(message.content)}`);
this.updateBeliefs(message.content);
}
async handleRequest(message) {
const canDo = await this.canPerformAction(message.content.action);
if (canDo) {
await this.sendMessage({
performative: 'agree',
sender: this.id,
receiver: [message.sender],
inReplyTo: message.replyWith,
content: { action: message.content.action }
});
const result = await this.performAction(message.content.action);
await this.sendMessage({
performative: result.success ? 'inform' : 'failure',
sender: this.id,
receiver: [message.sender],
content: result
});
} else {
await this.sendMessage({
performative: 'refuse',
sender: this.id,
receiver: [message.sender],
inReplyTo: message.replyWith,
content: { reason: 'Cannot perform requested action' }
});
}
}
async handleCFP(message) {
// Call for proposals - evaluate and respond with proposal
const proposal = await this.generateProposal(message.content);
if (proposal) {
await this.sendMessage({
performative: 'propose',
sender: this.id,
receiver: [message.sender],
inReplyTo: message.replyWith,
content: proposal
});
}
}
}
// 弘益人間: Agents communicate to coordinate for collective benefit
KQML (Knowledge Query and Manipulation Language) predates FIPA-ACL and focuses on knowledge sharing between agents. While less common today, it influenced the development of FIPA-ACL.
KQML defines performatives focused on knowledge operations:
// KQML message example
class KQMLMessage {
constructor(performative, sender, receiver, content) {
this.performative = performative;
this.sender = sender;
this.receiver = receiver;
this.content = content;
this.language = 'KIF'; // Knowledge Interchange Format
this.ontology = null;
}
toString() {
return `(${this.performative}
:sender ${this.sender}
:receiver ${this.receiver}
:language ${this.language}
:content "${this.content}")`;
}
}
// Example: Ask if temperature exceeds threshold
const askIfMsg = new KQMLMessage(
'ask-if',
'monitor-agent',
'sensor-agent-01',
'(> temperature 30)'
);
// Example: Tell current temperature
const tellMsg = new KQMLMessage(
'tell',
'sensor-agent-01',
'monitor-agent',
'(= temperature 25)'
);
Agent communication requires reliable message transport mechanisms. The WIA-AI-016 standard supports multiple transport protocols:
RESTful HTTP APIs provide a simple, widely-supported transport mechanism for agent messages. Agents expose endpoints for receiving messages and use HTTP POST to send messages.
// HTTP-based agent message transport
class HTTPAgentTransport {
constructor(agentId, port) {
this.agentId = agentId;
this.port = port;
this.endpoint = `http://localhost:${port}/messages`;
}
// Send message via HTTP POST
async send(message) {
const response = await fetch(this.endpoint, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(message)
});
return response.json();
}
// Receive messages via HTTP server
startServer(messageHandler) {
const express = require('express');
const app = express();
app.use(express.json());
app.post('/messages', async (req, res) => {
const message = req.body;
const response = await messageHandler(message);
res.json(response);
});
app.listen(this.port, () => {
console.log(`Agent ${this.agentId} listening on port ${this.port}`);
});
}
}
// 弘益人間: Open communication channels for all agents
WebSocket provides bidirectional, full-duplex communication ideal for real-time agent interactions. It reduces latency and overhead compared to HTTP polling.
// WebSocket agent communication
class WebSocketAgentTransport {
constructor(agentId, url) {
this.agentId = agentId;
this.ws = new WebSocket(url);
this.messageQueue = [];
this.handlers = new Map();
this.ws.onopen = () => {
console.log(`Agent ${agentId} connected`);
this.flushQueue();
};
this.ws.onmessage = (event) => {
const message = JSON.parse(event.data);
this.handleMessage(message);
};
}
send(message) {
if (this.ws.readyState === WebSocket.OPEN) {
this.ws.send(JSON.stringify(message));
} else {
this.messageQueue.push(message);
}
}
flushQueue() {
while (this.messageQueue.length > 0) {
const message = this.messageQueue.shift();
this.send(message);
}
}
onMessage(performative, handler) {
this.handlers.set(performative, handler);
}
handleMessage(message) {
const handler = this.handlers.get(message.performative);
if (handler) {
handler(message);
}
}
}
For large-scale systems, message queue systems like RabbitMQ, Apache Kafka, or MQTT provide reliable, scalable message delivery with features like guaranteed delivery, message persistence, and pub/sub patterns.
Many agent interactions require multiple message exchanges following structured patterns called conversation protocols or interaction protocols.
The FIPA Request protocol defines a simple interaction where one agent requests another to perform an action:
The Contract Net Protocol enables task allocation through bidding:
// Contract Net Protocol implementation
class ContractNetManager {
async allocateTask(task, contractors) {
// Step 1: Send CFP to all contractors
const cfp = {
performative: 'cfp',
content: {
task: task,
deadline: Date.now() + 3600000, // 1 hour
requirements: task.requirements
},
conversationId: this.generateConversationId(),
replyBy: new Date(Date.now() + 300000) // 5 min for proposals
};
const proposals = await this.broadcast(contractors, cfp);
// Step 2: Evaluate proposals
const bestProposal = this.evaluateProposals(
proposals.filter(p => p.performative === 'propose')
);
if (!bestProposal) {
console.log('No suitable proposals received');
return null;
}
// Step 3: Accept best proposal
await this.send(bestProposal.sender, {
performative: 'accept-proposal',
inReplyTo: bestProposal.replyWith,
conversationId: cfp.conversationId
});
// Step 4: Reject other proposals
for (const proposal of proposals) {
if (proposal.sender !== bestProposal.sender &&
proposal.performative === 'propose') {
await this.send(proposal.sender, {
performative: 'reject-proposal',
inReplyTo: proposal.replyWith,
conversationId: cfp.conversationId
});
}
}
// Step 5: Wait for task completion
return this.waitForCompletion(bestProposal.sender, cfp.conversationId);
}
evaluateProposals(proposals) {
return proposals.reduce((best, current) => {
if (!best) return current;
const currentScore = this.scoreProposal(current);
const bestScore = this.scoreProposal(best);
return currentScore > bestScore ? current : best;
}, null);
}
scoreProposal(proposal) {
const content = proposal.content;
let score = 0;
// Lower cost is better
score += (1000 - content.cost) / 10;
// Earlier delivery is better
const timeScore = (content.deliveryTime - Date.now()) / 3600000;
score += Math.max(0, 100 - timeScore);
// Higher quality is better
score += content.quality * 10;
return score;
}
}
// 弘益人間: Fair task allocation benefiting all participants
Various auction mechanisms can be implemented as conversation protocols:
For agents to truly understand each other, they must share a common ontology—a formal specification of concepts, relationships, and constraints in a domain.
// Simple ontology definition
const eCommerceOntology = {
concepts: {
Product: {
properties: ['name', 'price', 'category', 'manufacturer'],
relationships: ['hasReview', 'inCategory']
},
Order: {
properties: ['orderId', 'totalAmount', 'status', 'timestamp'],
relationships: ['containsProduct', 'placedBy', 'deliveredTo']
},
Customer: {
properties: ['customerId', 'name', 'email', 'address'],
relationships: ['placed', 'reviewed']
}
},
relationships: {
hasReview: { domain: 'Product', range: 'Review' },
inCategory: { domain: 'Product', range: 'Category' },
containsProduct: { domain: 'Order', range: 'Product' },
placedBy: { domain: 'Order', range: 'Customer' }
}
};
// Using ontology for semantic understanding
class SemanticAgent {
constructor(ontology) {
this.ontology = ontology;
}
validateMessage(message) {
const concept = message.content.concept;
if (!this.ontology.concepts[concept]) {
throw new Error(`Unknown concept: ${concept}`);
}
const requiredProps = this.ontology.concepts[concept].properties;
const providedProps = Object.keys(message.content.data);
return requiredProps.every(prop => providedProps.includes(prop));
}
interpretMessage(message) {
if (!this.validateMessage(message)) {
return null;
}
return {
concept: message.content.concept,
data: message.content.data,
semantics: this.ontology.concepts[message.content.concept]
};
}
}
Secure communication is critical in multi-agent systems, especially in open environments where malicious agents may exist.
Agents must verify the identity of communication partners using digital certificates, API keys, or token-based authentication.
Message content should be encrypted to prevent eavesdropping. TLS/SSL for HTTP and encryption layers for message queues provide transport security.
Digital signatures ensure messages haven't been tampered with during transmission.
// Secure agent communication
class SecureAgent {
constructor(agentId, privateKey, publicKey) {
this.agentId = agentId;
this.privateKey = privateKey;
this.publicKey = publicKey;
this.trustedAgents = new Map();
}
signMessage(message) {
const crypto = require('crypto');
const sign = crypto.createSign('SHA256');
sign.update(JSON.stringify(message));
const signature = sign.sign(this.privateKey, 'hex');
return {
...message,
signature: signature,
senderPublicKey: this.publicKey
};
}
verifyMessage(message) {
const crypto = require('crypto');
const verify = crypto.createVerify('SHA256');
const { signature, senderPublicKey, ...content } = message;
verify.update(JSON.stringify(content));
return verify.verify(senderPublicKey, signature, 'hex');
}
encryptMessage(message, recipientPublicKey) {
const crypto = require('crypto');
const encrypted = crypto.publicEncrypt(
recipientPublicKey,
Buffer.from(JSON.stringify(message))
);
return {
encrypted: encrypted.toString('hex'),
sender: this.agentId
};
}
decryptMessage(encryptedMessage) {
const crypto = require('crypto');
const decrypted = crypto.privateDecrypt(
this.privateKey,
Buffer.from(encryptedMessage.encrypted, 'hex')
);
return JSON.parse(decrypted.toString());
}
}
// 弘益人間: Secure communication protecting all participants
Efficient communication is essential for scalable multi-agent systems: