I Built a 6-Agent AI Team in tmux (Here’s What Actually Happened)

I Built a 6-Agent AI Team in tmux (Here’s What Actually Happened)

I want to tell you about the week I stopped coding alone.

Not in the “I hired a contractor” sense. I mean I spun up six instances of Claude Code across a tmux grid, assigned each one a role, and watched them coordinate on a real project. It was chaotic, occasionally brilliant, and broke in ways I did not anticipate. This is the honest build log.

Why Six Agents? Why Not One?

The project was a mid-sized content pipeline: scrape sources, classify articles, generate summaries, push drafts to WordPress, run a nightly audit, and notify me on Telegram when something went wrong. Five distinct concerns, each with its own error surface.

I’d been running it as a monolithic Claude Code session, and the context kept getting polluted. The scraping logic would drag irrelevant noise into the summary generation step. Asking one agent to hold the full pipeline in mind at once was like asking a surgeon to also manage hospital billing during the operation.

The insight that changed my approach: these concerns don’t actually need to talk to each other constantly. They need shared state at handoff points. That’s a coordination problem, not a monolith problem.

So I split them up.

6-Agent tmux Layout — Private Labs

The Team Structure

Here’s what I settled on after several iterations:

Pane Agent Role
0 Mason Orchestrator — assigns work, monitors heartbeats, handles escalations
1 Liam Architect/reviewer — reviews plans before execution, blocks bad calls
2 Ava Scraper & classifier — ingests sources, tags articles
3 Sophia Content generator — drafts summaries from classified articles
4 Noah WordPress publisher — formats and pushes approved drafts
5 Ryan Monitor — checks output quality, sends Telegram alerts

The orchestrator (Pane 0) doesn’t write code. It reads Redis keys, sends tmux send-keys commands to the worker panes, and responds when workers report blockers. Think of it as the project manager who doesn’t touch the keyboard except to delegate.

The reviewer (Pane 1) was the addition I almost skipped. I added it after a bad run where the scraper’s malformed output silently corrupted the generator’s input and I only noticed three hours later in production. Having a second agent do a 30-second sanity check on the scraper’s output before it reaches the generator is cheap insurance.

Setting Up the tmux Grid

The session is a single script:

#!/usr/bin/env bash
SESSION="private-labs"

tmux new-session -d -s $SESSION -x 220 -y 50

# Split into 6 panes: 2 rows × 3 columns
tmux split-window -h -t $SESSION
tmux split-window -h -t $SESSION
tmux select-layout -t $SESSION even-horizontal

tmux select-pane -t $SESSION:0.0
tmux split-window -v
tmux select-pane -t $SESSION:0.2
tmux split-window -v
tmux select-pane -t $SESSION:0.4
tmux split-window -v

# Start Claude Code in each pane with role CLAUDE.md
for i in 0 1 2 3 4 5; do
  tmux send-keys -t $SESSION:0.$i "cd ~/projects/pipeline && claude" Enter
done

tmux attach -t $SESSION

Each pane gets a per-role CLAUDE.md that scopes what the agent is allowed to touch and how it should communicate back to the orchestrator. The scraper agent’s CLAUDE.md explicitly says it should never write to the WordPress tables. Scope-limiting through role documents is the single most important thing I did to keep agents from stepping on each other.

Redis as the Shared Brain

Agents can’t read each other’s context windows. They need somewhere to write state that others can read. Redis is the answer — fast, simple, and already running on my server.

Every agent writes to a predictable key schema:

agent:{name}:status       # working | idle | blocked | error
agent:{name}:heartbeat    # Unix timestamp, TTL 120s
agent:{name}:task         # one-line description of current work
queue:classify            # articles waiting for classification
queue:generate            # classified articles waiting for summaries
queue:publish             # approved drafts waiting for WordPress push

The orchestrator runs a 5-minute check loop:

