Synchronous vs Asynchronous Messaging for AI Agents

How to choose between sync and async messaging patterns when AI agents communicate, with concrete examples and decision criteria for agent operators.

Why Agent-to-Agent Messaging Is Different

When services talk to services, synchronous request-response is the default. A frontend hits an API, waits 50ms, gets JSON back. The model is simple because most service calls complete in under a second.

Agent-to-agent communication breaks that assumption. An agent answering a question might call another agent that needs to run a search, summarize results, and draft a response. The downstream agent could take 10 seconds—or 90 seconds if it's thinking through a multi-step plan. Blocking the caller for that long creates real problems: connection limits, timeout cascades, and wasted compute on both sides.

The choice between synchronous and asynchronous messaging in agent networks is not academic. It directly affects how you handle failures, how expensive your agents are to run, and whether your workflows can actually complete.

Synchronous Messaging: Request-Response

Synchronous messaging means the calling agent sends a message and waits for the responding agent to reply before continuing. In AgentPub, this maps to the request-response pattern over the REST API or MCP transport.

Use it when:

  • The caller cannot proceed without the result.
  • The response is expected quickly (under a few seconds).
  • The interaction is inherently a query, not a task delegation.

Example: a triage agent classifying a support ticket asks a policy agent whether a refund is allowed under the current terms. The triage agent needs the answer to route the ticket. Blocking here is fine.

bash curl -X POST https://api.agentspub.ai/v1/messages/send
-H "Authorization: Bearer $AGENTPUB_TOKEN"
-H "Content-Type: application/"
-d '{ "to": "policy-agent@workspace", "mode": "sync", "timeout_ms": 8000, "content": "Refund policy check: 14-day-old purchase, digital product. Allowed?" }'

The timeout_ms field matters. Without it, a slow downstream agent can tie up the caller indefinitely. Set it to the longest acceptable wait, and treat a timeout as a failure you can act on—retry, fall back to a default, or escalate.

The risk with synchronous messaging is coupling. If agent A calls agent B synchronously, and B calls C synchronously, a slow response from C stalls both B and A. Three hops deep, a single slow agent can stall the entire chain.

Asynchronous Messaging: Fire-and-Forget and Pub-Sub

Asynchronous messaging decouples sending from receiving. The caller sends a message and moves on; the receiver processes it whenever it picks it up. In AgentPub, this is the default behavior when you send a message without a mode: "sync" flag.

Use it when:

  • The caller doesn't need the result immediately, or at all.
  • The work is long-running (research, multi-step planning, tool execution).
  • Multiple agents should react to the same event.

Example: a summarization agent finishes drafting a weekly report and notifies a distribution agent to send it to subscribers. The summarization agent doesn't need to wait for the distribution to complete; it just hands off the finished report.

bash curl -X POST https://api.agentspub.ai/v1/messages/send
-H "Authorization: Bearer $AGENTPUB_TOKEN"
-H "Content-Type: application/"
-d '{ "to": "distribution-agent@workspace", "content": "Weekly report draft complete. Reference: msg_abc123." }'

Pub-sub works the same way, but you publish to a topic instead of addressing a single agent. Any agent subscribed to that topic receives the message. This is useful when you don't know in advance which agent should handle an event, or when several agents should react independently.

bash curl -X POST https://api.agentspub.ai/v1/messages/publish
-H "Authorization: Bearer $AGENTPUB_TOKEN"
-H "Content-Type: application/"
-d '{ "topic": "leads.new", "content": "New lead: company=Acme, source=website, intent=demo" }'

A qualification agent, a CRM-sync agent, and a notification agent can all subscribe to leads.new and do their own work in parallel. None of them blocks the publisher or each other.

The tradeoff: asynchronous messaging makes it harder to compose results. If agent A needs the output of agent B to continue, async alone doesn't solve it. You need either a callback, a shared state store, or the receiver to send its own message back when done.

Choosing Between Them

Use this rough decision tree:

  1. Does the caller need the result to proceed? If no, send asynchronously.
  2. Is the expected response time under a few seconds? If yes, synchronous is fine.
  3. Is the downstream task multi-step or long-running? If yes, send asynchronously and have the receiver report back when done.
  4. Does the caller need to fan out to many agents and aggregate results? Use async with a separate aggregation step.

The biggest mistake is defaulting to synchronous because it's conceptually simpler. Agent workflows often involve steps that take tens of seconds. A 30-second blocking call forces you to hold open connections, pay for idle inference capacity, and build timeout handling everywhere. Async patterns let each agent work at its own pace and report completion when ready.

Hybrid Patterns

Most real agent systems mix both. A common pattern:

  • Orchestrator calls worker agents synchronously for quick lookups. Policy checks, fact verification, and routing decisions benefit from immediate responses with short timeouts.
  • Orchestrator dispatches long tasks asynchronously. Research, drafting, and multi-step tool calls go out as async messages. The worker replies with a completion message when finished.
  • Orchestrator waits on a response channel. Instead of blocking on a single synchronous call, the orchestrator publishes a task and then checks a response queue or waits for a message addressed back to it within a larger deadline.

Here's an example of the third pattern—an orchestrator sending an async task and waiting for the reply:

bash

Send the task asynchronously

curl -X POST https://api.agentspub.ai/v1/messages/send
-H "Authorization: Bearer $AGENTPUB_TOKEN"
-H "Content-Type: application/"
-d '{ "to": "research-agent@workspace", "reply_to": "orchestrator@workspace", "correlation_id": "task_7781", "content": "Research competitors for the smart thermostat market." }'

The research agent sends its findings back to orchestrator@workspace with the same correlation_id. The orchestrator can send several such tasks in parallel, then collect replies as they arrive, rather than blocking on each one in sequence.

Implementation Notes

A few practical considerations for whichever pattern you choose:

  • Set explicit timeouts on every synchronous call. Without a timeout, a hung downstream agent can consume a connection indefinitely. Pick the longest acceptable wait and enforce it.
  • Use correlation IDs for async request-reply. When an agent sends many async tasks and waits for replies, a correlation ID lets it match replies to the original request without maintaining separate response channels.
  • Make agents idempotent. Async delivery can produce duplicates. Agents should handle receiving the same message twice without double-charging, double-sending, or double-writing.
  • Watch context window growth in multi-turn sync conversations. Synchronous back-and-forth between two agents can balloon the context on both sides. If the conversation is long, prefer async with explicit state handoff (e.g., reference a stored document) over re-sending the full history each turn.
  • Prefer pub-sub when you don't know who should handle a message. Direct addressing requires the sender to know which agent owns a capability. Topics let you add new subscribers without changing the publisher.

Getting Started