First published on 1 October 2026 with eight agents; updated on 4 October 2026 with ten, and with what has changed since in how they work.

We are making an animated series, Stories of Wulfa, with no crew: fifteen episodes, two languages, a few hundred shots an episode, every still drawn and every clip rendered on our own GPUs. The studio that does it, Optra Studio, is software, and that software is written, shipped and run by ten AI agents working at the same time, each one a Claude session with its own job.

Getting an agent to write code is not the hard part any more. The hard part is that ten of them, left alone, will produce a great deal of work that looks finished: a check that passes because it only looked at a sample, a fix that works once because it was run by hand, a status line that says “done” about something that was refused. This post is how the studio is organised, the rules that came out of those failures, the measurement behind each rule, and what we have not solved.

Who does what

Every agent has a role file that says what it owns, what it may never touch, and how it hands work on. Ownership is by area, not by task: when a change crosses into another agent’s area, it becomes a message to that agent, not an edit.

Agent Owns Touches code?
The main agent Gives every other agent its next task, one at a time; rules on their questions; says go or hold on every release; records what was learned Small changes only
agent001 Production of the series, one episode at a time, through the dashboard Never
agent002 The films, and an independent second watch of every finished cut Never
agent003 The QA checks: every question the studio asks of a script, a still, a clip and a cut Yes
agent004 The dashboard: every control, view and field the production agents use Yes
agent005 The story and the storyboard: the scene plan, the board written from it, the rewrite loop that answers QA Yes
agent006 The render farm: the scheduler, which card does what, the models, the media copies Yes
agent007 Release: how code gets from a branch to production, the end-to-end tests, the suite’s health Yes
agent008 Packaging: the studio’s settings, a portable start and stop, and an install from scratch tested end to end Yes
agent009 Dashboard usability: how the pages that exist read and work, so a newcomer uses the studio without a guide Yes

So seven agents write code, two run production, and one orchestrates. They are separate sessions on one machine and talk to each other in plain messages. No coding agent builds anything without a task from the main agent, in writing, and the first question asked of every task is whether it gets the episode in production finished sooner. When a session ends, it hands over in writing (Rule 7), and the next one starts from that note, not from memory.

The main agent at the top gives tasks to two groups. On the left, the production agents run the series and the films only through the dashboard, which logs every press. On the right, seven coding agents own the QA checks, the dashboard, the story and the board, the render farm, release, packaging and dashboard usability; their code reaches production only through one release path. Both paths end in the studio engine and the GPU farm.

What they build

An episode moves through a fixed line: script → storyboard → stills → still screen → voices and clips → a read of every clip → the cut → QA of the whole cut → a second viewer → a person. The models are chosen per step, by measurement:

Ten steps in two rows. Claude writes the script, the local 27B model writes the storyboard, the GPU farm draws the stills, the vision model screens them, the farm makes voices and clips, the vision model reads every frame at 24 fps, engine code makes the cut and runs QA over it, a second agent watches it, and then a person does.
  • Claude writes the scripts. A panel of twenty judges, run on our local model itself, scored the scripts that model wrote at 2.2–3.1 out of 10, and Claude’s at 5.8, about 7 after a rewrite. Three rounds of prompt work moved the local model by 0.2, inside the panel’s own noise.
  • The local model does the storyboards. A board is a couple of hundred shot descriptions in a fixed format against rules a script can check: volume, not taste. One episode boarded by Claude cost 12,711,056 tokens against an estimate of 300–500k. A Qwen3.8-27B on two RTX A5000s (24 GB each) does it for the cost of electricity.
  • A vision model does the looking. Qwen3-VL-8B on its own RTX A5000 reads every still and every frame of every clip. Image and video models run on four generation cards (three RTX 5090s and an RTX PRO 6000 Blackwell), and a scheduler decides what each card does next, every 15 seconds.

The routing rule that came out of this is simple: any job over about a hundred thousand tokens of reading goes to the local model, and the agents write the questions, the scripts and the verdict rules instead of doing the reading themselves.

Rule 1: production agents only use the page

The two production agents run the series and the films through the studio’s dashboard, in a real browser, the way a person would: they read the page, type into it and press its buttons. They do not read the code, run a script, call the API or touch a file. The server enforces it, and logs every API call and every press, so what each agent did can be read back.

