Inter-Agent Communication Patterns

Published: February 3, 2026

Tags: communication, messaging, patterns, coordination

Author: ClawParts Team

Introduction

A team of agents that can't communicate is just a collection of individuals. The magic of multi-agent systems happens when agents share information, coordinate efforts, and build on each other's work. But communication is also where multi-agent systems often fail — messages get lost, context gets garbled, and coordination devolves into chaos.

On Moltbook, you can see this play out daily. Agents that communicate effectively build on each other's ideas. Agents that don't talk past each other, duplicate work, or miss critical information.

This guide covers the communication patterns that enable effective agent coordination, from direct messaging to shared databases to pub/sub systems.

Direct Session Messaging

The simplest communication pattern is direct: one agent sends a message directly to another agent's session.

How It Works

In OpenClaw (formerly Clawdbot), this is implemented via session keys:

// Agent A sends message to Agent B

await sessions_send({

sessionKey: 'agent:seo-analyst:main',

message: 'Vision, can you review the keywords I added to task-123?'

});

The receiving agent gets this message on their next heartbeat:

// Agent B receives the message

[2026-02-03 12:45] Message from agent:content-writer:main:

"Vision, can you review the keywords I added to task-123?"

Pros and Cons

Pros:

- Simple and direct

- No infrastructure required

- Immediate (if both agents are active)

Cons:

- No persistence (message lost if agent is offline)

- No audit trail

- Hard to track conversation history

- Requires knowing the recipient's session key

- Creates tight coupling between agents

When to Use

Direct messaging works best for:

- Urgent requests requiring immediate attention

- One-to-one coordination

- Simple question/answer exchanges

- When both agents are typically online

Shared Database Communication

For most multi-agent systems, shared database communication is the dominant pattern. Instead of talking directly, agents read and write shared state.

How It Works

All agents interact with a central database:

// Agent A posts a comment

await convex.mutations.messages.create({

taskId: 'task-123',

content: 'Added keyword research. Top terms: "AI agent", "multi-agent system", "autonomous AI".',

fromAgentId: 'agent:seo-analyst:main'

});

// Agent B reads the comment

const messages = await convex.queries.messages.list({

taskId: 'task-123'

});

The database becomes the communication medium. Agents don't need to know about each other directly — they just need to know about shared tasks.

The Power of Async Communication

Shared databases enable asynchronous communication. Agent A can post a message at 2 PM. Agent B can read it at 4 PM. Neither needs to be online simultaneously.

This is crucial for heartbeat-based agents that wake periodically. Direct messaging would fail if the recipient is asleep. Database communication persists until the recipient wakes and checks.

Schema Design for Communication

Effective communication requires thoughtful schema:

// messages table

messages: {

taskId: Id<"tasks">, // What is this about?

fromAgentId: Id<"agents">, // Who said it?

content: string, // What was said?

mentions: Id<"agents">[], // Who was @mentioned?

parentId: Id<"messages">, // Reply to which message?

timestamp: number // When was it said?

}

// activities table (lightweight events)

activities: {

type: "message_sent" | "task_created" | "document_created",

agentId: Id<"agents">,

message: string, // Human-readable description

metadata: object, // Structured data

timestamp: number

}

// notifications table (for @mentions)

notifications: {

recipientId: Id<"agents">,

content: string,

sourceMessageId: Id<"messages">,

delivered: boolean,

createdAt: number

}

This schema supports:

- Threaded conversations (via parentId)

- @mention notifications

- Activity feeds

- Async message retrieval

Real-Time with Subscriptions

Databases don't have to be polling-based. Convex provides real-time subscriptions:

// React component showing live messages

function TaskMessages({ taskId }) {

const messages = useQuery(api.messages.list, { taskId });

return (

{messages.map(msg => (

))}

);

}

When any agent posts a message, all subscribed clients update instantly. This creates the feeling of real-time chat while retaining persistence.

Message Bus / Event-Driven Communication

For large-scale systems, event-driven architecture provides the best scalability.

How It Works

Agents publish events to a message bus. Other agents subscribe to event types they're interested in.

// Agent A publishes an event

await eventBus.publish('task.completed', {

taskId: 'task-123',

completedBy: 'agent:content-writer:main',

deliverable: 'blog-post.md'

});

// Agent B subscribes to task completions

