"""
Pattern 16: Message Passing Pattern
Direct point-to-point communication between agents through message channels.
Agents send and receive messages asynchronously via mailboxes/queues.
"""
from typing import Dict, Any, List, Optional
from dataclasses import dataclass, field
from datetime import datetime
from collections import deque
from langchain_core.prompts import ChatPromptTemplate
from langchain_openai import ChatOpenAI
@dataclass
class Message:
"""Message passed between agents."""
sender: str
receiver: str
content: Any
message_type: str = "default"
timestamp: datetime = field(default_factory=datetime.now)
reply_to: Optional[str] = None
class MessageQueue:
"""Message queue (mailbox) for an agent."""
def __init__(self, max_size: int = 100):
self.queue: deque = deque(maxlen=max_size)
self.processed: List[Message] = []
def enqueue(self, message: Message):
"""Add message to queue."""
self.queue.append(message)
def dequeue(self) -> Optional[Message]:
"""Get next message from queue."""
if self.queue:
msg = self.queue.popleft()
self.processed.append(msg)
return msg
return None
def peek(self) -> Optional[Message]:
"""Peek at next message without removing."""
return self.queue[0] if self.queue else None
def size(self) -> int:
"""Get queue size."""
return len(self.queue)
class MessagePassingAgent:
"""Agent with message passing capabilities."""
def __init__(self, name: str, role: str, model_name: str = "gpt-4"):
self.name = name
self.role = role
self.llm = ChatOpenAI(model=model_name, temperature=0.7)
self.mailbox = MessageQueue()
self.system: Optional['MessagePassingPattern'] = None
def send(self, receiver: str, content: Any, message_type: str = "default"):
"""Send message to another agent."""
if not self.system:
raise ValueError("Agent not connected to message passing system")
message = Message(
sender=self.name,
receiver=receiver,
content=content,
message_type=message_type
)
self.system.route_message(message)
def receive(self) -> Optional[Message]:
"""Receive next message from mailbox."""
return self.mailbox.dequeue()
def process_message(self, message: Message) -> Optional[str]:
"""Process received message using LLM."""
prompt = ChatPromptTemplate.from_messages([
("system", f"You are {self.name}, a {self.role}. "
f"Process this message and respond if needed."),
("human", f"From: {message.sender}\n"
f"Type: {message.type}\n"
f"Content: {message.content}")
])
chain = prompt | self.llm
response = chain.invoke({})
return str(response.content)
def check_messages(self) -> int:
"""Check number of pending messages."""
return self.mailbox.size()
class MessagePassingPattern:
"""
Message Passing Pattern - Asynchronous agent communication.
Agents communicate by sending messages that are queued in mailboxes.
Each agent has its own message queue for asynchronous processing.
"""
def __init__(self):
self.agents: Dict[str, MessagePassingAgent] = {}
self.message_log: List[Message] = []
def register_agent(self, agent: MessagePassingAgent):
"""Register agent with message passing system."""
self.agents[agent.name] = agent
agent.system = self
def route_message(self, message: Message):
"""Route message to recipient's mailbox."""
self.message_log.append(message)
if message.receiver in self.agents:
recipient = self.agents[message.receiver]
recipient.mailbox.enqueue(message)
else:
print(f"Warning: Recipient {message.receiver} not found")
def process_all_messages(self):
"""Process all pending messages for all agents."""
for agent in self.agents.values():
while agent.mailbox.size() > 0:
message = agent.receive()
if message:
response = agent.process_message(message)
# Send reply if needed
if response and "reply" in response.lower():
agent.send(message.sender, response, "reply")
def get_statistics(self) -> Dict[str, Any]:
"""Get messaging statistics."""
return {
agent_name: {
"pending": agent.mailbox.size(),
"processed": len(agent.mailbox.processed)
}
for agent_name, agent in self.agents.items()
}
def run(self, scenario: str) -> Dict[str, Any]:
"""Execute message passing scenario."""
return {
"pattern": "MessagePassing",
"total_agents": len(self.agents),
"total_messages": len(self.message_log),
"agents": list(self.agents.keys()),
"scenario": scenario
}
# Example usage
if __name__ == "__main__":
print("=== Message Passing Pattern Demo ===\n")
# Create system
system = MessagePassingPattern()
# Create agents
coordinator = MessagePassingAgent("Coordinator", "project coordinator")
dev1 = MessagePassingAgent("Dev1", "backend developer")
dev2 = MessagePassingAgent("Dev2", "frontend developer")
tester = MessagePassingAgent("QA", "tester")
# Register agents
for agent in [coordinator, dev1, dev2, tester]:
system.register_agent(agent)
print("1. Agents sending messages...")
coordinator.send("Dev1", "Implement user authentication API")
coordinator.send("Dev2", "Create login UI components")
coordinator.send("QA", "Prepare test cases for auth flow")
dev1.send("Dev2", "API endpoints ready at /api/auth")
dev2.send("QA", "UI components completed, ready for testing")
print(f"\n2. Message queue status:")
stats = system.get_statistics()
for agent_name, stat in stats.items():
print(f" {agent_name}: {stat['pending']} pending, {stat['processed']} processed")
print("\n3. Processing all messages...")
system.process_all_messages()
print(f"\n4. After processing:")
stats = system.get_statistics()
for agent_name, stat in stats.items():
print(f" {agent_name}: {stat['pending']} pending, {stat['processed']} processed")
# Summary
result = system.run("Team communication")
print(f"\n5. Summary:")
print(f" Agents: {result['agents']}")
print(f" Total messages: {result['total_messages']}")
print("\nā Message passing pattern enabled asynchronous agent communication!")
Agentic Architecture Pattern: Message Passing
Pattern 16: 16 Message Passing – Line-by-Line Explanation
Overview
Pattern 16: Message Passing Pattern
Direct point-to-point communication between agents through message channels. Agents send and receive messages asynchronously via mailboxes/queues.
Code Structure Analysis
File Information
- Pattern Number: 16
- Pattern Name: 16 Message Passing
- File Path:
patterns\communication\16_message_passing.py - Total Lines: 206
Detailed Code Explanation
Module Docstring
"""
Pattern 16: Message Passing Pattern
Direct point-to-point communication between agents through message channels.
Agents send and receive messages asynchronously via mailboxes/queues.
"""
Explanation: This module docstring describes the purpose and key features of the 16 Message Passing pattern.
Imports Section
from typing import Dict, Any, List, Optional
from dataclasses import dataclass, field
from datetime import datetime
from collections import deque
from langchain_core.prompts import ChatPromptTemplate
from langchain_openai import ChatOpenAI # First 20 imports shown
Explanation: The module imports necessary dependencies:
– from typing import Dict, Any, List, Optional: Type hints for better code documentation
– from dataclasses import dataclass, field: Data class decorators for clean data structures
– from datetime import datetime: Date and time utilities
– from langchain_core.prompts import ChatPromptTemplate: LangChain framework integration
– from langchain_openai import ChatOpenAI: LangChain framework integration
Classes
Message (Line 17)
Description: Message passed between agents.
MessageQueue (Line 27)
Description: Message queue (mailbox) for an agent.
Methods:
__init__ (Line 30)
def __init__(self, max_size):
"""No method docstring."""
Purpose: No method docstring.
Parameters:
– self: Instance reference
– max_size: Parameter for max_size
enqueue (Line 34)
def enqueue(self, message):
"""Add message to queue."""
Purpose: Add message to queue.
Parameters:
– self: Instance reference
– message: Parameter for message
dequeue (Line 38)
def dequeue(self):
"""Get next message from queue."""
Purpose: Get next message from queue.
Parameters:
– self: Instance reference
peek (Line 46)
def peek(self):
"""Peek at next message without removing."""
Purpose: Peek at next message without removing.
Parameters:
– self: Instance reference
size (Line 50)
def size(self):
"""Get queue size."""
Purpose: Get queue size.
Parameters:
– self: Instance reference
MessagePassingAgent (Line 55)
Description: Agent with message passing capabilities.
Methods:
__init__ (Line 58)
def __init__(self, name, role, model_name):
"""No method docstring."""
Purpose: No method docstring.
Parameters:
– self: Instance reference
– name: Identifier or label
– role: Parameter for role
– model_name: LLM model to use (e.g., “gpt-4”)
send (Line 65)
def send(self, receiver, content, message_type):
"""Send message to another agent."""
Purpose: Send message to another agent.
Parameters:
– self: Instance reference
– receiver: Parameter for receiver
– content: Parameter for content
– message_type: Parameter for message_type
receive (Line 78)
def receive(self):
"""Receive next message from mailbox."""
Purpose: Receive next message from mailbox.
Parameters:
– self: Instance reference
process_message (Line 82)
def process_message(self, message):
"""Process received message using LLM."""
Purpose: Process received message using LLM.
Parameters:
– self: Instance reference
– message: Parameter for message
check_messages (Line 96)
def check_messages(self):
"""Check number of pending messages."""
Purpose: Check number of pending messages.
Parameters:
– self: Instance reference
MessagePassingPattern (Line 101)
Description: Message Passing Pattern – Asynchronous agent communication.
Agents communicate by sending messages that are queued in mailboxes. Each agent has its own message queue for asynchronous processing.
Methods:
__init__ (Line 109)
def __init__(self):
"""No method docstring."""
Purpose: No method docstring.
Parameters:
– self: Instance reference
register_agent (Line 113)
def register_agent(self, agent):
"""Register agent with message passing system."""
Purpose: Register agent with message passing system.
Parameters:
– self: Instance reference
– agent: Parameter for agent
route_message (Line 118)
def route_message(self, message):
"""Route message to recipient's mailbox."""
Purpose: Route message to recipient’s mailbox.
Parameters:
– self: Instance reference
– message: Parameter for message
process_all_messages (Line 128)
def process_all_messages(self):
"""Process all pending messages for all agents."""
Purpose: Process all pending messages for all agents.
Parameters:
– self: Instance reference
get_statistics (Line 140)
def get_statistics(self):
"""Get messaging statistics."""
Purpose: Get messaging statistics.
Parameters:
– self: Instance reference
run (Line 150)
def run(self, scenario):
"""Execute message passing scenario."""
Purpose: Execute message passing scenario.
Parameters:
– self: Instance reference
– scenario: Parameter for scenario
Design Patterns Used
- Strategy Pattern: Different execution strategies for various scenarios
- State Pattern: Managing different states in the workflow
- Chain of Responsibility: Sequential processing through workflow nodes
- Observer Pattern: Tracking and monitoring pattern execution
- Factory Pattern: Creating instances with proper configuration
Usage Example
# Initialize the pattern
pattern = Message(name="example", model_name="gpt-4")
# Configure and execute
result = pattern.execute(data={"key": "value"})
# Check results
print(result)
Key Concepts
- LLM Integration: Uses LangChain/OpenAI for intelligent decision-making
- Workflow Orchestration: LangGraph manages execution flow through nodes
- State Management: TypedDict defines workflow state structure
- Error Handling: Comprehensive error handling and fallback mechanisms
- Extensibility: Designed for easy customization and extension
Extension Points
This pattern can be extended by: 1. Adding custom workflow nodes 2. Implementing additional validation logic 3. Integrating with external services 4. Customizing LLM prompts and responses 5. Adding monitoring and logging capabilities
Leave a Reply