Dynamic subagents are impressive to watch. I eventually found I wanted the work to become explicit before the agents were spawned.
I used Ultracode for quite a while. And to be fair, it's a very cool feature.
You give it a problem and instead of having one agent work through it, Claude dynamically builds a workflow around the problem. It spins up subagents to investigate things, challenge other agents, review results and create more work as the workflow develops.
I liked the idea enough that some of what I learned from using it definitely influenced Grid. But I eventually disabled it.
Multi-agent workflows do work. That is closer to the reason I stopped than any failure was. They work well enough that it's very easy to spend an enormous amount of compute before realizing the whole swarm is solving the wrong version of the problem.
One prompt can turn into a lot of agents
With Ultracode, one prompt can turn into many agent calls. There is decomposition, research, implementation, adversarial review, more work based on that review, another review, and so on.
When everything goes well, it looks great. The problem is what happens when the initial understanding isn't quite right.
Now being wrong is expensive. Instead of one agent going down the wrong path, I can have multiple agents researching, implementing and reviewing work based on the same bad assumption.
Because the workflow is dynamic, I also don't necessarily know ahead of time how many agents are going to be involved, what each one will spend, or how much review they're going to generate.
I didn't want control over every individual tool call. I wanted control over the shape of the work before the expensive part starts.
Adversarial review is useful until it isn't
One thing I really liked was adversarial review. Having another agent look at an implementation specifically to find problems can be extremely useful, so I brought that idea into Grid.
But adversarial reviewers are very good at finding issues. And then finding more issues. And then finding more issues.
I've had tasks go through three rounds of adversarial review and end up with something like 20 review items. At some point you have to ask whether you've discovered 20 real engineering problems or whether you've built a machine whose job is to keep producing objections.
Once that happens, the review itself becomes difficult to review. There is too much information, it becomes hard to tell what matters, and I have to reconstruct why all these decisions were made.
So I still use adversarial review, but mostly where the difficulty justifies it. For a hard change, having a fresh agent argue against the implementation before it gets to me can be valuable. For an easy change, it can just burn tokens and start inventing things to worry about.
The difference is where the subagents come from
Both Ultracode and Grid Masterplans are multi-agent workflows. The important difference is how those agents get created and what exists around them.
With Ultracode, the workflow is dynamic. Claude is working on the problem and decides it needs subagents. Those subagents exist inside the workflow Claude is constructing while it runs.
Prompt -> Claude -> dynamic subagents -> more subagents/review -> result
A Grid Masterplan does something slightly different. During Prepare, the Masterplan decomposes the larger problem into explicit subcards. Each subcard becomes a normal piece of Grid work with its own scope, dependencies, difficulty, verification criteria and state.
Then the subagents are spun up through the SDLC of those subcards. A subagent isn't spawned simply because the current Claude session dynamically decided it wants another agent. It is spawned because a defined piece of work reached a stage in its lifecycle where an agent is needed.
Goal -> Masterplan Prepare -> Subcards -> an agent per subcard, in waves
-> integrated result
That sounds like a small distinction, but for me it changes a lot. The orchestration moves out of the agent conversation and into the work itself.
I can see the subcards before implementation starts. I can see their dependencies, which ones can run in parallel, their difficulty, which model and effort they'll get, and how each one is supposed to be verified.
The agents working on them don't need to know that they're part of some complicated swarm. From their perspective, they're picking up a properly prepared Card and doing a defined job.
Ultracode dynamically creates subagents inside the agent workflow. A Masterplan creates durable work, and Grid's SDLC creates the subagents needed to execute that work.
My alternative became the Masterplan
I still wanted large problems to be decomposed and worked on by multiple agents. I just wanted the decomposition to happen somewhere I could see and approve it.