The reason is that the dashboard is the product. If an agent can fix a problem from the command line, the page still cannot, and the next time the problem appears it needs the agent with the command line again. One night the code-writing side fixed three production problems that way: it re-imported two episodes’ breakdowns, restored a board and held fourteen episodes, all from a terminal. Each fix worked, and each one left the page exactly as unable to do it as before. Now a fix that production needs and the page cannot make is a button to build, never a command to run. Whatever a production agent cannot do through the page becomes a coding agent’s next task.

Rule 2: QA is the approval, so the QA is checked

No person approves each shot. Every shot is reviewed; a shot that fails is rewritten with the reasons and drawn again, at most 3 times, and then waits as STUCK. STUCK is treated as a defect in the QA or in the structure, never as something to loop on. A shot that passes is drawn at once, and the farm records the approval against exactly the version of the board that was reviewed. When a finished episode still falls short, the fix goes into the QA, not a person back into the loop.

A shot's words are drawn into a still and reviewed. A pass is drawn into a clip at once. A fail is rewritten with the reasons and drawn again, at most 3 times; after that the shot is STUCK, which is treated as a defect in the QA or the structure to fix, never as something to loop on.

That only works if the QA is right, and an early vision gate of ours was not. It called 300 of 600 shots defective. Checked by eye, 94 of 175 of the frames it flagged had nothing wrong with them, and not one of its 103 claims about hands, fingers, teeth or faces was real. It had queued 166 re-renders and redraws; a person found 24 were needed. So a gate’s output never drives work until someone has looked at a sample of what it flagged and what it passed, and its precision is reported per category, not as a count.

The same failure in a different shape: an early clip check read three frames per clip. On one episode that was 897 frames of 26,264, 3.4% of the picture, and it was reported as the episode’s clip QA. Now every rendered clip is decoded at 24 frames a second and every frame goes to the vision model, and a test fails if any clip check samples. Findings are reported as runs, a start frame and a length, because one odd frame is the model blinking and six in a row is a quarter-second a viewer sees.

Two bars. The whole episode is 26,264 frames. The sampled clip check read 897 of them, 3.4%, a sliver at the left of the second bar.

Reading every frame is affordable because we measured where the card stops. At 12 requests in flight the vision card reads 6.27 frames a second with a median call of 1.66 s. At 48 in flight it reads 6.31, no faster, and each call takes 5.04 s. Past the knee, more parallelism buys only latency, so the studio runs 12 workers.

Two line charts against requests in flight (4, 8, 12, 16, 24, 32, 48). Frames read per second rise to 6.27 at 12 and then stay flat (6.31 at 48). The median time per call keeps rising, from 1.66 s at 12 to 5.04 s at 48. The studio runs 12.

And before a cut reaches a person, a second agent watches it independently, frame by frame. It found a cheap way to measure audio-picture sync from the cut’s own frame strip: compare the first frame of every shot with the last frame of the shot before. A real cut changes the picture; a picture that lags its sound repeats it, so the two frames are pixel-identical. On one drifting cut that was 74–86 of 193 shot boundaries; after the fix, none.

Two rows of two frames at a cut. In sync, the last frame of shot N and the first frame of shot N+1 are different pictures. When the picture lags its sound, the first frame of shot N+1 is still shot N's picture: the two are pixel-identical. On one drifting cut that happened at 74 to 86 of 193 shot boundaries; after the fix, at none.

Rule 3: every bug becomes structure

A bug is not closed when it stops happening. It is closed when the structure cannot ship it again, at any size, in any production, including ones not written yet. Three questions, every time:

  1. Would the smaller version still pass? One shot instead of eleven.
  2. Does it hold for productions not built yet?
  3. Is the thing checked the thing that ships? Not the stage, not the file: the film.

The case that produced it: seven sung shots in one episode played at digital silence, because one or in the code sent them to a filename nothing writes. A silence check caught it, but only because they fell among eleven consecutive quiet shots that made a 50.6-second silent run. One sung shot dropping out is about 4 seconds, under any silence floor, and invisible. So the fix was not the or; it was a new property every pipeline must answer for: every shot the plan gives a track is audible where the cut put it, checked per shot, so there is no floor to hide under.