for AGENT in jun minjun seoyeon sua jihun taeyang; do
  TTL=$(redis-cli TTL "agent:${AGENT}:heartbeat")
  if [[ "$TTL" == "-2" ]]; then
    echo "[!!] ${AGENT} heartbeat missing — may be hung"
    # reboot-pane.sh called here
  fi
done

If a heartbeat key expires (TTL goes to -2), the orchestrator calls reboot-pane.sh on that pane. This has saved me several times from zombie agents sitting at a stuck prompt with no one noticing.

Redis State Coordination Between Agents — Private Labs

The First Real Run: What Broke

I ran the full team for the first time on a Tuesday afternoon. Here’s what happened in order:

Hour 0: Everything started cleanly. Scraper began pulling articles. I felt smart.

Hour 0:45: The classifier agent got rate-limited by the API and went silent. It didn’t write an error to Redis. It just stopped. The heartbeat key expired 2 minutes later. The orchestrator detected the dead heartbeat and rebooted the pane. Clean recovery — but only because I’d added the heartbeat system the day before. Without it, I’d have been waiting on a queue that was never going to drain.

Hour 2: The generator started producing summaries that were subtly off. The source articles had shifted from tech news to financial news mid-run (the scraper was working correctly; the source site had an editorial pivot). The generator had no way to know its input distribution had changed. I had to stop it manually, re-scope the classifier’s rules, and re-run the affected batch.

Hour 3:30: The WordPress publisher pushed a draft with a malformed featured image URL. The audit agent caught it. This was the system working as designed, but the fix required human judgment — the publisher couldn’t self-correct because the bad URL came from a third-party CDN and I hadn’t written a fallback handler. Added to the backlog.

By the end of the first run: 47 articles scraped, 31 classified, 28 summaries generated, 24 published, 3 flagged for review. About 80% autonomous, 20% needing my intervention. Not bad for a first run, worse than I’d hoped.

What Surprised Me

Context isolation is a feature. When the generator agent runs into a problem, it doesn’t contaminate the scraper’s session with noise. Each agent’s working memory stays focused. Debugging is also cleaner — I can look at one pane’s history in isolation.

The orchestrator needs to be dumber than you think. Early versions tried to be too clever — writing complex decision trees into the orchestrator’s CLAUDE.md. It got confused. The best orchestrators I’ve built do one thing: check Redis, send-keys to a specific pane with a specific task, wait. Any logic beyond that belongs in the worker’s own CLAUDE.md.

Agents will fill their context if you let them. A scraper running for six hours accumulates a lot of context — error logs, retry traces, intermediate state. I had to add periodic context resets (rebooting the pane and reloading from Redis state) to keep performance from degrading. The first sign of context bloat is the agent starting to repeat itself or asking clarifying questions it answered earlier.

The reviewer pane is worth the API cost. It adds maybe 15% to my total token spend. It catches bad handoffs before they cascade. I will never run without it again.

The Current State

Six weeks later, the pipeline runs nightly without me touching it on most days. My actual role has shifted from “person who writes the code” to “person who writes the role documents and fixes the edge cases the agents surface.”

The things that still need human eyes: – Source quality degradation (agents can’t judge whether a source has become unreliable) – Novel error types that don’t match any retry pattern I’ve written – Business logic changes (what’s worth publishing vs. skipping)

The things that run fully autonomously: – Scraping and classification – Summary generation and formatting – WordPress publishing and basic QA – Heartbeat monitoring and pane reboots – Telegram alerts for anomalies

If you’re thinking about building something similar, start with two agents before six. The orchestrator plus one worker, with Redis in between. Get the handoff right before you scale the team. The complexity doesn’t increase linearly — it roughly squares with the number of agents you’re coordinating.

What Stayed Manual vs. What Became Autonomous — Private Labs


The permission errors I kept hitting when the agents wrote to /mnt/c/ paths were a separate adventure — covered in the EACCES post in Problem Solving.

Leave a Reply

Your email address will not be published. Required fields are marked *.

*
*