<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Tim Wood</title>
    <description>The latest articles on DEV Community by Tim Wood (@timwood0x10).</description>
    <link>https://dev.to/timwood0x10</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3984998%2F49788ac4-dcdf-4bd5-a7d3-d037d7164360.png</url>
      <title>DEV Community: Tim Wood</title>
      <link>https://dev.to/timwood0x10</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/timwood0x10"/>
    <language>en</language>
    <item>
      <title>GoAgentX Architecture Deep Dive (Part 2): AHP — The Communication Backbone for Multi-Agents</title>
      <dc:creator>Tim Wood</dc:creator>
      <pubDate>Tue, 16 Jun 2026 08:14:59 +0000</pubDate>
      <link>https://dev.to/timwood0x10/goagentx-architecture-deep-dive-part-2-ahp-the-communication-backbone-for-multi-agents-1m0c</link>
      <guid>https://dev.to/timwood0x10/goagentx-architecture-deep-dive-part-2-ahp-the-communication-backbone-for-multi-agents-1m0c</guid>
      <description>&lt;p&gt;This is the second article in the GoAgentX series. Read Part 1 &lt;a href="https://dev.to/timwood0x10/shedding-old-baggage-i-designed-my-own-agent-framework-1bm0"&gt;here&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A common question when talking about multi-agent systems is: How do agents talk to each other? HTTP? WebSocket? Message queues? &lt;/p&gt;

&lt;p&gt;My blunt answer was:&lt;br&gt;
&lt;code&gt;They’re running in the same process. Why the hell would I go through the network just to chat?&lt;/code&gt;&lt;br&gt;
That’s how AHP (Agent Hierarchical Protocol) was born — a lightweight, network-free communication protocol built purely with Go channels.&lt;/p&gt;
&lt;h2&gt;
  
  
  Why Build My Own Wheel?
&lt;/h2&gt;

&lt;p&gt;In GoAgentX, we have two main roles: Leader Agent (the boss that delegates tasks) and Sub Agents (the workers). The headaches they need to solve include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Asynchronous task dispatching&lt;/li&gt;
&lt;li&gt;Progress reporting&lt;/li&gt;
&lt;li&gt;Heartbeat &amp;amp; liveness detection&lt;/li&gt;
&lt;li&gt;Fault tolerance and dead letter handling&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I tried Redis, looked at RabbitMQ… they were either too heavy, too slow, or just not feeling right for an in-process system. So I decided to build something simple, fast, and Go-native.&lt;br&gt;
Core Advantages:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Blazing fast (channel vs network RTT)&lt;/li&gt;
&lt;li&gt;No serialization overhead in single-process mode&lt;/li&gt;
&lt;li&gt;Easy to evolve — swap the backend to gRPC later without changing business logic&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Core Components of AHP
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbohdfz1g4qitnsivf5dk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbohdfz1g4qitnsivf5dk.png" alt=" " width="799" height="519"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Protocol: Facade that ties everything together&lt;/li&gt;
&lt;li&gt;MessageQueue: Buffered channel + backup + atomic flags&lt;/li&gt;
&lt;li&gt;HeartbeatMonitor: Detects dead agents with smart timeout logic&lt;/li&gt;
&lt;li&gt;DLQ (Dead Letter Queue): Handles failed messages with retry support&lt;/li&gt;
&lt;li&gt;QueueRegistry: Lazy loading with double-checked locking&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Message Model
&lt;/h2&gt;

