Multi-Agent Communication Protocols and Message Passing
Multi-Agent Communication Protocols and Message Passing
When multiple AI agents need to collaborate, the communication layer becomes critical. Unlike single-agent systems where reasoning happens in one context, multi-agent systems must coordinate across different agents with different knowledge, goals, and capabilities. This article explores the foundations of agent communication and the protocols that make effective collaboration possible.
Concept Introduction: Why Communication Protocols Matter
Simple Explanation
Imagine you’re working on a team where everyone speaks different languages and has different expertise. Without a common way to ask questions, share information, and coordinate tasks, chaos ensues. AI agents face the same challenge. A communication protocol is the “language” and “etiquette” agents use to work together.
Technical Detail
Multi-agent communication protocols define the syntax (message format), semantics (meaning), and pragmatics (when and how to use messages) for agent interactions. These protocols must handle:
- Content representation: How to encode knowledge, beliefs, and goals
- Speech acts: Types of messages (inform, request, propose, commit)
- Conversation patterns: Valid sequences of messages
- Error handling: What happens when agents misunderstand or fail
The protocol choice dramatically affects system complexity, flexibility, and robustness.
Historical & Theoretical Context
Origin of Agent Communication Languages
Agent communication research emerged in the 1970s from distributed artificial intelligence. Early work by Carl Hewitt on the Actor Model (1973) established message passing as a fundamental primitive for concurrent computation.
In the 1990s, DARPA’s Knowledge Sharing Effort led to two major agent communication languages:
KQML (Knowledge Query and Manipulation Language): Developed in 1993, KQML defined performatives (speech acts) like “tell,” “ask,” “reply,” and “subscribe.” It separated content language (what you’re saying) from communication language (how you’re saying it).
FIPA ACL (Foundation for Intelligent Physical Agents Agent Communication Language): Released in 1997, FIPA ACL built on KQML but provided more rigorous semantics based on speech act theory from philosophy of language.
Theoretical Foundation: Speech Act Theory
Philosopher J.L. Austin and later John Searle developed speech act theory, which recognizes that language doesn’t just describe the world—it performs actions. When an agent says “I promise to deliver this result,” it’s not just transmitting information; it’s making a commitment.
FIPA ACL’s 20+ performatives (INFORM, REQUEST, PROPOSE, ACCEPT-PROPOSAL, etc.) map directly to speech act categories: assertives (stating facts), directives (requesting actions), commissives (making commitments), and declaratives (changing world state).
Design Patterns & Architectures
Pattern 1: Request-Reply (Client-Server)
The simplest pattern: one agent requests information or action, another replies.
Agent A → REQUEST(action) → Agent B
Agent B → INFORM(result) → Agent A
Use case: Simple task delegation, information retrieval
Pattern 2: Contract Net Protocol
A manager agent broadcasts a task announcement. Multiple contractor agents bid with proposals. The manager evaluates bids and awards the contract.
Manager → CALL_FOR_PROPOSALS(task) → [Contractors]
Contractors → PROPOSE(bid) → Manager
Manager → ACCEPT_PROPOSAL → Selected Contractor
Manager → REJECT_PROPOSAL → Other Contractors
Contractor → INFORM(result) → Manager
Use case: Task allocation in multi-agent systems, resource optimization
Pattern 3: Publish-Subscribe
Agents subscribe to topics. Publishers send updates to all subscribers without knowing who they are.
Agent B → SUBSCRIBE(topic) → Broker
Agent C → SUBSCRIBE(topic) → Broker
Agent A → PUBLISH(topic, data) → Broker
Broker → INFORM(data) → Agent B, Agent C
Use case: Event-driven architectures, monitoring systems, distributed coordination
Pattern 4: Negotiation Protocols
Agents exchange proposals and counter-proposals until reaching agreement or deadlock.
Agent A → PROPOSE(offer_1) → Agent B
Agent B → REJECT_PROPOSAL + PROPOSE(counter_1) → Agent A
Agent A → PROPOSE(offer_2) → Agent B
Agent B → ACCEPT_PROPOSAL → Agent A
Both agents → COMMIT
Use case: Resource allocation, conflict resolution, collaborative planning
Practical Application: Building a Multi-Agent Task System
Let’s implement a simple multi-agent system using message passing in Python. We’ll build a research team with specialized agents that communicate via a message broker.
from dataclasses import dataclass
from typing import Literal, Any, Callable
from queue import Queue
import json
@dataclass
class Message:
"""FIPA ACL-inspired message structure"""
performative: Literal['REQUEST', 'INFORM', 'PROPOSE', 'ACCEPT', 'REJECT']
sender: str
receiver: str
content: dict[str, Any]
reply_to: str | None = None
conversation_id: str | None = None
class MessageBroker:
"""Central message router for agents"""
def __init__(self):
self.agents: dict[str, Queue] = {}
def register(self, agent_id: str) -> Queue:
"""Register an agent and return its message queue"""
self.agents[agent_id] = Queue()
return self.agents[agent_id]
def send(self, message: Message):
"""Route message to recipient"""
if message.receiver in self.agents:
self.agents[message.receiver].put(message)
elif message.receiver == "broadcast":
for agent_id, queue in self.agents.items():
if agent_id != message.sender:
queue.put(message)
class Agent:
"""Base agent with communication capabilities"""
def __init__(self, agent_id: str, broker: MessageBroker):
self.agent_id = agent_id
self.broker = broker
self.inbox = broker.register(agent_id)
self.handlers: dict[str, Callable] = {}
def send(self, performative: str, receiver: str, content: dict):
"""Send a message"""
msg = Message(
performative=performative,
sender=self.agent_id,
receiver=receiver,
content=content
)
self.broker.send(msg)
print(f"[{self.agent_id}] → [{receiver}]: {performative} - {content}")
def receive(self) -> Message | None:
"""Check for new messages"""
return None if self.inbox.empty() else self.inbox.get()
def process_messages(self):
"""Process all pending messages"""
while msg := self.receive():
self.handle_message(msg)
def handle_message(self, msg: Message):
"""Override to implement agent-specific behavior"""
print(f"[{self.agent_id}] ← [{msg.sender}]: {msg.performative}")
class ResearcherAgent(Agent):
"""Agent that can conduct research on topics"""
def __init__(self, agent_id: str, broker: MessageBroker, specialty: str):
super().__init__(agent_id, broker)
self.specialty = specialty
def handle_message(self, msg: Message):
if msg.performative == 'REQUEST' and msg.content.get('action') == 'research':
topic = msg.content['topic']
# Simulate research
result = f"Research on {topic} (specialized in {self.specialty}): " \
f"Found 3 key insights..."
self.send('INFORM', msg.sender, {'result': result})
class CoordinatorAgent(Agent):
"""Agent that coordinates multi-step research tasks"""
def __init__(self, agent_id: str, broker: MessageBroker):
super().__init__(agent_id, broker)
self.pending_tasks: dict[str, list] = {}
def request_research(self, topic: str, researchers: list[str]):
"""Delegate research to multiple specialists"""
task_id = f"task_{topic}"
self.pending_tasks[task_id] = []
for researcher in researchers:
self.send('REQUEST', researcher, {
'action': 'research',
'topic': topic,
'task_id': task_id
})
def handle_message(self, msg: Message):
if msg.performative == 'INFORM':
result = msg.content.get('result')
print(f"[{self.agent_id}] Received result: {result[:50]}...")
# Example usage
def main():
broker = MessageBroker()
# Create agents
coordinator = CoordinatorAgent("coordinator", broker)
ai_researcher = ResearcherAgent("ai_researcher", broker, "AI/ML")
systems_researcher = ResearcherAgent("systems_researcher", broker, "Distributed Systems")
# Coordinator requests research from specialists
coordinator.request_research("LLM Agent Architectures",
["ai_researcher", "systems_researcher"])
# Process messages
ai_researcher.process_messages()
systems_researcher.process_messages()
coordinator.process_messages()
if __name__ == "__main__":
main()
Integration with Modern Frameworks
Modern agent frameworks like LangGraph, CrewAI, and AutoGen abstract away low-level message passing but use similar patterns internally.
LangGraph uses a state graph where edges represent message flows between agent nodes. The framework handles message routing automatically.
CrewAI implements role-based agents with built-in communication patterns. Agents have delegation and collaboration methods that use request-reply under the hood.
AutoGen uses a conversation-oriented approach where agents exchange messages in structured chat formats, with built-in support for group chat (broadcast) and two-way conversations.
Comparisons & Tradeoffs
Synchronous vs Asynchronous Communication
Synchronous (Request-Reply): Simpler to reason about, but agents block waiting for responses. Good for simple workflows.
Asynchronous (Message Queue): More complex but enables parallelism. Agents continue working while waiting for responses. Essential for scalable systems.
Centralized vs Decentralized Routing
Centralized Broker: Single point of failure, but easier to implement features like logging, replay, and debugging.
Peer-to-Peer: More robust to failures, but harder to monitor and debug. Requires discovery mechanisms.
Structured vs Unstructured Content
Structured (FIPA ACL, JSON Schema): Enables automatic validation and tool integration, but requires upfront schema design.
Unstructured (Natural Language): Flexible and works with LLMs directly, but harder to ensure correctness. Requires LLM to interpret.
Latest Developments & Research
LLM-Based Agent Communication (2023-2025)
Recent work explores using LLMs to generate and interpret agent messages in natural language rather than formal protocols. Papers like “Communicative Agents for Software Development” (2024) show that LLM agents can coordinate complex tasks through natural language dialogue.
Advantage: Flexibility—agents can handle unexpected situations and explain their reasoning.
Challenge: Ambiguity—natural language lacks the precision of formal protocols, leading to misunderstandings.
Semantic Protocols and Ontologies
The Semantic Web community is reviving interest in shared ontologies for agent communication. Using standards like RDF and OWL, agents can communicate with shared understanding of domain concepts.
OpenAI’s Function Calling effectively creates a semantic protocol where the function schema defines both syntax and semantics. This hybrid approach (structured function calls + natural language) is becoming the de facto standard for LLM agents.
Multi-Agent Benchmarks
New benchmarks like AgentBench and CommunicativeAgents (2024-2025) evaluate how well agents coordinate through communication. Key metrics: task completion rate, number of messages, communication efficiency.
Research shows that explicit communication protocols outperform implicit coordination for complex tasks, but the gap narrows with more capable base models.
Cross-Disciplinary Insight: From Human Organizations
Multi-agent communication patterns mirror organizational structures:
- Hierarchical (Manager-Worker): Like corporate structure, efficient but less adaptive
- Market (Contract Net): Like freelance platforms, flexible but requires negotiation overhead
- Team (Peer-to-Peer): Like agile teams, collaborative but requires shared understanding
Organizational theory suggests that the optimal structure depends on task complexity and environment stability. The same holds for agent systems: use hierarchical for stable, well-defined tasks; use market-based for dynamic task allocation; use team-based for creative, unpredictable work.
Daily Challenge: Build a Multi-Agent Research System
Exercise: Extend the code example above to implement a complete research pipeline:
- Add a
WriterAgentthat receives research from multiple researchers and synthesizes a report - Implement a timeout mechanism—if a researcher doesn’t respond in time, the coordinator should request help from another agent
- Add a
PROPOSEperformative where researchers can proactively suggest related research topics - Implement conversation_id tracking so multiple concurrent research tasks don’t interfere
Thought Exercise: How would this system change if agents used natural language instead of structured messages? What would you gain? What would you lose?
References & Further Reading
Foundational Papers:
- Hewitt, C. (1973). “A Universal Modular ACTOR Formalism for Artificial Intelligence”
- FIPA ACL Specification: fipa.org/specs/fipa00061/
- Wooldridge, M. (2009). “An Introduction to MultiAgent Systems” - Chapter 7: Communication
Recent Work:
- “Communicative Agents for Software Development” (2024) - arxiv.org/abs/2307.07924
- “Multi-Agent Collaboration: Harnessing the Power of Intelligent LLM Agents” (2024)
- AutoGen Framework Documentation: microsoft.github.io/autogen
Tools & Frameworks:
- LangGraph: langchain-ai.github.io/langgraph
- CrewAI: crewai.com
- AutoGen: microsoft.github.io/autogen
Historical Context:
- Searle, J. (1969). “Speech Acts: An Essay in the Philosophy of Language”
- Genesereth, M. & Ketchpel, S. (1994). “Software Agents” - Communications of the ACM