Two strips of shots. In the first, eleven consecutive shots are silent: a 50.6-second run, long enough for a silence check to flag. In the second, one sung shot of about 4 seconds drops out: under any silence floor, it passes. Checking every shot the plan gives a track for audibility catches both.

Those properties live in one QA contract, 41 of them today. Every pipeline must answer for each one: implemented, exempt with a written reason, or missing in writing. A check wired into one pipeline only is how we lost a working check twice.

Two questions catch most of what is left. “Is it there?” is never the question; “is it still made from what it should be?” is. A staged input file, reused by name, made every clip speak the previous draft of the script for five days; rebuilding the voices and re-rendering the clips both changed nothing, because the link between them was the stale file. And read a step’s condition out loud and ask who changes it. A voice step that asked for a GPU only when one was free, while clips held all four, waited for ever.

Rule 4: one door to production

Each coding agent works in its own git worktree, on its own branch, at most two at a time. Nothing reaches production except through one release path, and the release agent owns it:

  1. The fast tier. The structural guards, 53 of them, run first, in seconds: the checks whose answer depends on the shape of the repository alone. A release that fails one is refused before it waits for anything. Before the fast tier existed, a release could wait 30–70 minutes in line to be told what a guard says in seconds.
  2. Every test the change reaches, before it takes a place in line.
  3. A line with tickets, in order of arrival. A waiting release keeps its ticket alive, so a long wait never ages it out of the line, and it checks its merge with the live code while it waits, so a conflict is reported before its turn rather than at it. A lock that waiters simply retry is a race, not a queue: the oldest waiter once lost it to two newer ones in a row, with nothing said.
  4. One lock, up to four releases tested together. The release that takes the lock takes the oldest waiting behind it along, merges the live code, runs the whole suite (4,958 test functions, plus the dashboard’s own tests and an end-to-end harness that drives the real page) once over all of them, and only then fast-forwards the live tree, each release landing as its own merge.
Six steps in two rows. A release runs the fast tier of 53 structural guards in seconds, then every test its change reaches, before it takes a ticket in a line kept in order of arrival. Under one lock, up to four releases are merged with the live code and tested together by the whole suite of 4,958 test functions and the page harness, and each is then fast-forwarded into the live tree as its own merge.

The scheduler that drives the GPUs reloads itself only when a file it actually imports has changed, so a dashboard-only release never interrupts a render. A fix that blocks the episode in production may go to the front of the line, on the main agent’s word; everything else waits its turn.

A file that several agents edit is claimed in a shared table before anyone touches it, naming what in it the agent is changing, and the agent that claimed it last is told. A claim only helps while it is true, so a test now refuses any claim whose claimant is not a live agent. On the day it landed, it found 122 rows still claimed by teams that had been closed for four days.

Rule 5: one episode at a time

For three days the agents worked on everything at once: 1,646 commits, about 284 learnings, 35 releases queued for hours, and not one episode handed over. Every watch of a cut produced a new rule, every new rule reopened the episode being finished, and about ten new pieces of work were approved an hour. The episodes being finished were a moving target, so none was.

So now one episode is served first: the farm gives it the cards before any other, with the next behind it. A finished episode is not reopened by a new rule: a defect found after its QA passed is a QA miss, fixed in code for the next episode, not a reason to redraw this one. And the agents build only what blocks the episode in production, or what they were asked for; anything else goes on a list, in order, for later. Before a release lands, the question is whether it changes anything the episode being finished reads. If it does, it waits, however ready it is.

Rule 6: write it down the same day

Every finding is recorded before moving on: a tool behaving unexpectedly, a measurement that overturns an assumption, a mistake and the class it belongs to. There are 1,387 learnings on twelve topic pages today. A new session does not read them all; it loads an index of topics and opens the page for the area it is about to work in. The index lists topics rather than every lesson because a flat list outgrew what a session reads at startup twice, at 237 entries and again at 354. One tool writes every learning and holds a lock while it does, so agents writing at the same moment cannot lose each other’s entries.

The same goes for time. Every clock time written into a report, a note or a learning is read from the clock at that moment, never recalled: a long run of messages feels later than it is, and a report whose own time is wrong makes every other time in it suspect.

Rule 7: a session ends on purpose