&lt;p&gt;AHP defines 5 message types: TASK, RESULT, PROGRESS, ACK, HEARTBEAT.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;AHPMethodTask&lt;/span&gt;      &lt;span class="n"&gt;AHPMethod&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"TASK"&lt;/span&gt;      &lt;span class="c"&gt;// Task allocation&lt;/span&gt;
    &lt;span class="n"&gt;AHPMethodResult&lt;/span&gt;    &lt;span class="n"&gt;AHPMethod&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"RESULT"&lt;/span&gt;     &lt;span class="c"&gt;// Task Result &lt;/span&gt;
    &lt;span class="n"&gt;AHPMethodProgress&lt;/span&gt;  &lt;span class="n"&gt;AHPMethod&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"PROGRESS"&lt;/span&gt;   &lt;span class="c"&gt;// Progress feedback&lt;/span&gt;
    &lt;span class="n"&gt;AHPMethodACK&lt;/span&gt;       &lt;span class="n"&gt;AHPMethod&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"ACK"&lt;/span&gt;        &lt;span class="c"&gt;// Confirm Reply&lt;/span&gt;
    &lt;span class="n"&gt;AHPMethodHeartbeat&lt;/span&gt; &lt;span class="n"&gt;AHPMethod&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"HEARTBEAT"&lt;/span&gt;  &lt;span class="c"&gt;// Heartbeat signal&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;message struct&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;AHPMessage&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;MessageID&lt;/span&gt;   &lt;span class="kt"&gt;string&lt;/span&gt;         &lt;span class="s"&gt;`json:"message_id"`&lt;/span&gt;
    &lt;span class="n"&gt;Method&lt;/span&gt;      &lt;span class="n"&gt;AHPMethod&lt;/span&gt;      &lt;span class="s"&gt;`json:"method"`&lt;/span&gt;
    &lt;span class="n"&gt;AgentID&lt;/span&gt;     &lt;span class="kt"&gt;string&lt;/span&gt;         &lt;span class="s"&gt;`json:"agent_id"`&lt;/span&gt;
    &lt;span class="n"&gt;TargetAgent&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;         &lt;span class="s"&gt;`json:"target_agent"`&lt;/span&gt;
    &lt;span class="n"&gt;TaskID&lt;/span&gt;      &lt;span class="kt"&gt;string&lt;/span&gt;         &lt;span class="s"&gt;`json:"task_id"`&lt;/span&gt;
    &lt;span class="n"&gt;SessionID&lt;/span&gt;   &lt;span class="kt"&gt;string&lt;/span&gt;         &lt;span class="s"&gt;`json:"session_id"`&lt;/span&gt;
    &lt;span class="n"&gt;Payload&lt;/span&gt;     &lt;span class="k"&gt;map&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="n"&gt;any&lt;/span&gt; &lt;span class="s"&gt;`json:"payload"`&lt;/span&gt;
    &lt;span class="n"&gt;Timestamp&lt;/span&gt;   &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Time&lt;/span&gt;      &lt;span class="s"&gt;`json:"timestamp"`&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;MessageID Generation&lt;/p&gt;

&lt;p&gt;MessageID is designed as a three-part ID:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;generateMessageID&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;atomic&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AddUint64&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;messageIDCounter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;randSuffix&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;getRandomSuffix&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Sprintf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"%s.%d.%s"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"20060102150405.000000"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;randSuffix&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Timestamp prefix: Highly readable, facilitates troubleshooting.&lt;/li&gt;
&lt;li&gt;Atomic counter: Sequence numbers of multiple messages within the same nanosecond increment.&lt;/li&gt;
&lt;li&gt;Random suffix: Avoids conflicts in multi-process scenarios.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This scheme does not rely on a global coordinator and guarantees uniqueness within the process.&lt;/p&gt;

&lt;p&gt;Don't worry if you don't quite understand; I've simply borrowed some design elements from blockchains. I previously participated in the design of a public chain, and the messages were referenced. There's no other intention; its main purpose is &lt;strong&gt;state synchronization&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  HeartbeatMonitor
&lt;/h2&gt;

