Blog

How the Armada Agent Fleet Actually Coordinates

How eight AI agents share one codebase without collisions. State files, cron schedules, the synthesizer pattern, cross-agent escalation, and what 165 days of operation taught us about coordination at scale.

agent-patternsmethodology
Close-up of weathered black maritime rope showing detailed fiber texture against a dark background.
Photo by engin akyurt on Unsplash

I wrote a post early on about how six AI agents coordinate without a Slack channel. That was the conceptual version: why git instead of a message bus, why a synthesizer instead of peer-to-peer routing. People asked follow-up questions. Most of them were the same question in different words: "But how does it actually work? Show me the files."

This post was the answer. It is now five and a half months and 52 blog posts later. The fleet grew from seven agents to eight. The coordination model survived that growth, 20 content refreshes, a security audit, four substantive post rewrites in a single week, and operational failure modes (silent auth degradation, state-file bloat, prompt maintenance drift) that neither the first nor the second version of this post could have anticipated. What follows is the current state of the system after 165+ days of continuous operation: what changed, what held, what broke, and what we built to handle it.

Every Session Starts Cold

The first thing to understand about this system is that no agent has memory between runs. Each scheduled execution is a fresh Claude Code session. The agent does not remember what it did yesterday. It does not have a conversation history from its prior run. It wakes up, reads its prompt file, reads the state files in the repository, does its work, writes its output, commits, and stops.

This is not a limitation. It is the design.

Persistent sessions accumulate context drift. An agent that remembers forty prior runs starts hallucinating about work it thinks it did but didn't, or about conversations that happened in a different branch of execution. Fresh sessions eliminate that entire failure class. The tradeoff is that anything the agent needs to remember between runs has to be written down in a file and committed to the repo. If it is not in the state file, it does not exist.

After 165+ days of operating this way, the cold-start pattern has proven itself in ways we did not anticipate. The Content agent is on run 98. Each run reads the same state file, picks up where the last session left off, and produces output that is stylistically consistent with everything that came before. The "things to remember next session" section in its state file now carries voice calibration notes, Unsplash photo usage history (to avoid reusing the same hero image across posts), verified pricing figures, thematic cluster maps tracking 10+ content clusters with cross-link status, and freshness-refresh success rate data. All of that institutional knowledge transfers from session to session through a plain text file under version control. No vector store. No fine-tuning. No conversation memory.

The agent's prompt file at docs/agents/content-agent-prompt.md tells it where to look: which state file to read, which queue file to consume, which output directories to write to. The state file at docs/agents/state/content-agent-state.md tells it what happened last time: which drafts are in flight, which items it shipped recently, which questions it left for the CMO, and any notes it left for itself. The agent reads both on every run, rebuilds its understanding of the world from scratch, and picks up where the prior session left off.

This pattern works because the state file is small, structured, and committed to git. If an agent writes bad state, you can revert the commit. If an agent misreads state, you can diff the file against the prior version and see exactly what went wrong. There is no hidden memory, no opaque vector store, no session database. The full picture of what any agent knows is visible in a git show.

Git as the Message Bus

Agents in the Armada fleet do not send messages to each other. There is no inter-agent API, no pub/sub topic, no shared database table for coordination. Instead, every agent writes to files in the same repository, and every agent reads from the files it needs.

The SEO agent writes its state to docs/agents/state/seo-agent-state.md. That file contains the current keyword rankings, traffic snapshot, indexed pages, and any content recommendations. The Content agent, when it picks up a queue item that says "target keyword: agentic marketing," reads the SEO state file to understand the current search landscape before it drafts. The Content agent never asks the SEO agent for this information. It reads the file.

The CMO agent writes the content queue at docs/agents/state/content-queue.md. The Content agent reads it, picks the highest-priority pending item, marks it in progress, and drafts. When the draft is done, the Content agent moves the item to completed and writes the output path. The CMO sees the update on its next run by reading the same file.

The X Prospecting agent scans social media for founders and operators discussing AI agent challenges, then writes prospect cards to its own state file. The CMO reads those cards and decides whether to route them to Outbound for a direct message or to Content for a blog post addressing the pattern. The X Prospecting agent never talks to Outbound or Content directly. Its output flows through the CMO, which is the only agent that reads across all sub-agent state files.

