<?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>Forem: Jonathan Melton</title>
    <description>The latest articles on Forem by Jonathan Melton (@jonathanmeltonfusional).</description>
    <link>https://forem.com/jonathanmeltonfusional</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%2F3806716%2F17aa3879-e4be-4f98-985d-3332d781ad65.png</url>
      <title>Forem: Jonathan Melton</title>
      <link>https://forem.com/jonathanmeltonfusional</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/jonathanmeltonfusional"/>
    <language>en</language>
    <item>
      <title># 9 Seconds. One AI Agent. A Wiped Production Database.</title>
      <dc:creator>Jonathan Melton</dc:creator>
      <pubDate>Mon, 11 May 2026 06:54:38 +0000</pubDate>
      <link>https://forem.com/jonathanmeltonfusional/-9-seconds-one-ai-agent-a-wiped-production-database-4i7a</link>
      <guid>https://forem.com/jonathanmeltonfusional/-9-seconds-one-ai-agent-a-wiped-production-database-4i7a</guid>
      <description>&lt;p&gt;In April 2026, a team using PocketOS watched Claude Opus 4.6 — running via Cursor — delete their entire production database and every backup in under 10 seconds.&lt;/p&gt;

&lt;p&gt;Not a partial delete. Not a staging environment. Production data, gone. Backups, gone. Nine seconds.&lt;/p&gt;

&lt;p&gt;The root cause wasn't the model. It wasn't even the code. It was three infrastructure decisions that nobody thought to question:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The agent had a blanket API token with no scope limits&lt;/li&gt;
&lt;li&gt;There was no blast radius constraint on what it could touch&lt;/li&gt;
&lt;li&gt;Backups were colocated with the source data
The agent did exactly what it was told. Nobody told it what it wasn't allowed to do.&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  This Isn't Isolated
&lt;/h2&gt;

&lt;p&gt;Two months earlier, DataTalks.Club had a similar moment. Claude Code executed &lt;code&gt;terraform destroy&lt;/code&gt; and wiped 2.5 years of production data in a single command.&lt;/p&gt;

&lt;p&gt;Earlier this year, researchers found over 5,000 AI-generated apps publicly accessible on the open web — exposing hospital records, bank transaction logs, and retail data. Not because the AI was malicious. Because nobody built the guardrails.&lt;/p&gt;

&lt;p&gt;The pattern is consistent: the model works exactly as designed. The governance layer doesn't exist.&lt;/p&gt;

&lt;p&gt;A 2026 Gravitee survey found that only 24.4% of organizations have full visibility into which AI agents are communicating with what systems. More than half of deployed agents run with zero security oversight or logging. Eighty-two percent of executives said they were confident their policies protect against unauthorized agent actions — but most have no execution-layer controls. Just policies.&lt;/p&gt;

&lt;p&gt;Policies don't stop &lt;code&gt;terraform destroy&lt;/code&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Real Problem Isn't the AI
&lt;/h2&gt;

&lt;p&gt;Every post-mortem on incidents like PocketOS points to the same structural gap: &lt;strong&gt;there's nothing between the LLM and the tools it can call.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The model reasons. The tool executes. There's no layer in the middle asking: &lt;em&gt;should this be happening right now?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;MCP (Model Context Protocol) made it dramatically easier to give AI agents access to tools. That's the whole point — it's powerful. But power without constraint is just risk waiting for a trigger.&lt;/p&gt;

&lt;p&gt;The MCP ecosystem hit 97 million monthly SDK downloads as of March 2026. 78% of enterprise AI teams have at least one MCP agent in production. The CIS published an MCP Companion Guide in April 2026 specifically because enterprises are scared and scrambling for governance frameworks.&lt;/p&gt;

&lt;p&gt;The adoption is real. The governance isn't.&lt;/p&gt;




&lt;h2&gt;
  
  
  What Governance Actually Looks Like at the Execution Layer
&lt;/h2&gt;

&lt;p&gt;Policy-level governance (acceptable use documents, model selection guidelines) is necessary but insufficient. What protects against a PocketOS-style event is execution-layer control — enforcement that happens &lt;em&gt;at the moment a tool is called&lt;/em&gt;, not in a document someone agreed to last quarter.&lt;/p&gt;

