Agent Communication Patterns
Agent Communication Patterns define how AI agents exchange information, coordinate work, share knowledge and collaborate to complete complex tasks efficiently and reliably.
Learning Objectives
- Explain why AI agents need structured communication.
- Compare different communication patterns used in Multi-Agent Systems.
- Understand synchronous and asynchronous messaging.
- Design communication workflows for enterprise AI platforms.
- Handle conflicts, failures and coordination between agents.
- Apply communication best practices in production systems.
Why This Matters
Imagine an enterprise AI platform with ten specialized agents. One retrieves data, another analyzes it, another creates reports, another reviews compliance. If these agents cannot communicate effectively: work is duplicated, tasks are missed, results become inconsistent and the system becomes unreliable.
Communication is the foundation of successful Multi-Agent Systems.
Everyday Analogy
Imagine a hospital. Doctors, nurses, pharmacists and laboratory technicians all perform different jobs. They constantly communicate patient status, test results, medication updates and treatment plans. Without communication, patient care would quickly fail.
AI agents work the same way.
Why Communication Matters
Agents need to exchange goals, tasks, results, context, status, errors, requests and approvals. Good communication reduces unnecessary work and improves decision making.
The Communication Lifecycle
Receive Request β Assign Task β Process Work β Share Results β Validate β Merge Outputs β Respond. Every enterprise workflow follows a similar communication cycle.
Request-Response
One agent asks another for information. Research Agent β Knowledge Agent β Relevant Documents. Simple and widely used.
Publish-Subscribe
One agent publishes information. Interested agents automatically receive updates. Example: Policy Updated β Compliance Agent / Legal Agent / HR Agent. Ideal for event-driven systems.
Broadcast
One agent sends the same message to many agents. Coordinator β Research / Planning / Finance / Security. Used for parallel workflows.
Peer-to-Peer
Agents communicate directly without a central coordinator. Agent A β Agent B. Suitable for collaborative decision making.
Hierarchical Communication
Coordinator β Specialist Agents β Coordinator. The most common enterprise pattern.
Synchronous Communication
The sender waits for a response. Coordinator β Research Agent β Wait β Continue. Advantages: simple and predictable. Limitations: slower and can block workflows.
Asynchronous Communication
The sender continues working while waiting for responses. Coordinator β Research Agent β Continue Other Tasks β Receive Result Later. Advantages: better scalability and faster overall workflows. Widely used in enterprise AI platforms.
Trade-offs: Choosing a Communication Pattern
| Pattern | Coupling | Latency profile | Best for | Risk if misused |
|---|---|---|---|---|
| Request-response (sync) | Tight β caller blocks on callee | Predictable but additive across hops | Simple lookups where the caller genuinely needs the answer before continuing | Chains of blocking calls turn into multi-second latency for the end user |
| Publish-subscribe | Loose β publisher doesn't know subscribers | Non-blocking for publisher; subscriber latency varies | Broadcasting state changes (policy updates, new data) to many interested agents | Silent subscriber failures β a policy update never reaches HR agent and nobody notices |
| Broadcast | Loose β same message to a fixed set | Parallel, one round trip | Fan-out to a known, small set of specialists that must all see the same input | Wastes tokens/compute if most recipients don't need the message |
| Peer-to-peer | Tight between the pair, loose from the system's view | Fast for that pair, but no central place to trace it | Two agents in a tight collaborative loop (writer/critic) | No single place enforces policy or budget across the whole system |
| Hierarchical (via coordinator) | Tight to the coordinator, loose between peers | Extra hop through the coordinator | Enterprise systems needing centralized logging, retries, and access control | Coordinator becomes a throughput bottleneck at high agent counts |
Synchronous messaging trades throughput for simplicity: it is easy to reason about ("the coordinator waits, then continues") but every blocking call adds directly to the user-facing latency. Asynchronous messaging trades simplicity for throughput: the coordinator can fan out three research tasks and only block once, at the point where it actually needs all three results. But now it needs a mechanism (a future, a callback, a polling loop) to know when each one finishes, and a plan for what to do if one never does.
A Runnable Message-Passing Skeleton
The example below implements a minimal async message bus in Python: the shape of what a production system would build on top of Redis pub/sub, a message queue, or an in-process asyncio event bus. It demonstrates structured messages, correlation IDs, timeouts, and a fallback path when an agent never responds.
import asyncio
import time
import uuid
from dataclasses import dataclass, field
@dataclass
class AgentMessage:
sender: str
receiver: str
task: str
payload: dict
correlation_id: str = field(default_factory=lambda: str(uuid.uuid4())[:8])
timestamp: float = field(default_factory=time.time)
status: str = "pending"
class MessageBus:
"""A minimal pub/sub + request-response bus for agent messages."""
def __init__(self):
self._handlers: dict[str, callable] = {}
self._log: list[AgentMessage] = []
def register(self, agent_name: str, handler):
self._handlers[agent_name] = handler
async def send(self, message: AgentMessage, timeout: float = 3.0) -> AgentMessage:
self._log.append(message)
handler = self._handlers.get(message.receiver)
if handler is None:
message.status = "no_handler"
return message
try:
result = await asyncio.wait_for(handler(message), timeout=timeout)
message.status = "completed"
return result
except asyncio.TimeoutError:
message.status = "timeout"
return message
def trace(self, correlation_id: str) -> list[AgentMessage]:
return [m for m in self._log if m.correlation_id == correlation_id]
async def budget_agent_handler(msg: AgentMessage) -> AgentMessage:
await asyncio.sleep(0.1) # simulated lookup
approved = msg.payload["amount"] <= 5000
return AgentMessage(
sender="budget_agent", receiver=msg.sender, task="budget_check_result",
payload={"approved": approved}, correlation_id=msg.correlation_id,
)
async def flaky_supplier_agent_handler(msg: AgentMessage) -> AgentMessage:
await asyncio.sleep(5.0) # simulates a hung downstream API β will trigger the timeout
return AgentMessage(sender="supplier_agent", receiver=msg.sender, task="supplier_result",
payload={}, correlation_id=msg.correlation_id)
async def run_procurement_check(bus: MessageBus, amount: float) -> dict:
correlation_id = str(uuid.uuid4())[:8]
budget_msg = AgentMessage(sender="coordinator", receiver="budget_agent",
task="check_budget", payload={"amount": amount},
correlation_id=correlation_id)
supplier_msg = AgentMessage(sender="coordinator", receiver="supplier_agent",
task="verify_supplier", payload={"amount": amount},
correlation_id=correlation_id)
# Fan out both requests concurrently (asynchronous pattern) instead of
# waiting on one before starting the next.
budget_result, supplier_result = await asyncio.gather(
bus.send(budget_msg, timeout=2.0),
bus.send(supplier_msg, timeout=2.0),
)
if supplier_result.status == "timeout":
# Fallback path: proceed on budget alone, flag for human review,
# rather than blocking the whole workflow indefinitely.
return {"decision": "escalate_to_human", "reason": "supplier_agent timed out",
"correlation_id": correlation_id}
return {"decision": "approved" if budget_result.payload.get("approved") else "rejected",
"correlation_id": correlation_id}
async def main():
bus = MessageBus()
bus.register("budget_agent", budget_agent_handler)
bus.register("supplier_agent", flaky_supplier_agent_handler)
result = await run_procurement_check(bus, amount=1200)
print(result)
if __name__ == "__main__":
asyncio.run(main())
Run this and the supplier check times out at 2 seconds (its handler sleeps 5), producing {"decision": "escalate_to_human", ...} instead of hanging forever, exactly the timeout-then-fallback pattern that keeps one slow agent from stalling an entire workflow. The correlation ID threads through both messages, so bus.trace(correlation_id) gives you every message tied to this one procurement check, which is what AI-028's observability tooling is built on in a real deployment.
Message Components
Every message should contain sender, receiver, task, context, priority, timestamp, status and correlation ID. Structured messages improve reliability and debugging.
Shared Context
Agents often access shared information including customer profiles, project data, business policies and conversation history. Shared context reduces repeated retrieval.
Shared Memory
Agents read and update common information. Advantages: easy collaboration and reduced duplication. Challenges: version conflicts and access control.
The version-conflict problem is not hypothetical; it is the same check-then-act race condition described in the failure-modes section below, and it shows up the moment two agents can read the same value before either writes their update. Production systems address it the same way concurrent databases do: optimistic locking (write only succeeds if the value hasn't changed since you read it), a single-writer rule (only the coordinator ever writes to shared memory; specialists propose changes but don't apply them), or simply narrowing what's actually shared. A shared read-only cache of customer data causes far fewer problems than a shared mutable budget counter that multiple agents increment concurrently.
Direct Messaging
Agents exchange information directly. Advantages: clear ownership and better isolation. Challenges: more communication overhead. Enterprise platforms often combine both approaches.
Task Delegation
Coordinator Agent β Assign Task β Specialist Agent β Complete Work β Return Result. Delegation allows each agent to focus on its expertise.
Conflict Resolution
Sometimes agents disagree. Example: Finance Agent rejects an expense. Travel Policy Agent approves it. Coordinator Agent compares evidence and makes a final decision. Enterprise workflows require clear conflict resolution rules.
Error Communication
Agents should report tool failures, timeouts, missing information, permission errors and validation failures. Failures should never disappear silently.
Retry Strategies
Temporary failure β Retry. Still failing β Alternative Agent. Still failing β Human Review. Well-built systems recover automatically whenever possible.
A retry strategy needs three explicit decisions, not just "add a retry": how many attempts before giving up (a fixed cap, not infinite retries), how long to wait between attempts (fixed delay, or exponential backoff with jitter, see the retry code in AI-031), and what "giving up" actually triggers (a fallback agent, a degraded response, or an escalation to a human). Skipping any of the three tends to produce one of two failure patterns: workflows that retry forever and never surface a problem to anyone, or workflows that give up on the first transient blip and escalate far more often than necessary, burying human reviewers in noise that would have resolved itself on a second attempt.
Failure Modes in Agent Communication
- Silent subscriber failure. In a publish-subscribe setup, a "policy updated" event fires and the compliance agent's subscription handler throws an unhandled exception, but nothing retries the delivery or alerts anyone, because pub/sub systems often treat "delivered to the queue" as success, regardless of whether the subscriber actually processed it. Production systems need explicit acknowledgment and dead-letter queues, not just fire-and-forget publishing.
- Correlation ID loss across hops. A coordinator generates a correlation ID, but a specialist agent calling a third, nested agent forgets to propagate it, and now half of a workflow's trace is invisible when someone tries to debug a failure (AI-028). This is a discipline problem, not a technology problem: every message-construction helper should require a correlation ID as a parameter, not an optional field.
- Timeout mismatch. The example above uses a 2-second timeout for a task whose realistic P99 latency is 4 seconds; under real load, most requests would falsely trigger the fallback path. Timeouts need to be set from observed latency distributions (see AI-028), not guessed.
- Unbounded broadcast fan-out. A broadcast pattern sends the same expensive task to every agent "just in case one needs it," multiplying token cost by the number of agents even though only one actually acts on the message. Broadcast should be reserved for genuinely shared, cheap state changes, not task assignment.
- Shared memory race conditions. Two agents read a shared budget total, both compute "still under limit" independently, and both approve spending that jointly exceeds it. It's a classic check-then-act race condition familiar from concurrent systems, now showing up in agent architectures because it's easy to forget agents can run concurrently too.
Case study: Slack's incident-response bot handoffs
Enterprise incident-response tooling (patterns documented by companies like PagerDuty and in Atlassian's incident management guide) commonly uses a publish-subscribe backbone: an "incident declared" event publishes once, and separately-owned bots (a paging bot, a status-page bot, a stakeholder-notification bot, and a postmortem-scheduling bot) each subscribe and act independently, with no single bot needing to know the others exist. This is a deliberate trade-off: it makes the system easy to extend (add a new bot without modifying the publisher) at the cost of harder debugging when an event doesn't produce every expected downstream action, which is exactly the "silent subscriber failure" pattern above. Teams that adopt pub/sub for agent coordination generally have to also invest in explicit delivery tracking (did every subscriber acknowledge the event) to catch that failure mode, rather than assuming pub/sub's looser coupling comes for free.
Enterprise Example
An employee requests: "Create next month's project forecast." The Coordinator delegates to Planning Agent, Finance Agent, Risk Agent and Analytics Agent. Results flow to Writing Agent, then Review Agent, producing the final report. Each agent exchanges structured messages throughout the workflow.
Best Practices
Keep messages small and focused. Define clear responsibilities. Include correlation IDs. Record communication history. Design for retries. Handle failures gracefully. Protect sensitive information.
Common Mistakes
Sharing excessive context. Sending unstructured messages. Ignoring failed communications. Creating circular dependencies. Overloading coordinator agents. Logging confidential information.
Hands-On Exercise
Design communication between agents for an AI procurement assistant. Include coordinator, supplier agent, budget agent, policy agent and approval agent. Define every message exchanged.
Mini Project
Create a communication protocol for an enterprise AI platform supporting HR, finance, engineering, sales and customer support. Document message format, routing rules, retry strategy, error handling and shared memory usage. Use the trade-off table above to justify at least two different patterns you chose for different parts of the platform, and specify realistic timeout values as you would derive them from observed latency data.
Worked Example: The Handoff, Concretely
The newsroom system of AI-032, at the message level. The researcher finishes and emits:
{"from": "researcher", "to": "writer", "type": "task_handoff",
"payload": {"facts": [{"claim": "Chip sector up 4.2% this week",
"source": "market-data-api", "confidence": 0.97}],
"notes": "Focus on semiconductor rally"},
"trace_id": "rpt-2026-07-02-441"}
Everything the writer needs, nothing it shouldn't have: structured facts (not the researcher's whole context, AI-020), provenance per claim (the critic will check them, AI-022), and a trace ID stitching the whole run together for debugging (AI-028). Compare the failure mode of unstructured handoffs, pasting one agent's chat log into another, where instructions, half-thoughts, and injected content (AI-027) all travel along uninvited.
Try It Yourself
- Write the schema first: for any two-agent pair you can imagine (triage β resolver), define the handoff JSON: required fields, who fills them, what's deliberately excluded. Ten lines of schema prevent most multi-agent chaos.
- Break it on purpose: relay a task through two chatbot conversations twice, once passing your own structured summary, once pasting the raw transcript. Compare how much the second run drifts. That drift is what message protocols exist to stop.
Key Takeaways
- Communication enables successful Multi-Agent Systems.
- Different communication patterns solve different problems.
- Structured messages improve reliability.
- Shared memory and direct messaging each have advantages.
- Enterprise systems require reliable communication, retries and monitoring.
Glossary
- Request-Response
- One agent asks another and waits for a direct reply, as in Research Agent β Knowledge Agent β documents back. Simple, synchronous, and the most widely used pattern.
- Publish-Subscribe
- An agent publishes an event and all subscribed agents automatically receive it, so "policy updated" reaches the compliance, legal, and HR agents at once. Ideal for event-driven systems.
- Asynchronous Communication
- The sender keeps working while awaiting responses, receiving results later. This gives better scalability and faster workflows than synchronous waiting, at the cost of coordination complexity.
- Structured Handoff
- Passing exactly what the next agent needs and nothing more. The worked example's JSON carries facts with per-claim provenance, notes, and a trace ID, not the researcher's whole chat log. Unstructured handoffs let half-thoughts and injected content travel along uninvited. (see AI-027)
- Correlation ID
- A unique identifier (like "rpt-2026-07-02-441") stitching all messages, responses, and log entries of one run together for end-to-end tracing and debugging. (see AI-028)
- Shared Memory
- A store multiple agents read and write, holding customer profiles, project data, and intermediate results, reducing duplicated retrieval at the cost of version conflicts and access control. Enterprise platforms usually combine it with direct messaging.
- Conflict Resolution
- When agents disagree (Finance rejects, Travel Policy approves), the coordinator compares evidence and decides. Every enterprise workflow needs explicit rules for it.
- Error Communication
- Agents reporting tool failures, timeouts, and permission errors instead of silence, with retry escalation: temporary failure β retry, still failing β alternative agent, still failing β human review.
References
Diagram
Knowledge Check
7 questions