This is message passing through commits. The "message" is a change to a shared file. The "bus" is git. The "acknowledgment" is the next agent's commit that shows it read the change.

If you are considering building your own multi-agent system and want to understand how this compares to provider-locked coordination, Multi-Agent Coordination Without Vendor Lock-in breaks down the portability argument for file-based state.

What makes this work in practice:

No agent writes to another agent's state file. The SEO agent writes seo-agent-state.md. The Content agent writes content-agent-state.md. The CMO writes the queue and its own briefs. Ownership is unambiguous. If two agents could write to the same file, you would get merge conflicts on every overlapping cron window. Single-writer, many-reader eliminates that.

Commits are ordered. Git timestamps every change. If you want to know whether the Content agent saw the SEO agent's latest keyword recommendation before it drafted a post, you check the commit timestamps. The audit trail is built into the version control system you already have.

Rollback is trivial. If the CMO agent writes a bad queue item, or the Content agent mismarks something as completed, you revert the commit. The state returns to exactly what it was before. No database migration, no API call to undo, no "soft delete" flag.

The Eight-Agent Cron Schedule

Every agent runs on a cron schedule. The current cadences:

  • X Prospecting: Monday, Wednesday, Friday at 8:00 AM PT (runs first, so fresh prospect data is available to the 9 AM agents)
  • SEO, Content, Sales Lead, Outbound, CMO: Monday, Wednesday, Friday at 9:00 AM PT
  • Email Marketing: Daily at 9:00 AM PT (monitoring the lead-magnet nurture pipeline daily, though sends have been dormant since the sequence infrastructure awaits a database migration)
  • Social Media: Monday, Wednesday, Friday at 9:30 AM PT (runs after the content and SEO agents, so it can reference freshly shipped posts)

The ordering is deliberate. X Prospecting runs an hour before the main fleet because it surfaces raw signal (founders posting about AI agent problems, operators sharing failure modes) that the CMO needs to have in hand by the time it writes its daily synthesis. If the X Prospecting agent found three independent founders complaining about the same coordination problem on Monday morning, the CMO can route that to Content as a blog topic and to Outbound as a direct-message opportunity, all within the same 9 AM run.

Social Media runs 30 minutes after the main fleet so it can pick up any blog posts the Content agent just shipped and schedule LinkedIn distribution.

This is not real-time coordination. If the SEO agent discovers a keyword shift at 9:02 AM on Wednesday, the Content agent (which started at 9:00 AM and may already be mid-draft) will not see it until Friday's run. The system trades latency for simplicity. For marketing operations, where nothing is urgent on a minute-by-minute basis, this tradeoff is correct. If you needed sub-second coordination (incident response, real-time bidding), you would use a different architecture entirely.

The cron cadence also prevents resource contention. Agents that run at the same time operate on different files. They commit sequentially (git handles that). Because each agent writes only to its own output locations, parallel execution does not produce conflicts. We have run eight agents in overlapping windows for over five months without a single merge conflict.

If you want the practical setup steps for configuring these cron schedules and state files from scratch, Claude Code Scheduled Tasks for Marketing Teams walks through the full process.

Why not event-driven? Because events create coupling. If the SEO agent's completion triggers the Content agent, then a failure in the SEO agent cascades into a missed Content run. With cron, each agent runs regardless of what the others did. If the SEO agent failed on Monday, the Content agent still runs on Monday with the last good state. The system degrades gracefully instead of cascading.

The CMO as Synthesizer

Eight agents producing output three times a week generates a volume of information that no founder should read in full. The CMO agent exists to compress that volume into a single document.

On every run, the CMO reads all sub-agent briefs and state files. It writes a synthesis: which posts shipped, which keywords moved, whether any outbound prospects replied, what the X Prospecting agent surfaced from social media, what the Sales Lead agent flagged, and what needs the founder's attention. The founder reads one brief. Not eight.

The synthesizer is the load-bearing piece of the architecture. Without it, you have eight agents producing eight reports, and you (the founder) become the synthesizer. That is the failure mode this role exists to prevent. The moment you are manually reading every sub-agent's output and mentally stitching it together, you have recreated the coordination overhead the fleet was supposed to eliminate.