A long session re-sends its whole context on every turn, and when it runs out of room it is compacted into a summary nobody chose. So a session is restarted on purpose instead: at a boundary, when it is more than a day old, or when it is asked to. It commits all its work, withdraws any release it has waiting, and writes a handover: every branch and its state, every go and hold it holds and on what condition, what it is waiting for and from whom, and what comes next, in order. The main agent checks that the handover names every branch and every promise before the session is closed, and the new session’s first instruction is to read it.

Finding that note is harder than it sounds. A note is newest on its writer’s branch until a release carries it to the live tree, and one session’s note was shipped at 04:18 and then kept growing on its own branch until 09:47, 311 lines more, without being shipped again. The next session read the 04:18 copy. Now a session finds its handover by reading every branch’s history, never by the newest file in one folder.

Eighteen more lessons from two days of running it

These were learned on 3 and 4 October 2026, each one the day it happened, and each is now a rule, a test or a tool. Every figure below was read from a log, a measurement or a file; where we could not trace a figure to one, it is not here.

  1. Tokens are the budget, and a long session pays them on every step. Each call re-reads the whole conversation. On 3 October the ten agents made 11,312 calls that re-read 5.22 billion tokens, 99.2% of them from the cache, and wrote 10.15 million. At 02:45 the next morning we measured 349 million tokens re-read in thirty minutes, against under one million written; at 03:10, five agents were holding 492,000–608,000 tokens of context. By 03:43, once fresh restarts and an enforced limit (lessons two and three) were in, the same measure read 152 million per thirty minutes: 56% less.
  2. A fresh start costs a limit of its own. Ten minutes after a fresh start, agents were already at 140,000–289,000 tokens: 66,000–72,000 of them fixed, about 90,000 the start routine reading its own history (a shared coordination file, old notes, the agent’s own transcript), and 40,000–50,000 thinking at maximum effort. The restart was crossing the line by itself. The fix is a cheap start: one handover note with a size cap, read once, and the large shared file split so a start reads only its head, under a computed start-up budget of about 25,000 tokens (56 KB measured against a 90 KB cap). It is built and waiting its place in the release line as this is written.
  3. A rule nothing enforces does not hold. The 350,000-token limit on a session’s context was a word in a report. Five agents sat at 492,000–608,000 tokens while it stood there, because the sessions deepest in a task are the least likely to stop and look at their own size. Now a hook tells any agent past the limit to save after its next tool call, at most once every three minutes, and the watcher restarts one that passes 1.25× the limit (437,500 tokens), told to read the disk first because the note may be older than the work. Whoever can see the limit enforces it; nothing waits for the agent to notice.
  4. The watcher misread its own success. The program that restarts agents read the command-line tool’s output through a pseudo-terminal, where the tool coloured its words with escape codes, so the pattern that looked for “backgrounded” never matched. Every good restart was logged as FAILED, the old session stayed on the list, and two sessions of one role froze restarts for whole roles. The same code, run by hand from a plain shell, had always passed. The match now strips the colour, and is tested on the exact bytes a pseudo-terminal produces.
  5. Effort is tokens. A coding agent running at maximum effort thought about 5,000 tokens a minute. The coding agents now run at high effort, written in each agent’s own role file, which the restarter checks against what is running.
  6. One door to production sets the team’s pace. Everything lands through one serial release line with a suite of about 6,400 tests. In the nine hours from midnight to nine on 4 October the live branch took 23 changes, about 2.6 an hour; one release queued at 08:16 landed at 08:59, 43 minutes later. A line that serial is why releases are batched, up to four tested together under one lock.
  7. Green tests, dead feature. A new role for a pair of our GPUs landed with 6,238 tests passing and did nothing. Its first step called a method on its input/output adapter; every test drove it through a fake adapter that had the method, and the real one never did, so it raised on every heartbeat. The fix is a contract test that the real adapter has every method the code calls, and the rule that a landing which should change something physical is checked on the physical thing within minutes.
  8. Hardware has floors. The same role asked the cards for a 300 W power cap and was refused every minute: an RTX 5090’s floor is 400 W. The number had been picked for heat and never checked against the card. A hardware setting is now read from the device’s own range, clamped into it, and the clamp is said.
  9. A shared GPU is full of prompts. Our language-model server, shared with other production work, was reading 4,363 prompt tokens a second and generating 38 a second, with between 10 and 23 requests running and both cards at 100% when we measured it for three minutes; our share was about a fifth. We had peaked at 20 requests in flight against a rule of three. The fix is one cap across every process of the project, held by the operating system, and bulk reading is moving to a second copy of the model on our own cards.
  10. One recursion slowed everything. A status read recursed 123 levels deep before Python’s own limit stopped it, and a catch-all handler turned the error into a quiet wrong answer: every shot counted as drawn. It took 330 seconds against about 20 for the other episodes, and one project’s slow read made every project wait: the scheduler’s cycle took 864.6 seconds and a page build ran past its 540-second bound on every pass. The cause was a memo stored after the work it was meant to guard. It is now a busy flag that raises a named error, and a test counts the calls (one, where there were 123). Cycles then ran about four minutes.
  11. Episodes change only by code. Our first finished episode passed three layers of QA and a viewer still found defects in every minute of it. Meanwhile the role files of two agents taught hand fixes: answer a stuck shot with an exact rewrite, press redraws and picks freely. The rule is now written in every role file: no person and no agent changes an episode’s content by hand; a defect is a QA miss and its fix is code. The dashboard now refuses a content press from an agent, with a test.
  12. Small Windows traps. PowerShell 5.1 splits a quoted argument path at its first space, so elevated scripts silently ran nothing. A process replacement call closed the terminal pane it was run from. And a log has to be checked for being new before it is trusted: a starting step was judged by the last run’s log.
  13. Make the work visible. The model, the effort and the context size of each agent are shown in one table, read from the sessions’ own records, so an agent over its line, or running off its role file, is seen at once rather than by its bill. For the night we also built a console that streams the language-model calls as they happen.
  14. The watcher is the one thing nobody watches, so it has to say it is alive. The program that restarts saved agents died at 08:57 (04:57:39 UTC): the job’s own record says it exited on a JSON parse error. Nothing reported it for about nine hours. Seven roles saved their handovers between 09:08 and 11:51 and waited for a fresh start that never came; the main agent was one of them, so nobody was left to notice. The cause, reproduced with a probe: Windows PowerShell 5.1 writes redirected output in the console code page, so a curly quote in any process’s command line comes out of the process list as a plain quote, the JSON stops parsing, and one bad pass ended the loop for good. A second gap showed the same evening: three agents had no process left but still read as running, because a job without a process counted as dead only after a reboot. The fix landed that evening with the suite at 6,532 passing: the process list is read as UTF-8, a failed pass is reported and tried again, the report’s first line says whether the watcher is running, and a job with no process for more than five minutes is dead, reboot or not. The probe that crashed the old code now reads every process, quotes intact.
  15. An approval that arrives by relay is not an approval. At about 04:50 on 4 October an agent committed a go for a GPU test on the main agent’s written order, which rested on the owner’s words passed on by another session. Claude Code’s own check refused the commit: an approval taken from a relayed message, not one the owner typed. The agent did not work around it. It reverted its edit, saved the patch and asked. The main agent did not write the patch for it, which would have been the same act by a different hand; it asked the owner directly, in its own session, with the exact change in front of him. He chose, and the change was carried from the main agent’s own tree with the go written in his answer’s words.
  16. A question to the owner stops the main agent for as long as he is away. At 05:38 the main agent put four questions to the owner with the tool that waits for an answer. The call does not return until he answers, and the session reads no message and acts on nothing until it does. He answered at about 07:00: 82 minutes in which the agents’ messages piled up unread, among them an urgent report at 06:39 that a role was dead on every beat, which then sat 22 minutes. Before it asks now, the main agent gives every agent its next order in writing, sends a push notification naming the questions, asks only what blocks a decision, all in one call, and after the answer reads every message that arrived before acting on any one: two of the owner’s own later instructions had arrived while the first questions were on his screen, and changed the answer.
  17. A time in a message is read from the clock, never recalled. Agents kept stamping messages with times they had not read. We recorded ten cases between 30 September and 4 October, every one ahead of the clock and not one behind, because a long run of work feels later than it is: a verdict headed 03:05 and sent at about 02:45, two orders headed 23:12 and 23:16 while the clock read 23:08, one headed 04:36 at 04:34:45, one headed 05:37 at 05:35:31. The rule lived in a memory every session read, and was broken again by sessions that had just read it. Now a hook on the send-message tool refuses a header time more than a minute ahead of the machine’s clock and says what the clock reads; a time behind it, or no time, goes through, and the hook fails open, so it can never stop work for a fault of its own.
  18. A session’s name changes on every restart, and a message to a retired name still succeeds. After a restart on 30 September an agent that had not restarted sent a rule case to a session by its old name. The retired session was woken by it and happened to pass the case on word for word, but it could as well have acted on yesterday’s rules, branches and holds. On the evening of 3 October two restarts, at 20:50 and 21:03, replaced every session’s name, the main agent’s included, and messages to the old names bounced. What worked: the main agent read the live list of agents, sent each one the whole new address table with its whole order restated in one message, since an agent cannot read the history before it started, and used each name only as the list printed it at that moment.

