The World at PlayWorld Games · Ready to Play

Engineering process · 01

Eight days, 52 games, and the one job I couldn't give the agents

I started using agents to build complete products fairly early. Those projects still had a clear finish line: ship one program, or finish one game. This time I wanted to push further, giving them a small game platform with a starting point but no prescribed endpoint. Instead of a fixed workflow, I used a multi-agent architecture built for open-ended goals and able to grow with the project: the harness handled scheduling and shared state without constraining what Codex and Claude Code could do. The agents chose the next work and divided it among themselves. Eight days later, theworldatplay.com had 52 games; I had touched very little of the code. I was surprised by the work that still needed me.

  • Coding agents
  • Multi-model workflow
  • Product experience

The home page was beautiful and I could not find the games

The first home page looked like a printed magazine: a big headline, generous whitespace, and collages of Connect6, chess, and Hive across the top. Honestly, better than anything I would have designed.

But none of the images were clickable. They were pictures of games, not entrances. On a phone, the first place you could actually start a game was buried seventeen screens down.

Nothing was broken. Every test passed. The catalog, links, and metadata were correct, and the page was fast. By the project's written standards, it was finished.

I opened it and could not find the games.

The system could check whether the page met its requirements. It could not know whether someone opening it could quickly find a game. The home page had not failed; it had completed the written task. The acceptance checklist had no answer for what to change next.

Those eight days were not eight days of continuous execution. When I hit my token limit, the system stopped and waited for the reset. I used those pauses to try the current site as an ordinary player and talk through what I found with the agents. When the limit reset and work resumed, my reaction — I can't find the games — became the starting point for the next round.

A starting point, but no prescribed endpoint

This was what made the project different from my earlier ones. Those complete products could close: ship one program or finish one game, with the endpoint known before the work began. This platform also had a clear starting point — build a site people could play — but I had not listed everything it must eventually contain.

That is what I mean here by an open-ended goal: the starting point and direction were clear, but the endpoint was not written in advance. Each thread still needed a narrow job: build a module, fix a problem, pass a review. Once a round finished, however, the next task might come from the original plan, a problem exposed by the work, or an actual user's reaction, as it did with that home page.

That created a continuity problem. New work still had to respect earlier decisions. By the fortieth task, the thread doing it might never have seen the fourth, but the two could not contradict each other. I began by pushing everything through Claude Code Ultra Mode. It was good at digging into one bounded task, but no single conversation could sensibly hold the whole project forever. I started routing work between models and keeping their shared state outside the threads.

I was not trying to produce a model ranking. The questions were practical: who should choose the next task, which tool could handle it, and whether earlier decisions would survive after that thread was gone.

A thin scheduler, the filesystem, and a short constitution

There was nothing mysterious about bootstrapping this architecture. At the start of the project, I gave the goal to Fable — Anthropic's strongest model at the time — and asked it to build the thinnest scheduler that could work. The first version treated several headless Codex and Claude Code processes as agents. Here an agent was simply a running thread with its own context, tools, and bounded scope, not a persistent virtual employee. When work appeared, the scheduler started one or woke an existing thread.

Once that loop ran, the system kept expanding through the work itself. The agents built the product while revising the scheduler, adding scheduler forms, and refining the roles and documents. The later multi-agent system was not a complete architecture I had designed in advance. It grew through repeated iterations of that cold-start version.

I did not adopt an off-the-shelf orchestration layer. Codex and Claude Code could already read and write files, run commands, inspect code, and carry out tasks, so the harness did not need to reimplement those abilities. It handled task assignment, thread lifecycles, shared state, and which thread should wake next. When the work exposed a new need, the agents could revise the harness itself.

The agents did not need a complicated, separate communication protocol either. They coordinated through the filesystem. The constitution held the highest-level rules; project documents held decisions, experience, findings, and corrections; scheduler forms recorded tasks, threads, and progress. One process wrote down its result, and a process started or awakened later continued from those files.