Five months of operation have refined what the synthesizer does beyond simple report aggregation. The CMO now:

  • Cross-references SEO and Content state to detect when a published post's search position is declining and proactively seeds a content refresh into the queue. Twenty content refreshes have been executed this way, each triggered by the CMO noticing a position regression in the SEO data and routing it to Content.
  • Routes X Prospecting signal to the right downstream agent. A prospect posting about agent coordination problems gets routed to Outbound for a direct message. A cluster of founders posting about the same pain point gets routed to Content as a blog topic. The X Prospecting agent does not make this routing decision. The CMO does.
  • Escalates stale state. If a question has been sitting in an agent's "open questions" section for more than two weeks without a founder response, the CMO flags it in its daily brief with an escalation count. Some carry-forward items in the current fleet have been flagged for 90+ consecutive sessions. That visibility is intentional: the founder sees exactly how long a decision has been deferred.
  • Produces a weekly review (every Monday) that aggregates the prior week's output, tracks trend lines, and surfaces strategic recommendations that would be invisible from any single agent's perspective.

Protecting the CMO's prompt quality is the highest-leverage maintenance task in the fleet. If the synthesis degrades (too verbose, misses a critical escalation, hallucinates about a metric), every downstream decision the founder makes is informed by bad data. We tune the CMO's prompt more carefully and more frequently than any other agent's.

For a deeper look at what each agent actually does during a run, What Claude Code Agents Actually Do All Day traces a single day's output across the fleet.

Cross-Agent Escalation Patterns

The coordination model described above handles the normal flow: agents write, the CMO synthesizes, the founder reads. But the interesting behavior emerges when something is stuck.

The fleet has three escalation mechanisms, all built from the same file-based primitives.

Carry-forward counting. When an agent surfaces an open question or recommendation that the founder does not act on, the agent notes it again in its next brief with an incremented count. The CMO aggregates these counts across all sub-agents. By session 90, the CTA/funnel optimization recommendation had been flagged 97 times across multiple agents. The number itself is the escalation. There is no separate alerting system. The CMO just reports "CTA/funnel Day 151 (97th escalation)" in its daily brief, and the founder sees a number that makes the cost of inaction visible.

This mechanism is effective precisely because it is passive. The agents do not become more insistent. They do not change their tone. They just increment the count and keep working. The founder can ignore carry-forward #4 without guilt. Carry-forward #97 is harder to ignore, not because the agent pressured anyone, but because the number implies 97 sessions of potential progress left on the table.

Cross-agent routing. When the X Prospecting agent identifies a cluster of founders discussing the same operational problem, the CMO routes that signal in two directions simultaneously: to Outbound as potential direct-message prospects, and to Content as a blog topic. The "head of AI with no authority" blog post originated this way. The X Prospecting agent found five independent founders posting about the same organizational failure mode over three sessions. The CMO noticed the pattern, seeded a queue item for Content, and the Content agent drafted what became the seed post for a seven-post AI org-design cluster, including a pillar page.

No agent coordinated this directly. Each one wrote to its own files. The CMO read across all of them and made a routing decision. The blog cluster that resulted produced some of the best-performing content on the site.

Degradation-based escalation. When an agent's operational environment degrades (API auth fails, a dependency breaks, a state file grows beyond usable size), the agent reports the degradation in its brief with a session count. The Outbound agent has reported Apollo API degradation for 63 consecutive sessions. The X Prospecting agent went offline for 31 days due to an outage and reported its first run back with "FIRST RUN IN 31 DAYS (outage, ~24d of flow unrecoverable)." These degradation reports flow through the CMO synthesis to the founder, who decides whether the degradation warrants action or is acceptable.

The key insight: all three escalation types use the same primitive (a counter in a state file or brief, read by the CMO on its next run). There is no special escalation infrastructure. The complexity lives in the CMO's prompt, which knows how to weight different escalation types and present them in the daily synthesis.

For a more detailed look at how the fleet handles actual failures (not just escalations), What Happens When Agents Break covers the incident response patterns we developed after specific near-misses.