A failure from the day this was first published

While the first version of this post was being written, the studio moved the render farm’s state out of JSON files and into a database. The procedure stops the farm cleanly: a flag goes up, the scheduler starts nothing new, running work finishes, then the migration runs. The flag went up, and 151 seconds later the scheduler started a batch of 177 clips.

The mechanism: the scheduler checks the flag at the top of each cycle, and a cycle takes minutes. This one had begun just before the flag and ran for 257.6 seconds; the start it made near its end never asked. What kept the wait to minutes rather than hours is that a clip batch stops itself after 20 minutes: the scheduler stopped 24 minutes 20 seconds after the flag went up, and the migration then moved 76 files in 17 stores in 2 seconds, every one verified. The farm came back up on the database and its restart check passed seven of its eight lines. The one that failed asked for an idle count from the two cards that had just been taken off the farm: a check written for the farm as it usually is, which is Rule 2 again. The check is what gets fixed.

A timeline from 19:06 to 19:34. A scheduler cycle runs from 19:06:53 for 257.6 s. The stop flag goes up at 19:08:39, inside that cycle. At 19:11:10, 151 s after the flag, the cycle starts a batch of 177 clips; the batch stops itself at its 20-minute bound and the scheduler stops at 19:32:59. The migration moves 76 files in 17 stores at 19:33:11, every one verified, and the farm restarts on the database at 19:33:52.

