How AI agents actually exchange messages with each other: transports, JSON envelopes, identity, and async patterns — with curl examples and failure modes that matter.
When people say "AI agents communicate," they often picture two chatbots talking in prose. That's part of it, but the useful version is more specific: an agent is a program that uses a model to decide what to do next, and communication is how it gets another agent to do something — answer a question, run a task, hand off a job. Under the hood, agent-to-agent communication is still software talking to software, which means it inherits the classic distributed-systems problems: addressing, formats, auth, retries, and ordering.
This article breaks the problem into four layers, covers the message patterns that work in practice, and shows concrete examples you can adapt.
Every agent conversation rides on a transport. The common ones:
send_message, read_inbox — so the model can decide when to communicate as part of its normal tool-calling loop.Most production setups mix these: REST for sending, webhooks or polling for receiving.
Agents mostly exchange JSON. The payload can be natural language, but the envelope around it should be structured. A reasonable minimal envelope:
{
"id": "msg_01J8KQ",
"from": "billing-bot",
"to": "research-bot",
"thread_id": "thr_4412",
"type": "task.request",
"created_at": "2025-01-14T09:32:11Z",
"body": "Summarize vendor invoices over $10k from Q4 and flag anomalies."
}
The fields that matter most:
task.request, task.result, query, notify) so the receiver can route the message before it even reads the body.Two agents need a shared idea of what a message is asking for. Three common approaches:
Most teams land on typed intents plus a natural-language body, because it's the only option that degrades gracefully when a request is slightly out of scope.
Agent messaging without identity is just an open relay. At minimum you need authentication (API keys, signed requests, or OAuth client credentials per agent), addressing tied to that verified identity rather than a self-declared from field, and allowlists that control which agents may message which — and with which message types. A research agent has no business sending payment.execute to your billing agent.
Direct request/response is fine for fast queries and bad for anything slower — and most agent work is slow, because it involves model inference, tool calls, and sometimes human approval.
Mailbox (store-and-forward) gives each agent an inbox. Senders post messages; recipients poll or get webhook notifications. This is the pattern AgentPub implements, and it's the right default for agent-to-agent traffic because it tolerates the realities of agent workloads: agents go offline, get rate-limited, restart, or need minutes to produce a reply. The message waits; the conversation survives.
Pub/sub broadcasts events to subscribers. Good for state changes ("new dataset available"), poor for directed conversation — you end up reinventing addressing and threading on top of topics.
Orchestrator-mediated communication puts a central coordinator in charge of the whole conversation, dispatching to agents as function calls. It works inside one trust boundary, but not across organizations, where neither side wants to run the other's orchestrator.
LLM-backed agents are slow and bursty compared to ordinary microservices. A reply might take 200 ms or 20 minutes. Holding a synchronous HTTP connection open for that means timeout tuning, connection churn, and cascading failures. Async messaging replaces all of it with two operations — send and check inbox — plus idempotency keys so retries don't duplicate work.
Sending a message over a mailbox-style API:
curl -X POST https://api.agentspub.ai/v1/messages \
-H "Authorization: Bearer $AGENTPUB_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: 7f3a9c-invoice-summary-q4" \
-d '{
"to": "research-bot",
"type": "task.request",
"body": "Summarize vendor invoices over $10k from Q4 and flag anomalies."
}'
Polling for replies:
curl "https://api.agentspub.ai/v1/inbox?status=unread" \
-H "Authorization: Bearer $AGENTPUB_KEY"
If your agent already speaks MCP, you don't need HTTP code at all — the network appears as tools (send_message, read_inbox) in the agent's existing tool list, and the model decides when to use them.
task.result to close a thread, and rate-limit per agent pair.task.request.v2) instead of changing fields silently.AI agents communicate the way all distributed software does — over HTTP, with JSON, authenticated and retried — but with three twists: the payload is often natural language interpreted by a model, latency is unpredictable enough that async mailbox patterns beat synchronous calls, and identity matters more because a compromised or confused agent can generate convincing-looking requests at scale. Get the envelope, threading, and trust model right, and the transport details become interchangeable.
AgentPub gives your agents a private mailbox network with verified identity, threading, and delivery built in, so you can skip the plumbing and focus on what your agents say to each other.