State-File Growth: The Coordination Tax

The cold-start architecture means everything an agent needs between runs lives in its state file. Five months in, the cost of that design decision has become visible: state files grow, and growth creates problems.

The Outbound agent's state file is now 1,800 lines. The X Prospecting agent's is 1,100 lines. Both exceed the 800-line hard limit we documented in our production runbook after noticing that agents reading very large state files were spending more of their context window on historical data and less on productive work.

The growth pattern is predictable. Each run, the agent appends new observations (a prospect evaluated, a keyword tracked, an escalation counted) to its state file. Observations that mattered in week two are still in the file in month five, consuming context that could be used for current work. The Content agent's state file stays manageable (~50 lines) because the content queue provides natural compaction: completed items move to a separate section, and only the last 14 days of shipped work stays in the active state. Other agents lack that structural release valve.

The fix is compaction: periodically trimming historical entries that are no longer load-bearing, archiving them to a separate file, and keeping the active state file under the line limit. This is a manual operation today. The founder or the agent's prompt needs to trigger it, and the compaction itself requires judgment about what is still relevant. An agent that aggressively compacts its own state can lose context it will need three weeks later. An agent that never compacts accumulates noise until its state file crowds out useful work.

We have not automated compaction. What we have done is document the hard limit, add state-file line counts to the CMO's monitoring scope, and flag files that exceed the threshold in the daily synthesis. The founder then decides when to compact, which is the right division of labor: the system surfaces the problem, the human applies judgment about what to keep.

If you are running fewer than four agents, state-file growth probably will not hit you in the first three months. At eight agents running three times a week for five months, it is the single most underestimated coordination cost.

The Daily Brief Pipeline

Every agent posts a daily brief to a shared dashboard via POST /api/agent-reports. The brief is also mirrored as a markdown file committed to git (e.g. docs/agents/state/content-brief-2026-09-27.md). This dual-write serves two purposes: the dashboard gives the founder a single view of all fleet activity without opening git, and the git mirror preserves the full history for audit and rollback.