&lt;p&gt;At minimum, a governed MCP setup needs:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Tool scoping.&lt;/strong&gt; Not every agent needs access to every tool. A customer support agent querying a knowledge base doesn't need write access to your database. Scope by role. Enforce it at the gateway, not the prompt.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Blast radius limits.&lt;/strong&gt; Define what each agent can touch. Separate environments. Separate tokens with separate permissions. If an agent only needs to read, it only gets read.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Audit logging.&lt;/strong&gt; Every tool call, every parameter, every response — logged with enough detail to reconstruct what happened. The PocketOS team couldn't answer "what exactly did it call and when?" Logs answer that.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Request filtering.&lt;/strong&gt; Destructive operations (deletes, drops, destroys) should require a second confirmation path, not just model reasoning. The model thought the delete was appropriate. A filter that flags &lt;code&gt;DELETE *&lt;/code&gt; or &lt;code&gt;terraform destroy&lt;/code&gt; before execution is a different kind of check.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Separation of data and backups.&lt;/strong&gt; Infrastructure basics that become critical when an agent has write access to both.&lt;/p&gt;

&lt;p&gt;None of this is exotic. All of it is skipped constantly because MCP adoption is outpacing the tooling to govern it.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Windows Problem Makes This Worse
&lt;/h2&gt;

&lt;p&gt;If you're running MCP infrastructure on Windows — which a significant chunk of the developer market is — you're fighting a second battle before you even get to governance.&lt;/p&gt;

&lt;p&gt;I've documented six Windows-specific MCP failure modes that don't exist on Linux: path expansion bugs, Docker socket misconfiguration, BOM encoding issues, server registry limits, absolute path requirements, and WSL2 VHDX placement. Add a seventh: MCP Python SDK DNS rebinding protection (the &lt;code&gt;TransportSecuritySettings&lt;/code&gt; issue) that silently rejects Tailscale connections with a 421 because the IP isn't in the hardcoded allowlist.&lt;/p&gt;

&lt;p&gt;These aren't documented anywhere official. They're discovered by whoever is unlucky enough to spend three days debugging what should have been a one-hour setup.&lt;/p&gt;

&lt;p&gt;When your foundation is unstable, governance becomes almost impossible. You're too busy keeping the servers running to think about what they're allowed to do.&lt;/p&gt;




&lt;h2&gt;
  
  
  What I Built to Fix This
&lt;/h2&gt;

&lt;p&gt;FusionAL is a unified MCP gateway I built after hitting every one of those failure modes personally. It runs on Windows, manages the Docker configuration that causes most Windows MCP failures, and centralizes tool access so you can actually reason about scope and logging in one place instead of per-server.&lt;/p&gt;

&lt;p&gt;The governance layer is the point. Not just "here's a gateway that runs your tools." Here's a gateway where you can define what each agent can see, log every tool call, and filter requests before they execute.&lt;/p&gt;

&lt;p&gt;The PocketOS wipeout would have looked different with a gateway in the path. Not because the gateway would have known the delete was wrong — it wouldn't. But because:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The agent's token would have been scoped to what it actually needed&lt;/li&gt;
&lt;li&gt;The delete operation would have been flagged as a destructive pattern&lt;/li&gt;
&lt;li&gt;Backups would have been on a separate access path the agent couldn't reach&lt;/li&gt;
&lt;li&gt;The entire call chain would be in a log that tells you exactly what happened
That's not magic. That's architecture.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  The Window Is Now
&lt;/h2&gt;

&lt;p&gt;The CIS MCP Companion Guide dropped April 20, 2026. EU AI Act enforcement starts August 2. Microsoft is running VS Live sessions this summer teaching .NET developers MCP basics — and those developers are going to ask "how do we govern this?"&lt;/p&gt;

&lt;p&gt;The enterprises asking those questions right now don't have answers yet. The consulting market for done-for-you MCP governance installs is essentially empty below $25K.&lt;/p&gt;

&lt;p&gt;If you're building AI infrastructure, governance isn't the feature you add after you ship. It's the feature that determines whether you have a production incident story or a post-mortem.&lt;/p&gt;




&lt;p&gt;If you're dealing with Windows MCP failures, governance gaps, or token bloat eating your context window before you've asked anything — I'm building this in public at &lt;a href="https://fusional.dev" rel="noopener noreferrer"&gt;fusional.dev&lt;/a&gt; and happy to talk through what you're hitting.&lt;/p&gt;

