<?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: David Morin</title>
    <description>The latest articles on DEV Community by David Morin (@davidmorin).</description>
    <link>https://dev.to/davidmorin</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.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3819440%2Fa4b5a2af-046f-41e3-b3ad-921c77189d03.jpg</url>
      <title>DEV Community: David Morin</title>
      <link>https://dev.to/davidmorin</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/davidmorin"/>
    <language>en</language>
    <item>
      <title>How I Run 4 AI Agents in Parallel to Ship Software 3x Faster</title>
      <dc:creator>David Morin</dc:creator>
      <pubDate>Thu, 12 Mar 2026 04:53:10 +0000</pubDate>
      <link>https://dev.to/davidmorin/how-i-run-4-ai-agents-in-parallel-to-ship-software-3x-faster-1c4j</link>
      <guid>https://dev.to/davidmorin/how-i-run-4-ai-agents-in-parallel-to-ship-software-3x-faster-1c4j</guid>
      <description>&lt;p&gt;I've been running multiple Claude Code instances in parallel for several months. Not as a novelty — as my primary development workflow. One orchestrator agent breaks a goal into scoped tasks, dispatches them to 4 worker agents running in separate pseudo-terminals, and coordinates their output until the project ships.&lt;/p&gt;

&lt;p&gt;This post covers the architecture patterns, communication protocols, and failure recovery strategies I've developed. Everything here is based on production use, not theory.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Setup
&lt;/h2&gt;

&lt;p&gt;The system is a Node.js app (~350 lines) that spawns N pseudo-terminals via &lt;code&gt;node-pty&lt;/code&gt;, each running an independent Claude Code CLI session. A browser UI (xterm.js over WebSocket) lets you watch all terminals simultaneously. An orchestrating agent — a 5th Claude instance — drives the workers through browser automation and a REST API.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;              +------------------+
              |   ORCHESTRATOR   |
              |  (5th instance)  |
              +--------+---------+
                       |
        +--------------+--------------+
        |              |              |
   +----+----+   +-----+----+   +----+-----+
   | Worker 1 |   | Worker 2 |   | Worker 3  |
   | (Backend)|   | (Frontend)|  | (Testing) |
   +-----------+  +----------+  +-----------+
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each worker runs in its own PTY with a clean environment — parent Claude env vars are stripped to prevent session conflicts. The orchestrator doesn't touch code directly; it delegates everything.&lt;/p&gt;

&lt;h2&gt;
  
  
  Pattern 1: Hub-and-Spoke (Use This by Default)
&lt;/h2&gt;

&lt;p&gt;The orchestrator receives a goal, breaks it into scoped tasks, and dispatches to workers in parallel. Workers report status. The orchestrator resolves conflicts and routes information between them.&lt;/p&gt;

&lt;p&gt;This covers ~80% of use cases. A feature build with frontend + backend + tests? Hub-and-Spoke. A product launch with content + listing + distribution? Hub-and-Spoke.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;When it breaks down&lt;/strong&gt;: Workers need constant cross-communication. If every other message is a &lt;code&gt;NEED:&lt;/code&gt; request between workers, you need a different pattern.&lt;/p&gt;

&lt;h2&gt;
  
  
  Pattern 2: Pipeline (Assembly Line)
&lt;/h2&gt;

&lt;p&gt;Sequential stages where each stage's output feeds the next:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;+-----------+     +----------+     +----------+     +----------+
| Stage 1   | --&amp;gt; | Stage 2  | --&amp;gt; | Stage 3  | --&amp;gt; | Stage 4  |
| Research  |     | Plan     |     | Build    |     | Verify   |
+-----------+     +----------+     +----------+     +----------+
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each stage produces a defined artifact with a contract specifying format, location, and completeness criteria. The orchestrator validates the artifact before passing it downstream.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Key insight&lt;/strong&gt;: Stages can have internal parallelism. Stage 3 (Build) might use Hub-and-Spoke internally with 3 workers, while the overall flow remains sequential.&lt;/p&gt;

&lt;h2&gt;
  
  
  Pattern 3: Mesh (Rare, Use Carefully)
&lt;/h2&gt;

