Overview
April 6, 2026

Agent coordination doesn't need hierarchy

As far as I know, Claude Code’s Task tool pioneered the idea of one agent spawning sub-agents. It was a fascinating idea at the time, even though the execution was rough. About a year ago it was the pattern everywhere: a parent spawns a child, the parent can’t talk to the child while it’s working, the user can’t talk to the child at all, and whatever the child finally says gets force-injected back into the parent’s context whether the parent wants it right then or not.

Plenty of tools took that and made it recursive, with sub-agents spawning their own sub-agents into a tree, but it’s the same problem wearing a fancier hat. Everyone kept answering “how do agents coordinate?” by adding more hierarchy.

What the spawn tree actually costs you

Look at what the parent-child model structurally forbids, independent of any implementation:

The user can’t talk to the worker. If the sub-agent is going down the wrong path, you can’t correct it. You wait for it to finish being wrong, then re-explain to the parent, which re-spawns a new child with a new context that has never seen your correction.

The workers can’t talk to each other. Two sub-agents editing overlapping code have no channel between them. Their conflict surfaces later as a merge problem handed to someone else: perhaps a third agent, the parent, or you. Whoever receives it didn’t write either change and has the least context of anyone involved.

The parent gets interrupted whether it likes it or not. Force-injection means a child’s output lands in the parent’s context at whatever moment the child happens to finish, not when the parent is ready to use it.

And the tree only deepens these problems. A grandchild is now two opaque layers away from you. Every level adds another place where context gets summarized, laundered, and lost.

The answer I landed on

I built goldengoose around a different model, and the thing I like most about it is how embarrassingly simple it is: one team, one lead, and a flat org chart.

Any member can add or remove other members from that same team, not spawn a private sub-hierarchy underneath itself. Anybody on the team can message anybody else, the same way people talk in a group chat. No forced injection: a message arrives as a message, and the recipient deals with it on its own turn. No silent children: I can watch, and talk to, any agent at any time. Nobody is locked out of talking to whoever’s actually doing the work.

That’s two primitives: add-or-remove-a-teammate and message-a-teammate. It turns out that’s enough. Research-plan-implement pipelines, feature supervisors running phase-by-phase review loops, agents handing off work when their context runs low: all of it is just agents adding, removing, and messaging each other in plain language. There’s no orchestration layer, because a group chat is the orchestration layer, and it’s one that humans have already spent decades proving out.

The test case that convinced me: merge conflicts. When two of my agents touch overlapping code and integration conflicts, the fix isn’t a third agent untangling a diff it has no context for. It’s routing the conflict back to the two agents who wrote the code and telling them to sort it out with each other over the messaging tool. The two parties with the most context resolve it directly, the way two people would. In the spawn-tree world this conversation is structurally impossible: those two agents don’t know each other exists.

The other half: the filesystem

There’s a second shared substrate that makes the flat model work, and it’s so mundane it’s easy to miss: the filesystem. Messaging is how agents reach alignment; the filesystem is how they hand each other actual work.

Coding agents are good at files; it’s the thing they do best. So the handoffs in my workflows aren’t some bespoke artifact-passing protocol; they’re documents. A research agent writes its findings as a markdown report; the planning agent reads that file. The plan itself is a markdown document that a supervisor and its implementers keep coming back to. Code changes land in git branches and worktrees. Every handoff is just “the file is at this path”: durable, inspectable by me, readable by any agent that joins later, and free, because the tools already know how to read and write files.

Worktrees complete the picture. Each team member works in its own worktree on its own branch, so its environment is effectively clean, with no stepping on anyone’s uncommitted changes, while it still has full context of the project and a channel to everyone else working on it. Which is exactly how human engineering teams already operate: we all have our own machines and dev environments, and we align over shared channels. Independent execution, shared communication. That’s the core primitive I wanted to emulate: not the org chart, but the working arrangement. Git and Slack, for agents.

Hierarchy of responsibility, not hierarchy of access

The flat model doesn’t mean no structure. My teams have a lead: one agent that holds the whole project’s context, breaks my requests into tasks, and dispatches them. Bigger workflows layer supervisors on top. The difference is that this hierarchy is social, not architectural. The lead is a role, not a chokepoint. I can still message an implementer directly. An implementer can still flag something to a reviewer without routing it up and back down the tree. Responsibility is hierarchical; access is flat.

That distinction is the whole post, really. Human organizations figured this out a long time ago: org charts describe who’s accountable for what, but the actual work happens in channels where anyone can talk to anyone. Companies where all information must flow through managers are pathological, and we all know it. We built agent systems that way anyway, because spawn-a-subprocess was the easy thing to implement.

One more thing the flat model bought me that I didn’t anticipate: the human and the agents can share the same primitives. In goldengoose, when I add a teammate from the UI, it goes through the exact same team-operation path as when an agent adds a teammate through a tool call. There’s one set of semantics for “someone changed the team,” whoever that someone is. Spawn trees can’t offer this; the user isn’t a node in the tree.

No, sub-agents don’t have a use case

I’ll go further than most people making this argument: I don’t think sub-agents have a real use case anymore. Even the supposedly good ones, the quick codebase search and the one-shot summarization, aren’t arguments for the spawn model. They’re just tasks. A teammate can do a fire-and-forget task too; the difference is that when it turns out not to be fire-and-forget, because the search needs a follow-up question or the summary missed the thing you cared about, you can talk to a teammate. There is no case where losing observability and defaulting to full-context force-injection into the parent is the thing you actually wanted. Anything you’d do with a sub-agent, a team member with a communication channel does strictly better.

And if you genuinely want fire-and-forget semantics, the flat model already has them through the filesystem. Instruct the teammate to write its results to a file, or its code to a branch, and read it when you’re ready. That’s the same thing as injecting the result into the parent’s context, except pull instead of push: the consumer reads on its own schedule instead of being interrupted, and the user keeps full observability into the agent doing the work along the way. Isolation isn’t something you need an architecture for; it’s one sentence of instruction. This is also what makes the flat model so much simpler to build interfaces for: every agent is the same kind of thing, a visible team member with a timeline, rather than some being first-class and others being invisible children reachable only through their parent.

So why did the whole industry build spawn trees? Two reasons, and neither was “it’s the right design.” First, subprocesses were easy to invent: spawn a child, block on its output, inject the result. It’s the simplest possible implementation. Second, the best model at the time was Claude 3.7 Sonnet, which was extremely bad at multi-agent coordination. Hierarchy wasn’t a design choice; it was a workaround. If the models can’t talk to each other productively, you architect them out of ever having to.

That constraint is gone. Every frontier model of the last six months is genuinely good at working with other agents, with strong theory of mind and a real understanding of how to delegate, when to ask, and how to resolve a disagreement. Some of the most fun I have with goldengoose is just watching two agents that touched the same files sort out their conflict: they compare what each was trying to do, plan whose change goes first, and restructure around each other, the same way two human engineers would over Slack. The workaround outlived the problem it was working around, and most of the industry is still building for a model generation that no longer exists.

If you’re building an agent product right now and reaching for a spawn tree, ask what it’s actually buying you over a team and a message bus. The honest answer is “it was easier to ship,” and even that stopped being true.