&lt;p&gt;The nine-second wipeout was preventable. Most of them are.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>security</category>
      <category>devops</category>
      <category>mcp</category>
    </item>
    <item>
      <title>Why Your MCP Setup Keeps Timing Out in 60 Seconds (And How I Fixed It on Windows)</title>
      <dc:creator>Jonathan Melton</dc:creator>
      <pubDate>Thu, 19 Mar 2026 03:39:57 +0000</pubDate>
      <link>https://forem.com/jonathanmeltonfusional/why-your-mcp-setup-keeps-timing-out-in-60-seconds-and-how-i-fixed-it-on-windows-367a</link>
      <guid>https://forem.com/jonathanmeltonfusional/why-your-mcp-setup-keeps-timing-out-in-60-seconds-and-how-i-fixed-it-on-windows-367a</guid>
      <description>&lt;p&gt;Every developer hits this wall: add more than 8 MCP servers to Claude Desktop (or Cursor, or VSCode) → it spins for exactly 60 seconds → red X, "timed out." It happens on every machine with limited resources. My i5-7300HQ laptop? Poster child for the problem.&lt;/p&gt;

&lt;p&gt;Tutorials skip it. AWS/Finch articles ignore Windows entirely. Docker's own docs don't cover it. But the problem is real, and I spent weeks diagnosing every failure mode until I fixed them all.&lt;/p&gt;

&lt;p&gt;I documented &lt;strong&gt;6 Windows-specific MCP failure modes&lt;/strong&gt; that nobody else has written about, then built a single Docker gateway that loads 150+ tools without hitting the timeout. Every single time.&lt;/p&gt;




&lt;h2&gt;
  
  
  The 6 Real Killers
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. BOM in &lt;code&gt;claude_desktop_config.json&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;What you see:&lt;/strong&gt; You edit the config in PowerShell, save it, restart Claude Desktop. Nothing changes. No error message. Claude just ignores your config entirely.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why it happens:&lt;/strong&gt; PowerShell's &lt;code&gt;Out-File -Encoding UTF8&lt;/code&gt; adds an invisible 3-byte BOM (byte order mark) at the start of the file. Claude's JSON parser chokes on those bytes without telling you.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How to check:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$bytes&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;System.IO.File&lt;/span&gt;&lt;span class="p"&gt;]::&lt;/span&gt;&lt;span class="n"&gt;ReadAllBytes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$&lt;/span&gt;&lt;span class="nn"&gt;env&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nv"&gt;APPDATA&lt;/span&gt;&lt;span class="s2"&gt;\Claude\claude_desktop_config.json"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="kr"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$bytes&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-eq&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="n"&gt;xEF&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-and&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$bytes&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-eq&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;0xBB&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-and&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$bytes&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-eq&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;0xBF&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="n"&gt;Write-Host&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"BOM detected — this is your problem"&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;The fix:&lt;/strong&gt; Always write config with BOM-free UTF-8:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;System.IO.File&lt;/span&gt;&lt;span class="p"&gt;]::&lt;/span&gt;&lt;span class="n"&gt;WriteAllText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$&lt;/span&gt;&lt;span class="nn"&gt;env&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nv"&gt;APPDATA&lt;/span&gt;&lt;span class="s2"&gt;\Claude\claude_desktop_config.json"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nv"&gt;$content&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="n"&gt;New-Object&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;System.Text.UTF8Encoding&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;$false&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c"&gt;# $false = no BOM&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;
  
  
  2. &lt;code&gt;%USERPROFILE%&lt;/code&gt; Doesn't Expand
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;What you see:&lt;/strong&gt; Your config references &lt;code&gt;%USERPROFILE%\some\path&lt;/code&gt; and the server never starts. No error — just silence.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why it happens:&lt;/strong&gt; Claude Desktop doesn't expand Windows environment variables in the JSON config. It reads &lt;code&gt;%USERPROFILE%&lt;/code&gt; as a literal string and tries to find a directory with percent signs in the name.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The fix:&lt;/strong&gt; Hardcode absolute paths everywhere. No exceptions.&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="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;"C:&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s2"&gt;Users&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s2"&gt;puddi&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s2"&gt;AppData&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s2"&gt;Local&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s2"&gt;Programs&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s2"&gt;node.exe"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Not:&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="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;"%USERPROFILE%&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s2"&gt;AppData&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s2"&gt;Local&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s2"&gt;Programs&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s2"&gt;node.exe"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  3. &lt;code&gt;docker.exe&lt;/code&gt; Needs the Full Absolute Path
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;What you see:&lt;/strong&gt; Config looks correct, Docker is running, but the MCP server won't start.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why it happens:&lt;/strong&gt; Claude Desktop launches child processes without inheriting the system PATH. So &lt;code&gt;"command": "docker"&lt;/code&gt; or even &lt;code&gt;"command": "docker.exe"&lt;/code&gt; fails — it can't find the binary.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The fix:&lt;/strong&gt; Use the full path to &lt;code&gt;docker.exe&lt;/code&gt;:&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="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;"C:&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s2"&gt;Program Files&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s2"&gt;Docker&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s2"&gt;Docker&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s2"&gt;resources&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s2"&gt;bin&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s2"&gt;docker.exe"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Every time. Don't trust PATH.&lt;/p&gt;