&lt;p&gt;Agents communicate directly via shared state (files, JSON state files) with no central orchestrator. Each agent monitors shared state and reacts to changes.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/project/
  state/
    status.json          # Each agent updates its own entry
    contracts/
      api-schema.json    # Agent A writes, Agent B reads
    locks/
      api-routes.lock    # Prevents concurrent modification
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;When to use&lt;/strong&gt;: Almost never. The coordination overhead and race conditions usually aren't worth it. Use Hub-and-Spoke with a responsive orchestrator instead.&lt;/p&gt;

&lt;h2&gt;
  
  
  Pattern 4: Supervisor Chain (For Large Projects)
&lt;/h2&gt;

&lt;p&gt;A meta-orchestrator delegates to team leads, who delegate to workers:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;            +------------------+
            | META-ORCHESTRATOR|
            +--------+---------+
                     |
          +----------+----------+
          |                     |
 +--------+--------+  +--------+--------+
 | TEAM LEAD:      |  | TEAM LEAD:      |
 | Frontend        |  | Backend         |
 +----+-------+----+  +----+-------+----+
      |       |             |       |
   +--+--+ +--+--+      +--+--+ +--+--+
   |  W1 | |  W2 |      |  W3 | |  W4 |
   +-----+ +-----+      +-----+ +-----+
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This solves context window bloat. A single orchestrator managing 8 agents will run out of context. The hierarchy keeps each node's scope manageable. Cross-team communication goes through team leads, never direct worker-to-worker.&lt;/p&gt;

&lt;h2&gt;
  
  
  Pattern 5: Swarm (Self-Organizing)
&lt;/h2&gt;

&lt;p&gt;A shared task board lists available work items. Agents self-assign based on capabilities and availability. When an agent finishes, it picks the next task.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"tasks"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"task-001"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"available"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"description"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Research competitor pricing"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"requires"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"web-search"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"assigned_to"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"task-002"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"in-progress"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"description"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Build landing page"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"assigned_to"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"agent-3"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Best for&lt;/strong&gt;: Unknown scope. "Find and fix all accessibility issues in the app" — you don't know how many issues exist or where they are, so let agents self-discover and self-assign.&lt;/p&gt;

&lt;h3&gt;
  
  
  Choosing Your Pattern
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Scenario&lt;/th&gt;
&lt;th&gt;Pattern&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Build a feature (frontend + backend + tests)&lt;/td&gt;
&lt;td&gt;Hub-and-Spoke&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Research → plan → build → deploy&lt;/td&gt;
&lt;td&gt;Pipeline&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Tightly coupled API + client&lt;/td&gt;
&lt;td&gt;Mesh (reluctantly)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Full product build, 8+ agents&lt;/td&gt;
&lt;td&gt;Supervisor Chain&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;"Fix all the X in the codebase"&lt;/td&gt;
&lt;td&gt;Swarm&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;The golden rule&lt;/strong&gt;: Start with Hub-and-Spoke. Upgrade only when you hit its limits.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Communication Protocol
&lt;/h2&gt;

&lt;p&gt;This is the single most important part of the system. Free-form agent output kills orchestration. When an agent says "I think I'm mostly done with the API," the orchestrator has no idea whether it can start the next phase.&lt;/p&gt;

&lt;p&gt;Structured protocols eliminate ambiguity. The orchestrator can parse status lines programmatically.&lt;/p&gt;

&lt;h3&gt;
  
  
  Status Lines
&lt;/h3&gt;

&lt;p&gt;Every worker ends its task with exactly one:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;STATUS: DONE — [what was accomplished] + [evidence]
STATUS: BLOCKED — [exactly what you need to proceed]
STATUS: ERROR — [what failed, what you tried, suggested fix]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Good &lt;code&gt;DONE&lt;/code&gt; examples:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;STATUS: DONE — Built REST API with 6 endpoints, all tests pass (23/23), server running on port 3001
STATUS: DONE — Research complete, findings in /tmp/research-output.md (2,400 words, 15 sources cited)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Bad &lt;code&gt;DONE&lt;/code&gt; examples:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;STATUS: DONE — I think the API is working
STATUS: DONE — Everything looks good
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The difference: good status lines include &lt;strong&gt;what&lt;/strong&gt; was done AND &lt;strong&gt;proof&lt;/strong&gt; it works.&lt;/p&gt;

&lt;h3&gt;
  
  
  Progress Heartbeats
&lt;/h3&gt;

&lt;p&gt;For tasks longer than ~2 minutes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;PROGRESS: [X/Y] — [what just completed]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Without these, the orchestrator can't distinguish "working" from "stuck."&lt;/p&gt;