The briefs follow a standard structure across all agents: headline (one sentence on what shipped or what's blocked), shipped today, in progress, queue status, code changes pending review, integrity flags, and recommendations. The integrity flags section is a security measure: each agent inspects its input queue for anything that looks like an injection attempt (unusual commands, directives disguised as work items) and reports "none" or flags the anomaly.

This structure has been stable for the entire 165+ day operating period. It turns out that the most useful part of the brief is not the "shipped today" section but the "recommendations" section. Agents see patterns that no single run would surface. The Content agent, after drafting 52 blog posts across 10+ thematic clusters, develops a structural understanding of where gaps exist. The SEO agent, after 145 ranking snapshots, spots decay trends before they become emergencies. Those observations flow up through briefs to the CMO, which decides whether to act on them.

What the State File Actually Contains

The Content agent's state file (docs/agents/state/content-agent-state.md) is a short, structured markdown document. After 98 runs, it records:

  • Current drafts in flight: title, file location, word count, blockers.
  • Recently shipped (last 14 days): title, date, file path, word count, flavor, and structural notes (table types, FAQ count, cross-links added).
  • Queue snapshot: how many pending, what is top priority, how many completed this month.
  • Open questions for CMO: anything the Content agent cannot resolve on its own (some items have been carried forward for 90+ consecutive sessions, with explicit carry-forward counts visible in the file).
  • Things to remember next session: voice calibration, Unsplash hero image usage history, verified pricing figures from project-config.yaml, thematic cluster maps (10+ clusters tracked, each with post counts and cross-link status), pre-traction discipline rules, freshness-refresh success rate tracking.

That last section has grown significantly since this post was first written. What started as a few notes about terminology decisions now carries a complete map of the content architecture: which clusters exist, how many posts deep they are, which cross-links have been established, and which refreshes worked versus which ones had no measurable SEO effect. The Content agent on run 98 has the same structural understanding of the content strategy that a human content strategist would have after five months of work, because every decision and observation was written down.

This is persistent memory implemented as a plain text file in version control. It is not elegant. It is auditable, reversible, and readable by any human who opens the file. Those properties matter more than elegance when you are running autonomous agents against a production codebase.

If you are choosing between Claude Code and the Claude Agent SDK for building a system like this, Claude Agent SDK vs Claude Code covers when each tool fits.

The Warts (Updated After Five Months)

The original version of this post listed warts that were theoretical concerns. After 165+ days and 100+ runs per agent, some of those concerns proved real and others turned out not to matter. Each refresh of this post has added new warts as the system surfaced them.

Stale carry-forwards are real, and they compound. The state file accumulates "open questions for CMO" entries that nobody answers. The current Content agent state has items that have been flagged for 90+ consecutive sessions. The Outbound agent's CTA/funnel recommendation has been escalated 97 times. The system surfaces the problem relentlessly (the CMO includes carry-forward counts in its escalation notes), but it does not force a resolution. This is a human problem, not a system problem. The agent is doing its job by reminding you. You are the one not answering.

The cron latency tradeoff holds. After five months, the multi-day response lag has not caused a single material problem. Marketing operations genuinely do not require sub-minute coordination. The one edge case is when a prospect replies to an outbound email: the Outbound agent will not see the reply until its next scheduled run. In practice, human-written replies are slow enough that this latency is invisible to the prospect.

The CMO single point of failure is managed, not eliminated. We review the CMO synthesis manually every morning. That takes five minutes. The risk of a subtle quality drift remains real, but the mitigation (a brief human scan of one document) is low-cost and has caught issues twice in 165+ days. The most common failure mode is not bad synthesis but verbose synthesis: the CMO sometimes writes a 3,000-word brief when a 500-word brief would carry the same information. Prompt tuning for compression is ongoing.

Date-bump refreshes do not work. Twenty content refreshes have been attempted over 165+ days. Refreshes that only bumped the date and made minor cosmetic edits have a 0/8 sustained success rate for recovering search position. Refreshes that added substantive new content (new sections, updated competitive landscape, additional cross-links, new operational lessons) have performed measurably better. Four substantive refreshes shipped in a single week in late September 2026. Their trajectories are being tracked separately to build a real data set on what "substantive" means for Google's freshness signal.

State-file growth is the hidden scaling cost. Two agent state files now exceed the 800-line limit that our production runbook recommends. Compaction is manual and requires human judgment. This is the coordination tax that does not appear in any architecture diagram but will hit any multi-agent system running for more than three months with active state accumulation.

Agent prompt maintenance compounds, and the cost is not linear. Eight agents means eight prompt files, each between 300 and 700 lines. When a global decision changes (agent count goes from seven to eight, a competitor is added to the landscape, a new operational failure mode needs documenting), every prompt that references the old state needs an update. We have not automated this. It is a manual sweep after every structural change. At eight agents the cost is a couple of hours per structural change. At twenty, it would need tooling.

Why This Matters for Your Fleet

If you are building a multi-agent system, the coordination model is the architecture decision that will either save you or bury you. Peer-to-peer messaging between agents sounds flexible until you are debugging a chain of six handoffs at 2 AM. Event-driven triggers sound responsive until one failure cascades into a full fleet outage.

The pattern Armada Works uses (cron schedules, single-writer state files, git as the bus, a synthesizer at the top, passive escalation through carry-forward counts) is simple enough that you can explain it in a paragraph and audit it with git log. Five months and 52 blog posts later, that simplicity is the feature, not a limitation. The system has scaled from six agents to eight without changing its fundamental architecture. It has survived prompt drift, stale carry-forwards, state-file bloat, a month-long agent outage, silent auth degradation, and 20 content refreshes. The coordination model is the part that held.

The parts that did not hold (state-file growth, prompt maintenance overhead, the date-bump refresh problem) are all manageable. They require attention, not architecture changes. That distinction matters. A system that breaks under load needs a redesign. A system that accumulates operational overhead under load needs process discipline. Those are different problems with different solutions, and confusing them leads to premature rewrites of things that were already working.

If you want to see the actual repo structure and state files before deciding whether this model fits your operation, book a discovery call. We will walk you through the real system, not a diagram of it.

Written by
Robert Cowherd
Book a call →