&lt;h3&gt;
  
  
  4. Docker Named Pipe vs Unix Socket Mismatch
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;What you see:&lt;/strong&gt; Docker commands work fine in your terminal, but MCP servers that need Docker access inside containers get connection errors.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why it happens:&lt;/strong&gt; Windows Docker Desktop runs through a named pipe (&lt;code&gt;//./pipe/docker_engine&lt;/code&gt;), but containers expect the Unix socket at &lt;code&gt;/var/run/docker.sock&lt;/code&gt;. Named pipes are flaky when passed through to containers via WSL2.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The fix:&lt;/strong&gt; Mount the Unix socket directly. Docker Desktop's WSL2 backend exposes it:&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="s2"&gt;"-v"&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/var/run/docker.sock:/var/run/docker.sock"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Don't use the Windows named pipe. The Unix socket is stable through WSL2 integration.&lt;/p&gt;




&lt;h3&gt;
  
  
  5. Cold-Start Bloat Kills the 60-Second Budget
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;What you see:&lt;/strong&gt; A server works fine after the first load, but on a fresh start (cold boot, after a Docker prune, or first install), it times out.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why it happens:&lt;/strong&gt; Some MCP servers download heavy dependencies on first run. Puppeteer downloads Chromium (~180MB). Python servers pull packages. Node servers run &lt;code&gt;npm install&lt;/code&gt;. All of this happens inside the 60-second initialization window that Claude Desktop enforces. On slower hardware, you're dead.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The fix:&lt;/strong&gt; Pre-bake dependencies into Docker images. If a server needs Chromium, include it in the Dockerfile — don't download it at runtime. For the gateway approach, this is handled by using official Docker MCP images that ship ready to run.&lt;/p&gt;

&lt;p&gt;I removed Puppeteer from my registry entirely after it blew the timeout three times in a row. If you need browser automation, use a pre-built image like &lt;code&gt;browserless/chrome&lt;/code&gt; and connect to it remotely.&lt;/p&gt;




&lt;h3&gt;
  
  
  6. Registry Bloat (The One That Started Everything)
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;What you see:&lt;/strong&gt; You have 8 MCP servers and everything works. You add a 9th. Timeout.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why it happens:&lt;/strong&gt; Claude Desktop initializes all registered servers in parallel on startup. Each server needs CPU time, memory allocation, and potentially network connections. On an i5-7300HQ with 16GB RAM, 8 servers is the practical ceiling before the 60-second timeout hits.&lt;/p&gt;

&lt;p&gt;This isn't a bug — it's a resource constraint. Every server you add steals initialization time from every other server. The relationship is roughly linear until you hit the wall, then it's catastrophic.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The fix:&lt;/strong&gt; This is the one that made me build FusionAL. Instead of registering 8 separate servers, you register &lt;strong&gt;one gateway&lt;/strong&gt; that loads tools from a catalog. One initialization, one process, 150+ tools available.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Fix: One Lean Gateway
&lt;/h2&gt;

&lt;p&gt;FusionAL runs a single &lt;code&gt;docker/mcp-gateway&lt;/code&gt; container that manages everything through a lightweight &lt;code&gt;registry.yaml&lt;/code&gt; + tool catalogs. Cold start drops from "never finishes" to 12-18 seconds.&lt;/p&gt;

&lt;h3&gt;
  
  
  Before (8 registry entries, constant timeouts):
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="c1"&gt;# registry.yaml with 8+ entries&lt;/span&gt;
&lt;span class="na"&gt;servers&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;github&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;...&lt;/span&gt;
  &lt;span class="na"&gt;filesystem&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;...&lt;/span&gt;
  &lt;span class="na"&gt;redis&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;...&lt;/span&gt;
  &lt;span class="na"&gt;postgres&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;...&lt;/span&gt;
  &lt;span class="na"&gt;puppeteer&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;...&lt;/span&gt;    &lt;span class="c1"&gt;# ← downloads Chrome, blows timeout&lt;/span&gt;
  &lt;span class="na"&gt;slack&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;...&lt;/span&gt;
  &lt;span class="na"&gt;notion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;...&lt;/span&gt;
  &lt;span class="na"&gt;custom-api&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;...&lt;/span&gt;
  &lt;span class="na"&gt;analytics&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;...&lt;/span&gt;    &lt;span class="c1"&gt;# ← 9th server, guaranteed timeout&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  After (1 registry entry, 150+ tools):
&lt;/h3&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;"fusional-gateway"&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;"C:&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s2"&gt;Program Files&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s2"&gt;Docker&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s2"&gt;Docker&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s2"&gt;resources&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s2"&gt;bin&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s2"&gt;docker.exe"&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="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"run"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"-i"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"--rm"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"-v"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/var/run/docker.sock:/var/run/docker.sock"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"-v"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"C:/Users/puddi/.docker/mcp:/mcp"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"docker/mcp-gateway"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"--catalog=/mcp/catalogs/docker-mcp.yaml"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"--catalog=/mcp/catalogs/custom.yaml"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"--registry=/mcp/registry.yaml"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"--config=/mcp/config.yaml"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"--transport=stdio"&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;p&gt;One process. One initialization. All 150+ tools available through the gateway.&lt;/p&gt;

&lt;h3&gt;
  
  
  Writing this config safely (no BOM):
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$config&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Get-Content&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;\my-config.json&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-Raw&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;System.IO.File&lt;/span&gt;&lt;span class="p"&gt;]::&lt;/span&gt;&lt;span class="n"&gt;WriteAllText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$&lt;/span&gt;&lt;span class="nn"&gt;env&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nv"&gt;APPDATA&lt;/span&gt;&lt;span class="s2"&gt;\Claude\claude_desktop_config.json"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nv"&gt;$config&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="n"&gt;New-Object&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;System.Text.UTF8Encoding&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;$false&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;h2&gt;
  
  
  Quick Reference: All 6 Fixes
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Failure Mode&lt;/th&gt;
&lt;th&gt;Symptom&lt;/th&gt;
&lt;th&gt;Fix&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;BOM encoding&lt;/td&gt;
&lt;td&gt;Config silently ignored&lt;/td&gt;
&lt;td&gt;&lt;code&gt;UTF8Encoding($false)&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Env vars in paths&lt;/td&gt;
&lt;td&gt;Server won't start&lt;/td&gt;
&lt;td&gt;Hardcode absolute paths&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;docker.exe not found&lt;/td&gt;
&lt;td&gt;Silent failure&lt;/td&gt;
&lt;td&gt;Full absolute path to binary&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Named pipe mismatch&lt;/td&gt;
&lt;td&gt;Container can't reach Docker&lt;/td&gt;
&lt;td&gt;Mount &lt;code&gt;/var/run/docker.sock&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Cold-start downloads&lt;/td&gt;
&lt;td&gt;Timeout on first run&lt;/td&gt;
&lt;td&gt;Pre-bake deps in Docker images&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Registry bloat (&amp;gt;8 servers)&lt;/td&gt;
&lt;td&gt;60-second timeout&lt;/td&gt;
&lt;td&gt;Single gateway, catalog-based loading&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  What I'm Building on Top of This
&lt;/h2&gt;