&lt;h3&gt;
  
  
  Build Status
&lt;/h3&gt;

&lt;p&gt;After any code change:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;BUILD: PASS
BUILD: FAIL — [error summary]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Rule&lt;/strong&gt;: Never proceed past a &lt;code&gt;BUILD: FAIL&lt;/code&gt;. Fix it first. This is non-negotiable — a broken build poisons everything downstream.&lt;/p&gt;

&lt;h3&gt;
  
  
  Cross-Agent Communication
&lt;/h3&gt;

&lt;p&gt;When an agent needs something from another agent's scope:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;NEED: /src/types/api.ts — Need the UserProfile type exported for frontend components
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When an agent produces an interface others will consume:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;CONTRACT: REST API endpoints for user management
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// GET /users — Response: { users: User[], total: number }&lt;/span&gt;
&lt;span class="c1"&gt;// POST /users — Body: { name: string, email: string }&lt;/span&gt;

&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;User&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;createdAt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&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;The orchestrator copies &lt;code&gt;NEED&lt;/code&gt; requests to the appropriate worker and broadcasts &lt;code&gt;CONTRACT&lt;/code&gt; definitions to all dependent workers.&lt;/p&gt;

&lt;h3&gt;
  
  
  Orchestrator-Side Parsing
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Worker Says&lt;/th&gt;
&lt;th&gt;Orchestrator Does&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;STATUS: DONE&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Verify evidence, mark complete, unblock dependents&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;STATUS: BLOCKED&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Provide what's needed or reassign&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;STATUS: ERROR&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Read suggested fix, retry with guidance or reassign&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;NEED: X from T3&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Copy request to T3's next prompt&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;CONTRACT: schema&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Copy to all dependent workers&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;BUILD: FAIL&lt;/code&gt; (2+ times)&lt;/td&gt;
&lt;td&gt;Intervene — the worker is stuck in a loop&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  PTY Isolation and Status Detection
&lt;/h2&gt;

&lt;p&gt;Each agent runs in its own pseudo-terminal with environment isolation:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ptyProcess&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;pty&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;spawn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;shell&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;xterm-256color&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;cols&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;120&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;rows&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;cwd&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;projectDir&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;env&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;cleanEnv&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="c1"&gt;// Parent Claude vars stripped&lt;/span&gt;
    &lt;span class="na"&gt;TERM&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;xterm-256color&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&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;The server buffers each terminal's output (rolling 10KB window) and runs status detection every 2 seconds by parsing ANSI-stripped output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;detectStatus&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;recentOutput&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;text&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;stripAnsi&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;recentOutput&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;lines&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;Boolean&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;last50&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;lines&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;slice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="c1"&gt;// Idle: prompt visible, no active tool calls&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;hasPrompt&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;recentWork&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;idle&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="c1"&gt;// Waiting: permission prompts detected&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/accept edits|allow bash|&lt;/span&gt;&lt;span class="se"&gt;\(&lt;/span&gt;&lt;span class="sr"&gt;y&lt;/span&gt;&lt;span class="se"&gt;\/&lt;/span&gt;&lt;span class="sr"&gt;n&lt;/span&gt;&lt;span class="se"&gt;\)&lt;/span&gt;&lt;span class="sr"&gt;/i&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;last50&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;waiting_approval&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="c1"&gt;// Working: tool calls in progress&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/Bash&lt;/span&gt;&lt;span class="se"&gt;\(&lt;/span&gt;&lt;span class="sr"&gt;|Read&lt;/span&gt;&lt;span class="se"&gt;\(&lt;/span&gt;&lt;span class="sr"&gt;|Edit&lt;/span&gt;&lt;span class="se"&gt;\(&lt;/span&gt;&lt;span class="sr"&gt;|Write&lt;/span&gt;&lt;span class="se"&gt;\(&lt;/span&gt;&lt;span class="sr"&gt;/i&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;last50&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;working&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="c1"&gt;// Done/Blocked: structured status lines&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/STATUS: DONE/i&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;last50&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;done&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/STATUS: BLOCKED/i&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;last50&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;blocked&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;working&lt;/span&gt;&lt;span class="dl"&gt;'&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;It's regex-based pattern matching against raw terminal output. Not elegant, but reliable. The main gotcha is Claude's status bar noise — spinner characters, MCP connection messages, effort indicators — which you need to filter out before checking for actual content.&lt;/p&gt;