&lt;p&gt;Core Process:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Each Agent sends a heartbeat at a fixed interval (default 5 seconds).&lt;/li&gt;
&lt;li&gt;HeartbeatMonitor records the time of the most recent heartbeat.&lt;/li&gt;
&lt;li&gt;If the timeout period (default 30 seconds) is exceeded and the number of consecutive missed heartbeats reaches the threshold (default 3 times), the agent is marked as offline.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Timeout detection algorithm&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;m&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;HeartbeatMonitor&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;CheckTimeouts&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;timedOut&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;checkAndMarkOffline&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;  &lt;span class="c"&gt;// 写锁下检测&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;agentID&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="k"&gt;range&lt;/span&gt; &lt;span class="n"&gt;timedOut&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;notifyCallbacks&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;agentID&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;        &lt;span class="c"&gt;// 锁外执行回调&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;timedOut&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Key Boundary Condition Handling:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Progressive Timeout: Offline is only determined after 3 missed heartbeats, avoiding false positives due to occasional network latency.
2.Avoid Duplicate Callbacks: Offline agents will not trigger callbacks again.
3.Callbacks Executed Outside Lock: The notifyCallbacks list is copied, the lock is released, and then execution begins; this is crucial for preventing deadlocks.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;There are two types of HeartbeatSenders:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;ahp.HeartbeatSender&lt;/code&gt;: Sends AHPMethodHeartbeat messages to the target's MessageQueue, which includes an internal heartbeat.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;heartbeatSender&lt;/code&gt;(in internal/agents/sub/): Directly calls HeartbeatMonitor.RecordHeartbeat, which includes an external heartbeat.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Currently, the Sub Agent uses the second method, which is more efficient in monolithic deployments.&lt;/p&gt;

&lt;h2&gt;
  
  
  Dead-Letter Queues: DLQ
&lt;/h2&gt;

&lt;p&gt;When the Enqueue returns an error, Protocol.SendMessage routes the failure message to the DLQ:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;classifyEnqueueError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="kt"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;switch&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="n"&gt;errors&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Is&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;apperrors&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ErrQueueClosed&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s"&gt;"queue_closed"&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="n"&gt;errors&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Is&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;apperrors&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ErrQueueFull&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s"&gt;"queue_full"&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="n"&gt;errors&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Is&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Canceled&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;          &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s"&gt;"context_canceled"&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="n"&gt;errors&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Is&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DeadlineExceeded&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s"&gt;"context_deadline"&lt;/span&gt;
    &lt;span class="k"&gt;default&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;                                        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s"&gt;"unknown"&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;DLQProcessor supports registering custom processors based on error type and supports automatic retries:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;MaxRetries = 0: Infinite retries&lt;/li&gt;
&lt;li&gt;MaxRetries &amp;gt; 0: Marked as exhausted after reaching the specified number of retries.&lt;/li&gt;
&lt;li&gt;Currently, there is no exponential backoff, which is an area for improvement.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Key Design Decisions
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Why Non-Blocking Enqueues?
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;The Agent operates in a multi-threaded environment; blocking can lead to cascading waits.&lt;/li&gt;
&lt;li&gt;DLQ provides better fault-tolerance semantics; failed messages can be retried.&lt;/li&gt;
&lt;li&gt;The caller has greater control: immediate retry, later retry, or discard.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Avoiding TOCTOUs
&lt;/h3&gt;

&lt;p&gt;SendMessage has a key design flaw: it doesn't check IsFull before enqueuing. If it checks IsFull before enqueuing, the queue might go from not full to full between the check and enqueue (TOCTOU race condition), leading to message loss. Directly executing operations and handling errors is more robust.&lt;/p&gt;

&lt;h3&gt;
  
  
  Serialization Reserved for Extensions
&lt;/h3&gt;

&lt;p&gt;Currently, AHP is purely intra-process communication, and JSON is sufficient. However, the Codec interface reserves extensions in two directions:&lt;/p&gt;

&lt;p&gt;Inter-process communication: protobuf/msgpack can provide a smaller payload.&lt;/p&gt;

&lt;p&gt;Persistence: If DLQ messages are written to disk, binary format is more advantageous.&lt;/p&gt;

&lt;h2&gt;
  
  
  Now for the much-anticipated exposé:
&lt;/h2&gt;

&lt;p&gt;To be honest, AHP isn't perfect. I've encountered some pitfalls myself:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Purely in-process: Can't cross processes; for distributed systems, you'd need to switch to a MessageQueue implementation.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;No broadcast: Need to send messages to multiple Subs? You have to send them one by one.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Insufficient retry strategy: DLQ retry intervals are fixed, without exponential backoff—continuous failures could cause a retry storm.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Inflexible routing: Doesn't support content-based dynamic routing or Topic subscriptions.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;However, these limitations are trade-offs made as needed—in the monolithic phase, the channel solution saves 90% of the distributed complexity. If you really want to implement microservices in the future, you only need to replace the underlying implementation; the business logic code above doesn't need to be changed. That's the benefit of an abstraction layer. When used on a single machine, it is indeed quite smooth. However, if you are going to use this project for an interview, I suggest you prepare how to handle it in a distributed environment. The purpose of writing this is to serve as a starting point. In the AI ​​era, in addition to basic programming skills, I personally suggest you hone your software engineering skills. After all, being an LLM API caller is not our goal.&lt;/p&gt;

&lt;p&gt;In summary, AHP is the communication framework I developed for GoAgentX. Channel message passing, DLQ fallback, and HeartbeatMonitor monitoring – these three components together provide the complete infrastructure for multi-agent communication.&lt;/p&gt;

&lt;p&gt;The interfaces left in the code (Codec, DLQ handler, MessageSender) are essentially backup plans: if you need to switch to gRPC or RabbitMQ later, simply change the implementation layer; the underlying business logic remains unchanged. This design is especially important in startup projects – you never know what the architecture will look like tomorrow.&lt;/p&gt;

&lt;p&gt;Next, let's talk about memory distillation – how agents extract useful experience from hundreds of conversations in their history. This is also a key technology I think is frequently asked in agent interviews: how to ensure the model's information is not distorted in long-context scenarios.&lt;/p&gt;

&lt;p&gt;GitHub: &lt;a href="https://github.com/Timwood0x10/GoAgentX" rel="noopener noreferrer"&gt;https://github.com/Timwood0x10/GoAgentX&lt;/a&gt;&lt;br&gt;
What do you think? Star, try it, or drop your feedback — highly appreciated!&lt;/p&gt;

</description>
      <category>ai</category>
      <category>agents</category>
      <category>go</category>
    </item>
    <item>
      <title>Shedding Old Baggage, I Designed My Own Agent Framework</title>
      <dc:creator>Tim Wood</dc:creator>
      <pubDate>Mon, 15 Jun 2026 08:53:25 +0000</pubDate>
      <link>https://dev.to/timwood0x10/shedding-old-baggage-i-designed-my-own-agent-framework-1bm0</link>
      <guid>https://dev.to/timwood0x10/shedding-old-baggage-i-designed-my-own-agent-framework-1bm0</guid>
      <description>&lt;p&gt;Hello everyone, before I begin, let me ask a quick question: how did you all learn about Agents?&lt;/p&gt;

&lt;p&gt;I initially started with deep learning papers, but their mathematical principles completely overwhelmed me. Later, I found a tutorial on GitHub, but I still only had a superficial understanding; each concept was fragmented and couldn't be systematically pieced together. Then I wondered if I wasn't suited for AI and even considered giving up… Finally, I came up with an idea: I would create a demo of an agent, compare it with mainstream agents, and incorporate some of my own ideas. Would that work? And so, this project came about.&lt;/p&gt;

&lt;p&gt;Great, let's get started. But here's the question: what is an agent? What problem does it solve? I eagerly researched various reports and even asked about GPT and Gemini. Oh, so it's driven by LLM to complete a series of tasks (I have to complain, there are so many ridiculous terms in this field).&lt;/p&gt;