&lt;p&gt;The gateway solves the reliability problem. But managing a fleet of MCP servers — knowing which ones are running, which ones crashed, queuing new builds — that's the next layer.&lt;/p&gt;

&lt;p&gt;I'm building &lt;a href="https://github.com/JRM-FusionAL/FusionAL" rel="noopener noreferrer"&gt;FusionAL&lt;/a&gt;, an open-source MCP operations gateway that wraps all of this into one Docker command. It handles the 6 failure modes automatically and gives you a clean interface for managing your MCP infrastructure.&lt;/p&gt;

&lt;p&gt;If you've hit other Windows-specific MCP issues I didn't cover here, drop them in the comments. I'm actively documenting every edge case I find.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Find me on &lt;a href="https://github.com/JRM-FusionAL" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt; or &lt;a href="https://x.com/2EfinAwesome" rel="noopener noreferrer"&gt;X (@2EfinAwesome)&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>mcp</category>
      <category>docker</category>
      <category>microsoft</category>
      <category>ai</category>
    </item>
    <item>
      <title>I Had Claude Build Me a Full AI Marketing Department — Here's Exactly How I Did It</title>
      <dc:creator>Jonathan Melton</dc:creator>
      <pubDate>Fri, 13 Mar 2026 09:28:21 +0000</pubDate>
      <link>https://forem.com/jonathanmeltonfusional/i-had-claude-build-me-a-full-ai-marketing-department-heres-exactly-how-i-did-it-f3</link>
      <guid>https://forem.com/jonathanmeltonfusional/i-had-claude-build-me-a-full-ai-marketing-department-heres-exactly-how-i-did-it-f3</guid>
      <description>&lt;h2&gt;
  
  
  Real talk: I didn't write most of this code.
