Local AI Infrastructure Notes (4/15) — Building an Inter-Agent Message Hub
A dual-path agent communication architecture separating fire-and-forget webhooks from ACK-based task messages
Summary
- Multiple agents require a communication structure — without one, each agent becomes a silo
- Insight delivery (fire-and-forget) and task requests (ACK-required) demand distinct design patterns
- Separating the webhook path from the message path enables simultaneous handling of simple notifications and trackable work items
Background
When there is only one agent, communication is unnecessary. The agent executes a task and returns a result to the user.
The problem begins with multiple agents. When an insight discovered by a stock analysis agent must be written up by a content agent. When an investment strategy from a life-organization agent should influence the portfolio direction of a stock agent. If those connections can only be made through a human intermediary, the human becomes a bottleneck.
A hub where agents can exchange messages directly is required. However, not all messages are equivalent. Passing along a "for your reference" insight and issuing a "please do this task and confirm when done" request require different mechanisms.
Body
1. Why Two Communication Paths
Routing all communication through a single API leads rapidly to complexity explosion. Simple insight delivery would still require waiting for an ACK, and critical task requests would be buried under notification traffic.
The solution is path separation:
| Path | Purpose | Pattern | Tracking |
|---|---|---|---|
| Webhooks | Insight / notification delivery | fire-and-forget | None |
| Agent Messages | Task requests / responses | ACK required | Full |
Webhooks (fire-and-forget): The sender emits "here is what I found" and moves on. Whether the receiver reads it is irrelevant to the sender. Insights, monitoring data, and status updates travel this path.
Agent Messages (ACK-based): The sender emits "please do this task" and waits for the receiver to return an acknowledgement (ACK). Task requests, post-transfer processing confirmations, and collaborative inter-agent work travel this path.
2. Webhook Path — Lightweight, Fast Delivery
The webhook API pattern is minimal:
POST /api/webhooks
{
"content": "content to deliver",
"tags": ["tag1", "tag2"],
"source": "sending-agent"
}
No response is awaited. HTTP 200 means delivery is complete. When the receiver reads it and how it processes the content are outside the sender's concern.
Use cases for this path: - A research agent records discovered data to the hub - A monitoring agent reports service health - An agent shares a detected pattern for other agents to reference
Overhead is negligible, allowing agents to share insights freely. Information that might only prove useful later can be emitted without hesitation.
3. Agent Message Path — Communication Requiring Tracking and Confirmation
Task-request messages require a higher level of reliability.
POST /api/agent-messages
{
"fromAgent": "sending agent",
"toAgent": "receiving agent",
"messageType": "task_request",
"intent": "description of task intent",
"body": {
"text": "specific request content"
},
"dedupeKey": "unique-key"
}
Core mechanisms of this path:
Inbox pattern: Each agent maintains its own inbox.
GET /api/agent-inbox/{agentName}
When an agent activates, it checks its inbox and processes any pending messages.
ACK (acknowledgement): On receiving a message, the agent must return an ACK.
POST /api/agent-messages/{messageId}/ack
{
"status": "acked",
"response": { ... }
}
If no ACK arrives, the message was not processed. This enables retry logic and timeout handling.
Deduplication: dedupeKey prevents the same message from being processed more than once. If a message is retransmitted due to a network issue, any message sharing the same key is processed exactly once.
4. Agent Naming Convention
Agent names require a consistent convention. While the API auto-normalizes names, the canonical form uses Korean names with spaces.
- Correct: "๊ธ ์์ฑ ๋๋ ํฐ", "์ฃผ์ ์ ๋ณด ๊ด๋ฆฌ ๋๋ ํฐ"
- Avoid: "๊ธ-์์ฑ-๋๋ ํฐ", "write_score_agent"
The reason is straightforward. The name a user uses to refer to an agent must match the system's internal identifier. Using hyphens or underscores for technical convenience generates recurring "which name is correct?" confusion.
5. Real-World Case: Passing Blog Material Between Agents
Here is one flow where this architecture operates:
- The life-organization agent reviews a user's experience or decision and determines "this could become blog material"
- It delivers an insight via webhook:
POST /api/webhooks— tags include "blog-material" - The content agent checks the hub for relevant insights at session start
- If the material is deemed viable, the agent initiates its pipeline via the message path: research → source file compilation → verification → blog draft
- Once the blog draft is complete, the agent sends a confirmation request to the user
The key point: steps 1–2 use webhooks (fire-and-forget); the remainder is the content agent's autonomous pipeline. Insight delivery stays lightweight; actual work execution is autonomous within each agent.
If the life-organization agent needs to directly instruct the content agent to "write a post on this topic," it uses the message path (POST /api/agent-messages). The content agent returns the result via ACK upon completion.
Design Pitfalls and Response Patterns
Single-path design problem: Routing all communication through one API forces even insight notifications to require ACK, increasing processing load on every agent. Critical task requests get buried in notification traffic — a priority inversion. Separating paths means each communication type carries only the overhead it actually needs.
Name mismatch problem: Using different agent names internally and externally causes inbox lookup failures. Apply normalization at the API level, but keep the user-visible name and internal identifier identical as a hard rule.
Missing dedupeKey risk: When a message is retransmitted due to network timeout, the absence of dedupeKey results in duplicate task execution. Including a deterministic unique key in every task-request message is mandatory. Key generation strategy: the pattern {fromAgent}:{toAgent}:{intent}:{timestamp} minimizes collision probability.
Conclusion
With one agent, no communication structure is needed. With two, it becomes "nice to have." With three or more, it is non-negotiable.
The core design principle is simple: lightweight delivery via webhooks, trackable work via messages. That single distinction brings communication complexity down to a manageable level.
In inter-agent communication, the hard part is not technical implementation. The design challenge is judging "what level of reliability does each type of communication require?" The message hub's role is to encode that judgment as structure.
Series overview: Series index
๋๊ธ
๋๊ธ ์ฐ๊ธฐ