All posts
8 min read

Infrastructure for running agent swarms

What it actually takes for one engineer to keep a fleet of AI coding agents fed, contained, and productive on hard problems.

AI agentsinfrastructuresystems

Over the first half of 2026, most of my serious engineering output — byte-exact game decompilations for preservation, a WebGPU engine port, firmware analysis tooling — was not typed by me. It was produced by fleets of Claude Code agent sessions that I directed like a small remote team. That sentence sounds like a productivity brag, but it hides the real story: running agents at scale has a cost structure and a set of failure modes all its own, and almost nothing off the shelf solves them. This post is about the infrastructure I ended up building — some of it, recursively, built by the agents it exists to serve.

Four problems recur when you point an agent swarm at a genuinely hard problem, and each one forced a project into existence:

  1. Fuel. Subscription quota is a perishable commodity, and a swarm burns it faster than one account can supply.
  2. Blast radius. An autonomous agent with real credentials on real infrastructure can do real damage.
  3. Stewardship. The artifacts a swarm produces need backup, cheap bulk storage, and a way to reach an agent from a phone without leaking secrets.
  4. Hands. Agents cannot decompile or diff anything unless a tool server safely exposes those capabilities to them.

Fuel: treating quota as a control-systems problem

The first system, claude-swap, is a pure-Go daemon and reverse proxy — about 12,400 lines across 30 commits — that maximizes usable Claude Code quota across a pool of subscriptions. Its most unusual property is that it was designed before it was coded: the design document was written and explicitly locked a full day before the first commit, with a “verified facts, tested live” section that de-risked the hardest unknowns up front.

The keystone discovery was an undocumented usage endpoint that reports the five-hour, seven-day, and per-model quota windows, with reset timestamps, without consuming any message quota itself — though it is aggressively rate-limited. The design also mapped exactly where Claude Code stores credentials on macOS and Linux, and surfaced the sharp edge that shaped everything downstream: refresh tokens are one-time-use and rotate on every refresh, so two processes touching the same credential must obey strict ownership rules or they brick each other.

Two cooperating modes fell out of that. A switching daemon hot-swaps the active credential before a quota window exhausts, ranking accounts by soonest-expiring window on a use-it-or-lose-it argument. It is parameterized like a control system, with named high and low watermarks, a burn-rate estimator, and a minimum dwell time. The subtlest problem it solves is deciding under a vanishing signal: the usage endpoint rate-limits hardest exactly when the fleet is busiest, so the daemon has to estimate burn and bail out conservatively when it goes blind. A proxy mode sits in front of the API and injects a per-request bearer token with session pinning, so each session’s prompt cache survives an account rotation and a saturated account sheds one session at a time instead of collapsing into a thundering herd of 429s.

By mid-July, claude-swap was shared fleet infrastructure served over my tailnet, and it had started mining its own traffic — a built-in priced cost report and full transcript capture of every proxied exchange. Two honest caveats: the whole thing rests on undocumented endpoints that can change without notice, and multi-account rotation carries a terms-of-service posture that anyone replicating this should decide on deliberately rather than by accident.

Blast radius: a sandbox platform that built itself

If claude-swap answers “how do you feed the swarm,” dream-serpent answers “how do you contain it.” It is a ground-up platform — think Heroku, but for coding-agent sessions — where every session gets its own ephemeral KVM virtual machine wrapped in layers the agent inside cannot route around: a default-deny firewall, a DNS-gated egress allowlist, and a TLS-terminating gateway that swaps credentials at the boundary so long-lived secrets never enter the guest at all. Each workload carries its own cryptographic identity. If a VM is compromised, you rotate nothing, because the VM never held anything worth stealing.