&lt;/h2&gt;

&lt;p&gt;I directed it. I described what I wanted, reviewed what came back, pushed back when it was wrong, and kept iterating until it worked. That's the actual skill I want to talk about — because if you're still treating Claude like a search engine that writes code snippets, you're leaving a lot on the table.&lt;/p&gt;

&lt;p&gt;Here's what we built together and how the conversation actually went.&lt;/p&gt;




&lt;h2&gt;
  
  
  What I Wanted
&lt;/h2&gt;

&lt;p&gt;I was tired of asking AI for marketing help and getting back the kind of copy that sounds like it was written by a committee of robots. You know the type — "Unlock Your Potential Today!" Nobody buys that.&lt;/p&gt;

&lt;p&gt;The real problem is that marketing isn't a one-prompt job. It's a team sport. You need someone thinking about strategy, someone thinking about keywords, someone writing the actual copy, and someone planning the social calendar. When you smash all that into a single prompt, you get a single-perspective answer that misses everything it wasn't specifically asked about.&lt;/p&gt;

&lt;p&gt;So I told Claude what I actually wanted: build me a team.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Prompt That Started It
&lt;/h2&gt;

&lt;p&gt;I didn't give Claude a spec doc. I just described the problem:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"I want a Python CLI that runs multiple specialized AI agents sequentially. Each agent has a specific marketing role — CMO, SEO, copywriter, social media, email, analyst. Each one should receive the previous agents' output as context so they're building on each other's work, not starting from scratch. Use Claude Opus 4.6 with streaming and adaptive thinking."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That's it. No architecture diagram. No file structure. Just the outcome I wanted and one key constraint: sequential context passing.&lt;/p&gt;

&lt;p&gt;What came back was a working base. Not perfect. But working.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Architecture Claude Landed On
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;main.py                 # CLI + orchestrator
agents/
  base.py               # MarketingAgent base class
  cmo.py                # Campaign strategy
  seo.py                # Keyword + content strategy
  copywriter.py         # Landing pages, ads, taglines
  social.py             # Content calendar, platform playbooks
  email_marketer.py     # Welcome sequences, nurture flows
  analyst.py            # KPI dashboard, A/B roadmap
tools/
  platform_tools.py     # HubSpot, Mailchimp, Buffer, Semrush hooks
campaigns/              # Saved campaign outputs
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Six agents. Each one a specialist. Each one named like a real person on a real team because — honestly — it makes the system prompts better when you write them that way.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Base Agent — This Is the Core
&lt;/h2&gt;

&lt;p&gt;Every agent inherits from one class. The &lt;code&gt;think()&lt;/code&gt; method is the whole game:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MarketingAgent&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;role&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;system_prompt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;emoji&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;🤖&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;role&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;role&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;system_prompt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;system_prompt&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;emoji&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;emoji&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;think&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;task&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;max_tokens&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;4096&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;messages&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;role&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;user&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;content&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;task&lt;/span&gt;&lt;span class="p"&gt;}]&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;messages&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
                &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;role&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;user&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;content&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Context from previous team members:&lt;/span&gt;&lt;span class="se"&gt;\n\n&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="se"&gt;\n\n&lt;/span&gt;&lt;span class="s"&gt;---&lt;/span&gt;&lt;span class="se"&gt;\n\n&lt;/span&gt;&lt;span class="s"&gt;Your task: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;task&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
                &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="p"&gt;]&lt;/span&gt;

        &lt;span class="n"&gt;full_text&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;""&lt;/span&gt;
        &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stream&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;claude-opus-4-6&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;max_tokens&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;max_tokens&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;thinking&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;type&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;adaptive&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
            &lt;span class="n"&gt;system&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;system_prompt&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;stream&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;stream&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;text_stream&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;end&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;flush&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="n"&gt;full_text&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;full_text&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Simple. Take the task, prepend any context from previous agents, stream the response. The context is what makes it not stupid.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Context Handoff — Why This Actually Works