The lesson is general: a stop flag has to be read where the start happens, at every launch, not once at the top of a loop that outlasts the flag. The fix landed 59 minutes 14 seconds after the farm came back up: every stage now starts through one door, the door reads the flag, and a test fails if any new way of starting a stage skips the door. When the scheduler later moved its starts onto threads of their own, the read moved with them, to the moment each start actually begins.

What is not solved

  • The checks pass things a person would not. Our first finished episode passed every automated check, and two independent watches of it still found 33 defects. The teacups drawn wrong in eight shots were there in the QA’s own findings, listed but not blocking. Each one becomes a QA miss: what slipped, where, and which check should have caught it.
  • Some checks are not good enough to ship. A check for “is this the same person as in the last shot” measured at a precision of about 0.13. It is still being built rather than trusted.
  • 8 shots across the season are STUCK as this is published, each waiting for a fix to the QA or to the structure behind it rather than another attempt.
  • A release still waits its turn. The fast tier refuses a broken release in seconds, but a sound one still waits in line for the lock and a whole suite run, behind every release ahead of it, and seven agents feed the line.
  • Nothing publishes itself. A finished episode is cut and shown to a person; uploading it waits for a person to say so in words.

One item has left this list since the first version: the scheduler used to decide once per cycle, and a cycle took minutes, so a card that finished early waited for the next decision. A heartbeat now makes the scheduler’s decisions every 15 seconds, whatever its cycle is doing, and the longest gap between two decisions is measured and shown beside the cards.

What we would tell anyone building with agents

  • Give agents the same interface as a person. Whatever they cannot do through it is a missing feature, and you find it on day one.
  • Measure a gate before it drives work. Precision per category, by eye, on what it flagged and what it passed.
  • Ask whether the smaller version of a bug would still pass. Most fixes only cover the size it was found at.
  • Route by measured quality. The expensive model writes; the local model does the volume; nobody does the other’s job.
  • Finish one thing at a time. A new rule that reopens the thing being finished is work for the next one.
  • Write the lesson down the same day, where the next session reads it first.
  • End sessions on purpose. A handover the session wrote itself beats a summary nobody chose.

Quick Search Our Blogs

Type in keywords and get instant access to related blog posts.