<?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>Some thoughts on participating in an AI programming challenge organized by a major Chinese corporation</title>
      <dc:creator>Tim Wood</dc:creator>
      <pubDate>Thu, 23 Jul 2026 02:20:49 +0000</pubDate>
      <link>https://dev.to/timwood0x10/some-thoughts-on-participating-in-an-ai-programming-challenge-organized-by-a-major-chinese-5em3</link>
      <guid>https://dev.to/timwood0x10/some-thoughts-on-participating-in-an-ai-programming-challenge-organized-by-a-major-chinese-5em3</guid>
      <description>&lt;p&gt;To give a brief background: a while back, I participated in an AI programming competition organized by Trea, but I encountered some unfair treatment that I’d like to share with everyone. I’m also curious to know how judges typically score competitions like this.&lt;/p&gt;

&lt;p&gt;My entry transforms my personal notes on the underlying mathematics of LLMs into an interactive interface, which I have deployed on GitHub Pages.(I've already deleted the code repository. :( ).&lt;/p&gt;

&lt;p&gt;Here is a brief overview of the process: over 14,000 independent developers participated in the preliminary round. The submission deadline was July 15. The review period ran from July 16 to July 21, with the 350 qualifiers announced on the afternoon of July 21. Of these spots, 300 were determined by judges officially selected by ByteDance, while the remaining 50 were awarded to entrants who posted their work on TikTok (known as Douyin in China) and ranked in the top 50 based on likes and comments.&lt;/p&gt;

&lt;p&gt;The overall atmosphere of the competition was reasonably cordial—until the list of those advancing to the next round was announced on the afternoon of July 21st. Many independent developers immediately sought out Trea’s operations team to demand an explanation.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The review process was a "black box," and the scoring criteria were even altered (a community member pointed this out).&lt;/li&gt;
&lt;li&gt;A significant number of entries from contestants went unreviewed or unexamined.&lt;/li&gt;
&lt;li&gt;Some posts that did not comply with the preliminary round guidelines were able to advance.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Developers are questioning these specific points: is the reality living up to the official pre-launch marketing? Clearly, it is not. On a broader level, this represents a crisis of trust between the community and the product.&lt;/p&gt;

&lt;p&gt;I wasn't selected either—I didn't even make the top 2,000. Everyone is questioning the fairness of the competition here. While it is undeniable that the top 300 entries included truly outstanding work worth learning from, the fact remains that these merits do not overshadow the community's desire for fairness or their doubts regarding the contest's integrity.&lt;/p&gt;

&lt;p&gt;Here are my main takeaways from this competition.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The rules were a joke; they changed constantly, and the organizers themselves disregarded them, even granting special exceptions to entries that didn't meet the requirements&lt;/li&gt;
&lt;li&gt;The community atmosphere is quite poor; a handful of members enjoy mocking those who ask genuine questions, and the official team turns a blind eye—unless a topic draws a crowd of dozens, at which point they only show up to watch the drama unfold.&lt;/li&gt;
&lt;li&gt;As for the competition review process, luck plays a significant role. Some participants reported their services being accessed from IP addresses in Shanghai or Beijing, while others found their servers completely untouched. Perhaps those entries simply didn't appeal to the judges' tastes. The same applies to my own work; the link click count visible in the post shows no increase.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Finally, there is no need to deliberately alter your work just to cater to the judges' preferences. No matter how well you execute it, people will inevitably focus on the weakest aspects, nitpick, and dismiss both the work and the creator as worthless. In my view, a project is a success if it helps even a small number of people solve real-world problems—something that cannot simply be judged by someone holding a title like "judge."&lt;/p&gt;

&lt;p&gt;This was perhaps the worst programming competition experience I’ve ever had. Trae’s operations team focused entirely on talking about how hard they worked—mentioning, for instance, that they had put in five consecutive days of overtime reviewing tens of thousands of submissions. They refused to disclose the shortcomings of the rejected projects or the actual scores of the ones that advanced; instead, they simply had community members aggressively promote the narrative of the team's hard work.&lt;/p&gt;

&lt;p&gt;I saw many rejected projects that actually held significant social value. One such project—an app designed by a couple to help children suffering from depression or mental health issues—failed to advance, which struck me as particularly ironic. I provided the couple with free technical support on the side, and they were very grateful; at that moment, at least, I felt that the true meaning of the competition lay not in rankings, but in helping those who genuinely need it. Yet, Trae—and ByteDance—you have truly betrayed the original intent behind promoting this competition.&lt;/p&gt;

&lt;p&gt;The screenshot shows the logo designed for their app, right? I really like it—it’s a sprouting seed, symbolizing new hope.&lt;/p&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fctaqb61v98shrr5sdyev.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fctaqb61v98shrr5sdyev.png" alt=" " width="800" height="1767"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
    </item>
    <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>