&lt;p&gt;So I'm wondering, what can the agent do? What problems can it solve? How is it different from what I've encountered in the GPT Q&amp;amp;A section on the website?&lt;/p&gt;

&lt;p&gt;Then I remembered the local knowledge bases that were so popular last year, so why don't I build one? I started writing scripts using Python and a vector database.&lt;/p&gt;

&lt;p&gt;After that, with the help of AI, I started my first agent-like project: a local knowledge base. After finishing the coding, when I first executed python main.py, I saw that the local notes were first split, then embedded, and then stored in the database. Then I tried to write my first search command. I asked the local ollama 3 hey, can you tell me what's in the local knowledge base? It quickly gave me a reply... Not bad, at least it's a good start.&lt;/p&gt;

&lt;p&gt;The Excitement Didn’t Last Long&lt;br&gt;
At first, I was thrilled. It actually worked! But as I tried to make it more powerful — adding tool calling, multi-step reasoning, memory across sessions, and letting multiple agents collaborate — things quickly fell apart.&lt;br&gt;
Python was slow when handling concurrent agents. Memory management became messy. The workflow logic turned into a spaghetti of callbacks and state machines. Every time I wanted to change the flow (add a new step, add failover, or support human-in-the-loop), I had to rewrite half the code. Debugging long-running agent sessions felt like chasing ghosts.&lt;br&gt;
I kept thinking: “There must be a better way.”&lt;br&gt;
Why I Chose Go&lt;br&gt;
I’ve always loved Go for its simplicity, performance, and great concurrency support. So I asked myself — what if I rebuild this agent system in Go from the ground up?&lt;br&gt;
That decision became the starting point of GoAgentX.&lt;br&gt;
How GoAgentX Was Born&lt;br&gt;
I started small, just like before — implementing basic LLM calling and simple RAG. But this time everything felt different:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Goroutines made concurrent agents naturally fast and lightweight.&lt;/li&gt;
&lt;li&gt;Strong typing and clean interfaces forced me to design clearer abstractions.&lt;/li&gt;
&lt;li&gt;Channels and context made workflow orchestration and cancellation much more reliable.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;As the project grew, I gradually added the features I wished I had in my Python experiments:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Dynamic DAG Workflows — Agents’ execution flow can be built and modified at runtime. No more hardcoded sequences.&lt;/li&gt;
&lt;li&gt;Memory Distillation — Long-term memory is automatically summarized and compressed so agents don’t drown in context.&lt;/li&gt;
&lt;li&gt;AHP (Agent-to-Agent Hierarchical Protocol) — A clean way for agents to communicate, delegate, and collaborate.&lt;/li&gt;
&lt;li&gt;Leader + Sub-Agent architecture with Failover — If the leader fails, another agent can seamlessly take over.&lt;/li&gt;
&lt;li&gt;Pluggable vector stores (PostgreSQL pgvector, Qdrant, etc.) and high-performance benchmarks (many operations under 1µs with zero allocation hot paths).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;From a simple local knowledge base demo, it evolved into a production-ready multi-agent framework.&lt;br&gt;
What GoAgentX Is Today&lt;br&gt;
GoAgentX is no longer just my personal learning project. It’s a general-purpose, high-performance Multi-Agent framework written in Go that focuses on reliability, observability, and scalability.&lt;br&gt;
Whether you want to build:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Complex RAG systems&lt;/li&gt;
&lt;li&gt;Autonomous research agents&lt;/li&gt;
&lt;li&gt;Multi-agent collaboration workflows&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;repo: &lt;a href="https://github.com/Timwood0x10/GoAgentX" rel="noopener noreferrer"&gt;https://github.com/Timwood0x10/GoAgentX&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Next, I will start a series of articles to gradually break down the design concept of this project, helping everyone to better understand my design approach. Discussions and comments are welcome.&lt;/p&gt;

&lt;p&gt;Of course, if you don't like this narrative style, you can tell me, and I'll try to be more serious.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>agents</category>
    </item>
  </channel>
</rss>