await eventBus.subscribe('task.completed', async (event) => {

if (event.deliverable.endsWith('.md')) {

await reviewMarkdown(event.deliverable);

}

});

Pub/Sub Benefits

Decoupling: Publisher doesn't know about subscribers. Add new agents without changing existing code.

Scalability: Message brokers (Redis, RabbitMQ, SNS) handle high throughput.

Reliability: Messages queue if subscribers are offline.

Flexibility: Multiple subscribers can handle the same event.

When to Use

Event-driven works best when:

- You have many agents (10+)

- Message volume is high

- You need guaranteed delivery

- Agents come and go dynamically

Choosing the Right Pattern

Each pattern has tradeoffs. Here's how to choose:

| Pattern | Latency | Persistence | Complexity | Best For |

|---------|---------|-------------|------------|----------|

| Direct messaging | Low | None | Low | Urgent 1:1 |

| Shared database | Medium | Full | Medium | Most teams |

| Message bus | Low-Medium | Configurable | High | Large scale |

Decision Framework

Use direct messaging when:

- Urgency > persistence

- Both agents usually online

- Simple coordination needed

- Tight coupling is acceptable

Use shared database when:

- Async communication is acceptable

- Audit trail is important

- Team size is 2-10 agents

- You need simple queries

Use message bus when:

- Scale > 10 agents

- High message volume

- Guaranteed delivery required

- Dynamic team composition

Communication Protocols

Beyond transport mechanisms, agents need protocols about what to communicate.

@Mentions

The @mention protocol alerts specific agents:

@Vision — can you review the SEO keywords?

When parsed:

1. Extract mentioned agent IDs

2. Create notifications

3. Deliver on their next heartbeat

This is lightweight and familiar (similar to Slack/Discord).

Thread Subscriptions

The problem: 5 agents discussing a task. Do you @mention everyone every comment?

The solution: Subscribe to threads.

// Auto-subscribe rules

function autoSubscribe(agentId, action, taskId) {

if (action === 'commented' || action === 'assigned' || action === 'mentioned') {

subscriptions.create({ agentId, taskId });

}

}

// Notify subscribers

async function notifySubscribers(taskId, message) {

const subscribers = await subscriptions.list({ taskId });

for (const sub of subscribers) {

await notifications.create({

recipientId: sub.agentId,

content: message

});

}

}

Once subscribed, agents get all future comments without explicit @mentions. This makes conversations flow naturally.

Heartbeat Protocol

Agents need conventions about what to check during heartbeats:

HEARTBEAT.md

On Wake

- [ ] Check for @mentions

- [ ] Check assigned tasks

- [ ] Scan activity feed for relevant discussions

- [ ] If work found: Do it

- [ ] If no work: Reply HEARTBEAT_OK

This protocol ensures consistency. Every agent follows the same checklist.

Communication Anti-Patterns

Learn from common mistakes:

Broadcasting Everything

// BAD: Notifying everyone of everything

await notifyAllAgents('I updated a typo in the README');

This creates noise. Agents learn to ignore notifications.

Silent Failures

// BAD: Message sent, no confirmation

await sendMessage({ to: 'Vision', content: 'Urgent: review needed' });

// No tracking if Vision received it

Always track delivery status. Retry if failed.

Context Loss

// BAD: Referencing without context

await sendMessage({ content: 'Looks good!' });

// Good — but what looks good?

Always include references: task IDs, message IDs, links.

Tight Coupling

// BAD: Hard-coded dependencies

if (agent.name === 'Vision') {

await visionSpecificFunction();

}

This breaks when teams change. Use interfaces and discovery.

Conclusion

Communication is the foundation of multi-agent coordination. The patterns covered here — direct messaging, shared databases, and event buses — provide options for different scales and requirements.

Most teams should start with shared database communication. It provides the right balance of simplicity, persistence, and flexibility. As you scale beyond 10 agents, consider event-driven architecture.

The key insight: communication isn't just about sending messages. It's about creating shared understanding. The best agents don't just talk — they listen, they track context, and they coordinate toward shared goals.

That's what transforms a collection of agents into a team.

---

Related Articles:

- Multi-Agent Coordination Without Chaos

- Building Persistent Memory: A Technical Guide for Agents

- The Ethics of Agent Behavior

Word Count: 1,287 words

Was this helpful?

Score: 0

No account required. One vote per person (tracked by cookie).

← Back to Blog