Tech Blog

Building a streaming platform and a bank in parallel — deploying a fleet of AI agents to implement real features, and tuning the division of labor by measurement

AIエージェント Claude Code チューニング プロンプト設計 サブエージェント 運用

Introduction

On my own, I am building two systems in parallel. One is an all-in-one platform that bundles video and music; the other is a self-made banking system used for its payments. To move both forward at once, I did not ask a single AI to do everything. I assembled a fleet of subagents split by role — implementer, reviewer, coordinator — and ran the real feature work through it.

The difference between an AI as a “companion” and an AI as an “agent” is in I used GitHub Copilot for a month and Claude Code for two days — coding partners and agents are two different things.. This article goes one step further — stop using an agent as a single all-rounder, deploy it as a “fleet,” and tune it through actual development — a record of the design and the measurements.


What breaks when one agent does everything

Have one agent write the code, then ask that same agent to “review it.” Simple, but weak: it can’t doubt its own code (dragged by the context it just wrote), its context gets polluted, and capability and cost don’t match. The answer wasn’t “a smarter single agent” but multiple agents split by role.

[one agent for everything]
  one agent ─▶ implementation, verification, investigation — all of it
        └─ goes easy on its own code / context gets polluted / cost doesn't match

[split by fleet]
  implementer ─▶ reviewer (different eyes, different permissions) ─▶ coordinator directs the whole
        └─ checked by independent eyes / context isolated / capability assigned per job

Split by role: coder → reviewer, and orchestrator

The foundation is that once the implementer (coder) writes, a separate agent — the reviewer — checks it with independent eyes and sends findings back to the implementer. Above them sits the coordinator (orchestrator), which does no work itself and only directs.

                        ┌─▶ coder (implement) ─┐
  orchestrator (direct) ┤                      ├─▶ reviewer (verify) ─▶ findings back to coder
                        └─▶ decompose/parallel ┘         │
                                ▲                        └─ round-trip until it's good
                                └─────────────────────────┘

In Claude Code, the roles in this diagram are expressed as one definition file per agent, each stating its role, the tools it may use, and the model assigned. The diagram above becomes the settings below.

# ~/.claude/agents/*.md (excerpt of each subagent definition)
orchestrator : { model: opus,   tools: [Agent, Read, Grep, ...] }   # coordinator (direct only)
rag-reviewer : { model: opus,   tools: [Read, Grep, Bash, ...]  }   # reviewer
rag-coder    : { model: sonnet, tools: [Read, Write, Edit, ...] }   # implementer

Line the diagram and the settings up, and the key is that the reviewer has no Write / Edit tools. The reviewer cannot directly edit the implementer’s output. If verification and implementation are held by the same hand, you slide back to “going easy on yourself.” Don’t mix the role boundary — enforce it at the permission level.

The first time I ran this fleet end-to-end on a real bank API, the nested serial chain (implement → verify → dedicated commit) worked without permission errors. Here are the measurements.

# measurements of orchestrator directing a real feature (an identity API)
rag-coder (implement)      … ~11.6 min / ~136k tokens   ← the heaviest stage
rag-reviewer (verify)      … ~6.7 min  /  ~73k tokens
dedicated commit (split)   … ~34 sec   /  ~40k tokens    ← ~1/3 of implement; light routine isolated to a separate agent

Token counts mirror the weight of the stage. Implementation is heaviest; a routine like committing costs a third of that. So heavy implementation goes to the main workhorse model, and light routine is split out to a separate agent — the numbers become the basis for the next assignment.


Assign models by fit

The heart of fleet tuning is which model to assign to which role. The goal is not saving tokens, but allocating capability and cost. I hold this as a “ladder” in a diagram, then burn it into the instructions (CLAUDE.md) as prose.

capability↑  fable ─── promote only the single hardest step, by judgment
             opus ──── verification / design / security (guarded)
             sonnet ── generation / everyday coding (workhorse)
             haiku ─── mechanical / simple
cost↓ (cheaper toward the bottom)
# CLAUDE.md (operating discipline, excerpt) — fixing the ladder above in words
Model choice is "best-fit for maximum performance" first = saving tokens is not the goal.
Verification / design / security judgment = opus, guarded (don't skimp)
⛔ Dropping verification to a cheaper model to make it cheap is a misplaced axis — forbidden

Once, meaning to cut cost, I dropped even the reviewer to a lighter model and misplaced the axis. Choose by “does this job require commensurate capability,” not “how cheap can it go.” Cheapness is not the goal; allocating capability is.


Delegation has a “structural cost”

Another lever is delegating heavy greps and long-log reading to a subagent that has its own blank workspace (an isolated context), separate from the main. Let the subagent read; the main only receives the summary — so the main’s context isn’t buried in noise.

But delegation is not always a win. Running in parallel has a structural cost — total tokens that grow with each parallel agent, and a fixed cost of re-handing the premises to each one. On one large consistency audit, I misread it.

# result of deploying a large-file audit across 3 parallel agents
aim: shorten via parallelism  ─▶  reality: the structural cost of multi-launch
                                    outweighed the model tier, consuming 80%+ of context
verdict: this audit was "one heavy task that needs a whole-picture view" = not a fit for splitting
         → cheaper for the main to process it directly, all at once

So whether to delegate is decided by the nature of the work.

  verbose reading (large logs, full read-through)  → delegate (isolate to protect the main's context)
  independently parallelizable work (many conversions) → delegate (parallelism works / cap concurrency at 2–4)
  one heavy task needing a whole-picture view       → main directly (splitting's fixed cost is high)

The fleet isn’t omnipotent: when it breaks, measure and recover

The fleet is strong, but not unbreakable. On another day, when I deployed a highly independent batch-conversion job across 4 parallel agents, the API was unstable and more than half stalled (a stall = the response stops midway through streaming). What worked was not overtrusting “delegation = fast,” but the discipline of measuring and recovering.

① measure the damage with a presence matrix … present 21/32, missing 11 (writes are whole-file at once = no half-cut file remains)
② redeploy only the failed ones, at lower load … reduce each agent's share
③ whatever still fell, do directly in main … finish reliably by hand in a stable place
④ confirm consistency with a mechanical check … 0 internal-link errors

I could list the missing ones because writes are whole-file at once — a stall leaves no half-written file behind. Speed is designed together with how it breaks.


”A fleet that doesn’t fumble” beats “a single all-rounder”

Building two systems in parallel, what landed is that an agent’s strength isn’t decided by one agent’s cleverness. Split by role (implementation and verification to different eyes, different permissions), assign capability (a strong model for what mustn’t be gotten wrong, without skimping), measure delegation’s structural cost (one heavy task goes to the main directly), and design how it breaks (even when it falls, keep it shaped so you measure the damage and recover). What was strong wasn’t a smarter single agent, but the fleet that closed off unclever moments with structure and discipline.

How I folded failures that even a fleet lets through — such as an implementation that is “technically correct yet doesn’t look finished” — into gates in the instructions is in Lifting “technically correct” to “a finished product”. How a fleet that spans projects pulled another project’s decision out of shared memory and contaminated ours is in Detecting and separating another project’s decision that had leaked in.


Feel free to send a message

Job offers, project referrals, feedback, questions — anything is welcome. I sincerely hope to connect with people who share high ambitions. I will keep taking on the challenges I have staked my life on. Thank you very much.