&lt;/h2&gt;

&lt;p&gt;Here's the pipeline in the orchestrator. This is the part I pushed back on Claude about — the first version ran everything in parallel and the output was incoherent because nobody was talking to each other.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# CMO goes first — sets everything
&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;outputs&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;01_cmo&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;agents&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;cmo&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;think&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cmo_task&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# SEO gets the CMO brief
&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;outputs&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;02_seo&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;agents&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;seo&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;think&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;seo_task&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;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;outputs&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;01_cmo&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Copywriter gets CMO + SEO both
&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;outputs&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;03_copy&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;agents&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;copywriter&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;think&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;copy_task&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;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;outputs&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;01_cmo&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n\n&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;outputs&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;02_seo&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Social gets CMO + Copy
&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;outputs&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;04_social&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;agents&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;social&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;think&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;social_task&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;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;outputs&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;01_cmo&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n\n&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;outputs&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;03_copy&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Email gets CMO + Copy
&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;outputs&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;05_email&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;agents&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;email&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;think&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;email_task&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;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;outputs&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;01_cmo&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n\n&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;outputs&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;03_copy&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Analyst gets everything
&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;outputs&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;06_analytics&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;agents&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;analyst&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;think&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;analyst_task&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="sh"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n\n&lt;/span&gt;&lt;span class="s"&gt;---&lt;/span&gt;&lt;span class="se"&gt;\n\n&lt;/span&gt;&lt;span class="sh"&gt;"&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="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;outputs&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;01_cmo&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;outputs&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;02_seo&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;outputs&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;04_social&lt;/span&gt;&lt;span class="sh"&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;When the Copywriter writes your landing page headline, it already knows the positioning the CMO defined, the keywords the SEO specialist identified, and the exact personas. The copy isn't generic because it's not starting from scratch — it's starting from a complete strategic brief written by the agent before it.&lt;/p&gt;

&lt;p&gt;That's what single-prompt marketing AI can't do. It has no team. It's one person trying to do six jobs at once and it shows.&lt;/p&gt;




&lt;h2&gt;
  
  
  What I Had to Correct
&lt;/h2&gt;

&lt;p&gt;A few things Claude got wrong on the first pass that I pushed back on:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Parallel execution.&lt;/strong&gt; First draft ran all agents at once. Looked efficient. Output was a mess because the Copywriter had no idea what the SEO specialist recommended. Told Claude to make it sequential and explained why. Fixed immediately.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Generic system prompts.&lt;/strong&gt; Early versions had vague role descriptions like "you are a marketing expert." I pushed for specificity — actual deliverables listed, actual output format expected, written from the perspective of a real person with a real title. The output quality jumped noticeably.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. No context injection on quick mode.&lt;/strong&gt; The quick campaign (CMO + Copywriter only) wasn't passing the CMO brief to the Copywriter. Caught it in testing. One-line fix but it's the whole point of the system.&lt;/p&gt;

&lt;p&gt;This is what directing AI actually looks like. It's not magic prompt engineering. It's reviewing output, identifying what's wrong, and being specific about how to fix it.&lt;/p&gt;




&lt;h2&gt;
  
  
  What It Produces
&lt;/h2&gt;

&lt;p&gt;Run a full campaign and you get six connected deliverables:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;CMO output&lt;/strong&gt; — positioning, personas, channel mix, messaging pillars, KPIs&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;SEO output&lt;/strong&gt; — keyword clusters, search intent analysis, content briefs for top 3 pages, technical checklist&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Copywriter output&lt;/strong&gt; — hero copy, full landing page, 3 Google ad variations, 3 Meta ad variations, brand voice guide&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Social output&lt;/strong&gt; — 4-week calendar for LinkedIn, Instagram, X, and TikTok with ready-to-post content&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Email output&lt;/strong&gt; — welcome sequence (5 emails), sales sequence (3 emails), re-engagement sequence, newsletter template&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Analyst output&lt;/strong&gt; — KPI dashboard, attribution model, A/B testing roadmap, 90-day benchmarks&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Total output on a full run: somewhere between 8,000 and 12,000 words of interconnected marketing content that actually references itself. The social posts use the same messaging pillars the CMO defined. The email subject lines match the copy angles the Copywriter developed. It coheres.&lt;/p&gt;




