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:

  1. The life-organization agent reviews a user's experience or decision and determines "this could become blog material"
  2. It delivers an insight via webhook: POST /api/webhooks — tags include "blog-material"
  3. The content agent checks the hub for relevant insights at session start
  4. If the material is deemed viable, the agent initiates its pipeline via the message path: research → source file compilation → verification → blog draft
  5. 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

๋Œ“๊ธ€

์ด ๋ธ”๋กœ๊ทธ์˜ ์ธ๊ธฐ ๊ฒŒ์‹œ๋ฌผ

Agent Memory Engine (2/10) — Building an AI Agent Memory System with SQLite Alone

"ML Foundations (9/9) — PyTorch vs TensorFlow, and the Road to Local LLMs"

"RAG Core Study (14/26) — Evaluation Sets with RAGAS & DeepEval"

"ML Foundations (8/9) — Deep Learning Architectures: CNN, RNN, Attention"

"ML Foundations (7/9) — Deep Learning Training: Optimizers, Regularization, Initialization"

OpenClaw to Hermes Migration (2/13) — What to Preserve, Partially Port, or Discard

AI Agents I Built (5/7) — Building an Automated Blogger API Publishing System