The constitution answered only a few questions: what counts as fact, who decides when there is a disagreement, what done means, and which boundaries cannot be crossed. The agents worked downward from those principles, adding handbooks and other working documents. A new thread did not need every earlier discussion; it read the constitution, the scheduler form, and the relevant documents, then continued from the state already written down.

Opus plans, GPT executes, and neither grades its own work

In the setup I was using, Opus was the main planning model and also ran the main coordinator threads. Its one-million-token context could hold the constitution, the relevant handbooks, the current plan, and the current diff at once. GPT-5.6 could not do that in the configuration I had.

Execution was different. GPT-5.6 was faster and sometimes produced better code, and through Codex it could call image generation directly; that pipeline produced all of the site's original artwork and other visual assets. For frontend work, I often preferred what Opus made. Those were observations from this project.

In practice, the roles stayed clear:

  • Planning and coordination: Opus read the constitution, relevant handbooks, current plan, and diff, then split the work and kept it pointed in one direction.
  • Execution and assets: GPT-5.6/Codex handled a large share of the code and used image generation for the site's original visual assets.
  • Cross-review: one model executed and the other checked the result, giving the second pass a different line of thought.

I watched mistakes turn into rules

The work followed a rough loop: check the rules, write a plan, build the module, test it, then hand the result to another model for review. theworldatplay.com grew from one Gomoku board into 52 games, followed by AI opponents, daily puzzles, and phone layouts.

Some problems escaped the automated checks. After a layout bug passed them, we added real screenshots and manual visual review to the acceptance process. After an animated state confused players, the interface handbook gained a rule that motion could not replace an explanation. Later threads read those rules before working on similar features.

I did not sit down and write those handbooks in one pass. They accumulated as the project made mistakes, corrected them, and checked the corrections. The agents drafted most of that material themselves.

I could not clear a single beginner puzzle

Later they built the puzzle mode, and I tried the beginner tier. I could not clear a single puzzle. I do not mean that I found it difficult; I mean I could not clear one.

The problem was the definition of the word beginner. The puzzles come from a real bank — in this case Go life-and-death problems — and the agents had built the opening chapters around the middle of that bank, which is a perfectly reasonable move if beginner means the easy end of what we have. But the bank was hard to start with. The long life-and-death problems in it have a measured solve rate whose median is 0.12. Close to nine attempts in ten fail. That was the material chapter one was drawing from.

It was not a bug. Not one number was wrong. Every step from the source data to the schedule was defensible, and the result was a beginner tier that beginners cannot beat.

The fix now sits in the generator as a comment: pull the long problems out into a chapter of their own near the end, thicken the entry tier, let chapter one take the easiest 26 percent, and spread the daily schedule across the pool's tenth, fiftieth and ninetieth percentiles instead of sitting on the median. None of that came from a test. It came from me losing repeatedly.

The data was correct, but it hid a simple fact: someone seeing these puzzles for the first time was unlikely to make it through chapter one. The system did not sit down and play as a beginner, so the problem only surfaced through use.

After that, I stepped outside the development loop from time to time and opened the site as a player. If I could not find a game, I said so. If I could not tell what a piece was doing, I wrote down what I saw. If an animation made me wait without understanding why, I recorded that too. These were not finished specifications. They were places where a user got stuck.

Agents are extremely good at satisfying a written standard. Being a beginner is not a standard.

Sometimes an arbitrator, sometimes a morale officer

I also had to make occasional calls. Some disagreements had two defensible answers and nothing in the existing documents settled them. More analysis would not choose a side, so I did, giving the later work a shared assumption.

There was a simpler kind of stall. Two threads would reopen the same discussion, acknowledge each other's case, and then repeat their original arguments. No test was failing and the code was not broken; the discussion had simply stopped producing new information. I would tell them that the current answer was good enough, ship it, and move on.

I have been writing software for a long time and I had never had to encourage it before.

This was a way of taking part in development that I had never experienced before. I was not there as the programmer, and for most of it I was not really the product manager either. I was a user inside the development process. I told the system where it lost me, made the choices the documents could not settle, and stopped discussions that were no longer producing anything new. The agents still produced most of the code and the rules around it. I kept those judgments for myself.

JOURNAL

Keep reading

All notes