&lt;h2&gt;
  
  
  Failure Recovery
&lt;/h2&gt;

&lt;p&gt;Things that &lt;strong&gt;will&lt;/strong&gt; fail in multi-agent systems:&lt;/p&gt;

&lt;h3&gt;
  
  
  Context Compaction
&lt;/h3&gt;

&lt;p&gt;AI agents have finite context windows. During long tasks, the system compresses earlier conversation history. The agent literally forgets what it did.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Symptoms&lt;/strong&gt;: Agent repeats completed work, asks answered questions, contradicts its earlier output.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The protocol&lt;/strong&gt;:&lt;/p&gt;

&lt;p&gt;Workers that detect disorientation emit:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;STATUS: BLOCKED — context compacted, need task re-orientation
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The orchestrator re-injects a summary:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;Your context was compacted. Here's your state:

&lt;span class="gs"&gt;**Original task**&lt;/span&gt;: Build the REST API
&lt;span class="gs"&gt;**Completed**&lt;/span&gt;: Schema created, 4/6 endpoints built, tests for first 4 passing
&lt;span class="gs"&gt;**Next step**&lt;/span&gt;: Build PUT /users/:id and DELETE /users/:id
&lt;span class="gs"&gt;**Files modified**&lt;/span&gt;: src/api/routes.ts, src/models/user.ts
&lt;span class="gs"&gt;**Build status**&lt;/span&gt;: PASS
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Prevention&lt;/strong&gt;: Have workers write checkpoint files after each major step. If context compacts, they can read the checkpoint to self-recover before reporting BLOCKED.&lt;/p&gt;

&lt;h3&gt;
  
  
  Agent Loops
&lt;/h3&gt;

&lt;p&gt;An agent gets stuck applying the same failing fix repeatedly.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Detection&lt;/strong&gt;: &lt;code&gt;BUILD: FAIL&lt;/code&gt; more than 2 times with the same error, or progress hasn't advanced in 3+ minutes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Recovery&lt;/strong&gt;: Stop the agent. Don't let it burn more tokens. Re-read what it was trying to do, diagnose the root cause yourself, and re-dispatch with a different approach.&lt;/p&gt;

&lt;p&gt;The agent-side equivalent: if you've tried the same fix twice and it's still broken, &lt;strong&gt;stop&lt;/strong&gt;. Report &lt;code&gt;STATUS: ERROR&lt;/code&gt; with what you tried and a suggested alternative approach. Don't loop.&lt;/p&gt;

&lt;h3&gt;
  
  
  Bad Output Propagation
&lt;/h3&gt;

&lt;p&gt;The most dangerous failure: an agent produces incorrect output, and downstream agents build on it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Prevention&lt;/strong&gt;: Validation gates between stages.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;+----------+     VALIDATE     +----------+     VALIDATE     +----------+
| Stage 1  | ----&amp;gt; GATE ----&amp;gt; | Stage 2  | ----&amp;gt; GATE ----&amp;gt; | Stage 3  |
+----------+                  +----------+                  +----------+
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Before passing output downstream, check: Does the file exist? Is it non-empty? Is the format valid? Does the content match the contract? Does the agent's evidence check out?&lt;/p&gt;

&lt;p&gt;If any check fails, re-run the stage. Do not proceed with bad input.&lt;/p&gt;

&lt;h3&gt;
  
  
  Deadlocks
&lt;/h3&gt;

&lt;p&gt;Agent A waits for Agent B, who waits for Agent A.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Resolution&lt;/strong&gt;: The orchestrator detects the cycle and breaks it by having one agent produce a temporary stub. The other proceeds with the stub. Both update to final versions later.&lt;/p&gt;

&lt;h3&gt;
  
  
  Coordination Failures
&lt;/h3&gt;

&lt;p&gt;Two agents modify the same file simultaneously.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Prevention&lt;/strong&gt;: File ownership tables in the orchestrator prompt.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;| File/Directory | Owner |
|---------------|-------|
| /src/api/     | T1    |
| /src/frontend/| T2    |
| /src/shared/  | T1 (T2 reads only) |
| /tests/       | T3    |
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you need a change in another agent's files, use &lt;code&gt;NEED:&lt;/code&gt;. Never modify files you don't own, even if it seems faster.&lt;/p&gt;