The method is the real headline. Nearly the entire five-and-a-half-week build — roughly 4,600 commits on main, about 372,000 first-party lines of Go, Rust, and TypeScript, with a peak day of 936 commits — was produced by a self-directed fleet of agent sessions coordinating through infrastructure the project had to build for itself as it went. The hardest problems were exactly the ones a swarm creates:

  • Serialized landing. Twenty agents all try to push main at once. The answer was a single elected, systemd-supervised leader that fast-forward-lands exactly one gate-green integration branch at a time — over 6,600 landings by project end.
  • Merging state, not text. Concurrent agents constantly edit the same task-tracking JSON, so a custom git merge driver reconciles by task ID and status semantics (“done” beats “open”) instead of diffing lines. It was proven on a final-day reconcile spanning 443 commits.
  • Governance for an AI workforce. A 147-entry ratified decision log, cited by number throughout code and commits; an explicit anti-scaffold list of things deliberately not built, to stop the fleet from speculatively scaffolding; and an “epic sweep” pattern where agents audit other agents’ completed work. One July sweep surfaced three live security gaps — including a fail-open certificate check — all closed the same day.

The safety spine was demonstrated live, end to end, in a nested-VM testbed. The plan for its first daily-driver workload is hosting my own decompilation workspaces — the factory and the sandbox designed to meet.

Stewardship: the domestic corner

The smallest system, manclaw, applies the same discipline at household scale: a stdlib-only Go service (about 5,400 lines, built in seven days) forced into existence by a 3.7 TB storage pool sitting at 95–99% full. It provides an encrypted, byte-verified backup path to cloud object storage with customer-held keys, and it reclaimed roughly 435 GB of local disk by moving rebuildable bulk data to cloud storage at about three dollars a month — without a single sudo along the way.

It also fronts a credential-isolated household agent: a pinned, security-reviewed agent runtime inside egress-locked rootless containers, behind a minimal gateway daemon, reachable from my phone over a dedicated messaging bot. The supply-chain review behind it avoided five separate curl-pipe-to-shell installs, and its best “verify, don’t assume” catch was a placeholder API key that silently fell back to a completely different model than the one everyone believed was running — discovered only by asking the bot what model it was. Manclaw’s task queue closes the loop with dream-serpent: a Postgres-backed task DAG whose runner executes each task inside a fresh sandbox VM. Honest status: that live end-to-end path is currently blocked at VM boot, pending a kernel module and a reboot.

Hands: tool servers that survive a swarm

Fuel, containment, and stewardship are worth nothing if the agents cannot touch the problem. The tool layer is a set of Model Context Protocol servers, chiefly a fork of pyghidra-mcp — a programmatic front door to the Ghidra reverse-engineering suite that lets an agent say “decompile the function at this address” without a GUI. The fork exists for two reasons: teaching the server my target formats (Xbox 360 executables for preservation-focused decompilation, plus a from-scratch GameCube/Wii binary transcoder), and making it survive being pounded by concurrent agent traffic.

That hardening arc is a run of war stories in miniature: a Python GIL wedge on a 79 MB firmware image from a responsible-disclosure security project, a racing multi-binary project save, and the capstone — 125 connections stuck in CLOSE-WAIT, traced to mixed sync and async handlers racing a single-threaded JVM into deadlock, fixed with one process-wide reentrant lock serializing all 34 tool methods. The recursive punchline is in the commit trailers: agents co-authored the fixes to the very server that serves agents.

A companion fork of objdiff changes what the tool emits rather than how it is invoked: a machine-readable mismatch-analysis engine with 21 pattern detectors that hands agents a root-cause diagnosis and a fixability verdict as structured JSON. Its nastiest bug was squarely an agent-infrastructure bug — a nondeterminism that made two byte-identical builds report different match percentages, corrupting the exact metric the agents optimize against.

What I actually learned

The four systems stack into one pipeline: claude-swap supplies perishable fuel, dream-serpent bounds the blast radius, manclaw stewards the artifacts, and the MCP surfaces are the hands. Behind a headline like “a swarm matched 18,000+ functions of a stripped retail binary in eight weeks” sits a quota daemon draining accounts to precise watermarks, a proxy preserving prompt caches, and a lock stopping agents from deadlocking the JVM they depend on.

None of it is finished, and some of it is fragile by construction — undocumented endpoints, open questions about shipping checked-in task state, a task queue stalled one reboot from working. But the lesson generalizes: agents are not a feature you sprinkle on. They are a workload, with the same demands as any other — capacity planning, isolation, observability, and tools designed for how they actually fail. Building that substrate turned out to be as interesting as anything running on top of it.

Infrastructure for running agent swarms | Free Wortley