&lt;h2&gt;
  
  
  How to Run It
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://gitlab.com/JonathanMelton-FusionAL/ai-marketing-team
&lt;span class="nb"&gt;cd &lt;/span&gt;ai-marketing-team
pip &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-r&lt;/span&gt; requirements.txt
&lt;span class="nb"&gt;cp&lt;/span&gt; .env.example .env
&lt;span class="c"&gt;# Add your ANTHROPIC_API_KEY&lt;/span&gt;

&lt;span class="c"&gt;# Full campaign — all 6 agents&lt;/span&gt;
python main.py campaign &lt;span class="nt"&gt;--product&lt;/span&gt; &lt;span class="s2"&gt;"B2B SaaS for HR teams"&lt;/span&gt; &lt;span class="nt"&gt;--save&lt;/span&gt;

&lt;span class="c"&gt;# Quick mode — CMO + Copywriter only&lt;/span&gt;
python main.py campaign &lt;span class="nt"&gt;--product&lt;/span&gt; &lt;span class="s2"&gt;"your product"&lt;/span&gt; &lt;span class="nt"&gt;--mode&lt;/span&gt; quick

&lt;span class="c"&gt;# Ask one agent directly&lt;/span&gt;
python main.py ask cmo &lt;span class="s2"&gt;"What channels should a bootstrapped SaaS focus on first?"&lt;/span&gt;
python main.py ask copy &lt;span class="s2"&gt;"Write 5 headline variations for a project management tool"&lt;/span&gt;
python main.py ask seo &lt;span class="s2"&gt;"Keywords for email automation software?"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;--save&lt;/code&gt; flag dumps everything to a timestamped folder in &lt;code&gt;campaigns/&lt;/code&gt;. Use it. You'll want to reference the outputs later.&lt;/p&gt;




&lt;h2&gt;
  
  
  What I'd Do Differently
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Real keyword data.&lt;/strong&gt; Right now the SEO agent estimates keyword volume. Hooking in a Semrush API key (there's a hook for it in &lt;code&gt;tools/platform_tools.py&lt;/code&gt;) would make those recommendations actually grounded in real search data.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Iteration loops.&lt;/strong&gt; Right now it's a straight pipeline. What I want is the CMO reviewing the Copywriter's output and pushing back if it doesn't match the positioning. That's more expensive token-wise but would be closer to how a real team works.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;MCP server version.&lt;/strong&gt; This is the one I'm actually building next. Wrap the whole thing as an MCP server so it runs inside Claude Desktop as a tool — no CLI, just "run a campaign for X" and it happens in your workspace. That's what &lt;a href="https://fusional.dev" rel="noopener noreferrer"&gt;FusionAL&lt;/a&gt; is moving toward: all your AI tools in one place, zero config headache.&lt;/p&gt;




&lt;p&gt;Note: Opus 4.6 with adaptive thinking burns tokens fast. A full 6-agent campaign run will cost roughly $1-3 depending on your product description length. Budget accordingly or swap claude-opus-4-6 for claude-sonnet-4-6 in agents/base.py for a cheaper run.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Bigger Point
&lt;/h2&gt;

&lt;p&gt;I'm a self-taught developer. No CS degree. No team. I built this working alone, directing Claude to do the heavy lifting on code I understood well enough to review and correct but didn't have to write from scratch.&lt;/p&gt;

&lt;p&gt;That's the skill now. Not knowing every syntax. Not being the fastest typist. Knowing what you want, being able to recognize when you're not getting it, and knowing how to course-correct.&lt;/p&gt;

&lt;p&gt;If you're sleeping on that because it feels like "cheating" — it's not. It's just how good builders work in 2026.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Repo:&lt;/strong&gt; &lt;a href="https://gitlab.com/JonathanMelton-FusionAL/ai-marketing-team" rel="noopener noreferrer"&gt;gitlab.com/JonathanMelton-FusionAL/ai-marketing-team&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you run it, let me know what it produces. Tag me on X — &lt;a href="https://x.com/2EfinAwesome" rel="noopener noreferrer"&gt;@2EfinAwesome&lt;/a&gt;.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;I'm building &lt;a href="https://fusional.dev" rel="noopener noreferrer"&gt;FusionAL&lt;/a&gt; — a unified MCP gateway for teams who don't want to hire a platform engineer to set up their AI tooling. Follow the build on &lt;a href="https://x.com/2EfinAwesome" rel="noopener noreferrer"&gt;X&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>python</category>
      <category>machinelearning</category>
      <category>productivity</category>
    </item>
  </channel>
</rss>