&lt;h2&gt;
  
  
  Tool Integration Hierarchy
&lt;/h2&gt;

&lt;p&gt;Not all tools are equal:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Priority 1: Native MCP tools     (fastest, most reliable)
Priority 2: API calls via code    (reliable, needs auth)
Priority 3: Browser automation    (flexible, but brittle)
Priority 4: Manual workarounds    (last resort)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If an MCP server exists for the task, use it. Don't browser-automate something that has a direct integration.&lt;/p&gt;

&lt;h3&gt;
  
  
  MCP Configuration
&lt;/h3&gt;

&lt;p&gt;MCP servers are configured in &lt;code&gt;.mcp.json&lt;/code&gt; in your project root. Each agent in the project directory inherits these tools automatically:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"mcpServers"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"github"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"command"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"npx"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"args"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"-y"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"@modelcontextprotocol/server-github"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"env"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"GITHUB_PERSONAL_ACCESS_TOKEN"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"ghp_..."&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Tool Scoping
&lt;/h3&gt;

&lt;p&gt;Don't give every agent every tool. Assign tools based on scope:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Builder agent&lt;/strong&gt;: filesystem, code editor — nothing else&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Browser agent&lt;/strong&gt;: browser automation, filesystem — for web interactions&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Research agent&lt;/strong&gt;: web search, filesystem — for investigation&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Deploy agent&lt;/strong&gt;: deployment CLI, health checks — for shipping&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Agents get confused by tool overload. More tools = more ways to go wrong.&lt;/p&gt;




&lt;h2&gt;
  
  
  Graceful Degradation
&lt;/h2&gt;

&lt;p&gt;When you can't recover, degrade rather than fail completely:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Can another agent absorb the failed work? (merge scopes)&lt;/li&gt;
&lt;li&gt;Can you ship a reduced version? (skip the failing component)&lt;/li&gt;
&lt;li&gt;Can the orchestrator do it manually? (direct execution)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Priority: &lt;strong&gt;Ship something &amp;gt; ship everything &amp;gt; ship nothing.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Communicate clearly: "T3 failed on integration tests. Proceeding with unit test coverage only. Integration tests will need manual verification."&lt;/p&gt;




&lt;h2&gt;
  
  
  What I Didn't Cover
&lt;/h2&gt;

&lt;p&gt;This post covers the architecture, protocol, and failure modes — roughly 80% of what you need. What's missing:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;25+ copy-paste prompt templates&lt;/strong&gt; for orchestrators, workers, research agents, testing agents, deployment agents, browser automation agents, context recovery, conflict resolution, and product launch coordination&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;6 complete end-to-end playbooks&lt;/strong&gt; with exact agent assignments, dependency graphs, and timelines for: digital product launch (90 min), full-stack feature build (2-3 hrs), research deep dive (45 min), content sprint (60 min), bug triage swarm (30 min), and competitive analysis (60 min)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Custom MCP server patterns&lt;/strong&gt; with TypeScript starter code&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Orchestrator prompt internals&lt;/strong&gt; — the exact prompt structure I use for the conductor agent&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I packaged all of this into the &lt;a href="https://melodavid4.gumroad.com/l/ai-agent-blueprint" rel="noopener noreferrer"&gt;AI Agent Orchestration Blueprint&lt;/a&gt; — a 7-chapter markdown bundle ($12) that works in Obsidian, Notion, or any markdown viewer. It's the complete reference I wish existed when I started building this system.&lt;/p&gt;




&lt;h2&gt;
  
  
  Core Principles (TL;DR)
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Scope isolation beats shared context.&lt;/strong&gt; Agents that own specific files produce better output than agents that touch everything.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Structured communication beats prose.&lt;/strong&gt; &lt;code&gt;STATUS: DONE — tests pass (14/14)&lt;/code&gt; &amp;gt; "I think I'm done."&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Autonomy with guardrails.&lt;/strong&gt; Workers self-recover from errors but escalate when truly blocked.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Evidence over assertion.&lt;/strong&gt; Never accept "it should work." Require proof.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Parallel by default.&lt;/strong&gt; If two tasks don't depend on each other, run them simultaneously.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The patterns here work with Claude Code, GPT, Gemini, or any LLM with tool access. The hard problems in agent orchestration aren't model-specific — they're about process isolation, state detection, and coordination. Those are engineering problems, and they have engineering solutions.&lt;/p&gt;

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