A Masterplan starts with a larger goal. During Prepare it investigates the goal and turns it into smaller Cards. Those aren't vague jobs like 'investigate auth' or 'fix frontend'. They're normal Grid Cards that get properly prepared.
Each one should have a clear problem, scope, task list, verification criteria, expected files, dependencies and difficulty level. So before I start throwing compute at implementation, I have a human-readable description of what the system believes the actual problems are.
The unit of parallelism became a problem I can understand
I don't really want an agent swarm to be my unit of parallelism. I want a well-defined engineering problem to be my unit of parallelism.
If a Masterplan produces 12 subcards, I can look at those 12 subcards. The Masterplan can work out their dependencies and decide which ones can run at the same time. Maybe wave one contains three independent Cards. Once those finish, wave two can start another four.
The orchestration is still happening. There can still be a lot of agents. But the thing being orchestrated is no longer a pile of transient agent calls. It's a graph of durable pieces of work.
Each subcard is a real piece of work
A Masterplan subcard isn't a second-class task. It is a Card on the Board with its own stage, its own scope, its own task list and its own definition of done, and you can watch the job come apart and go back together.
What a subcard doesn't have is a session of its own. The Masterplan runs it as a builder agent, ticks its tasks and closes it, and that builder runs the tests of the files it touched. The heavier work happens once on the parent after the last subcard closes: the full project check, a reconciliation pass over the subcards against each other, and the adversarial review.
A Masterplan might be a very hard overall problem without every part of it being hard. One subcard might need a strong model with high effort. Another might be a straightforward mechanical change that a cheaper model can do. Another might only be Research.
That gives me much better control over token spend. The Masterplan defines the engineering problems. The difficulty of each problem determines the appropriate workflow. Then my current compute budget helps determine which model and effort actually picks it up.
The integration boundary sits at the Masterplan
The Masterplan gets a worktree, and its subcards do their work inside that one tree rather than in trees of their own. Grid works the waits out into waves, the Masterplan starts a whole wave in one turn, and two subcards that would edit the same files are kept from running at the same time.
That gives me a useful integration boundary. Instead of every parallel agent eventually fighting over main, the Masterplan becomes responsible for integrating the work it created, and its branch is the single one that lands.
If two subcards cause a conflict, the Masterplan can resolve that conflict. If integrating one subcard changes an assumption for another, that's something the Masterplan can deal with. The parent owns the result.
Don't run the expensive checks 12 times if you don't need to
Suppose a Masterplan has 12 subcards. I don't necessarily want every one of those Cards running the complete E2E suite, starting every service and performing every expensive verification independently.
The subcards verify the things relevant to their own work. The Masterplan does the heavier integration verification, once, after every subcard has closed and its work is in the tree.
It can run E2E tests against the combined result, start the application and verify the complete feature. This saves compute, but more importantly it tests the thing I actually care about: does the integrated result work?
Human input happens through the Masterplan

I don't want a 14-subcard Masterplan to create 14 unrelated interruptions. The Masterplan owns the work, so it also becomes the main place where the work comes back to me.
I can see what the Masterplan was trying to accomplish and inspect the changes produced by each subcard. The individual Cards are still there when I need to drill down, and the Masterplan's own session holds the transcript of every agent that worked on them, but I can review the overall result from the parent instead of reconstructing the feature from a collection of agent sessions.

If I reject something or have a question, that feedback happens in the context of the Masterplan. That's important because my responsibility hasn't changed just because more agents were involved. I'm still responsible for the resulting code, and that code still gets reviewed by my peers.
A lot of Grid was built this way
This isn't really a theoretical architecture anymore. A lot of Grid features have been built using Masterplans.
That also means I've seen plenty of places where this approach is annoying. Decomposition isn't always correct. Dependencies aren't always obvious. Subcards can still conflict. Sometimes the Masterplan makes something into two Cards that should obviously have been one. Sometimes parallel work turns out not to be parallel at all.
But when something goes wrong, I can usually point at the thing that was wrong. The Card boundary was bad. The dependency was missing. The verification wasn't strong enough. The difficulty was wrong. The plan made a bad assumption.
Those are problems I can understand and improve. That's much more useful to me than simply knowing that a swarm produced a bad result.
I still like multi-agent systems
Disabling Ultracode didn't convince me that subagents are the problem. Grid uses lots of them.
The difference is that I generally don't want one agent dynamically constructing a large tree of other agents inside its own workflow. I want the work decomposed into durable units first, and then I want the SDLC of those units to decide when agents should be spawned.
A Prepare agent can prepare a subcard. A Doing agent can implement it. A hard Card can get an adversarial reviewer. A Verify agent can validate it. Those are still subagents working toward the same larger goal.
But they're attached to work I can inspect, rather than only to an agent process I have to trust.
The boring version works better for me
Ultracode looks cooler. A prompt exploding into a swarm of agents researching, arguing and implementing things is genuinely impressive to watch.
A Masterplan is much more boring. It turns a large problem into a bunch of Markdown Cards. It figures out dependencies. It puts them into waves. Agents pick them up through their SDLC. The parent integrates what they produce. The integrated result gets tested. Then I review it.
But I've gradually found that I prefer the boring version. It is not that I want fewer agents. I actually want to be able to run a lot more of them. I just want the things they're doing to remain understandable.
I don't want the agent call to be the unit of work. I want the engineering problem to be the unit of work.
Once I made that change, multi-agent orchestration started feeling a lot less like watching a swarm and a lot more like engineering.
Comments