Managing Multiple Agents
Four Minions assemble an Ikea bookshelf, and Stuart gets a promotion he didn't ask for
Agent-driven AI programming is so 2025. This year, it’s all about co-ordinating multiple agents who work together as a team, with shared tasks, inter-agent messaging and centralized management. Armed with more than 200 years’ worth of management research, this post explains how different management styles work with agents.
The problem
You have a team of agents on one side. On the other side, a set of poor-quality instructions and all the pieces of an Ikea bookshelf. The challenge? Coordinate work amongst the agents to get the job done.
We’ll have four agents / minions for this task.
Kevin’s job is reading the instructions to the rest of the group.
Stuart is the parts manager (he grabs the bits that are needed)
Bob is responsible for assembling (he builds!).
Dave performs QC (there’s a fixed chance that Bob will make a mistake)
Let’s see if Kevin, Stuart, Bob and Dave can put this shelf together.
Under the hood, I’m using gpt-oss:20b (an open-weights 20B parameter model; big enough to reason about tasks, small enough to run on my GPU) to provide the behaviour . Shout if you want the source code, but honestly you can almost certainly just paste this blog post into an LLM and generate it 🙂
The task is assembling a bookshelf, and there are some instructions behind it. Each part of the process has an ID (step 1 to 20), a description, some required parts, required hardware, some dependencies and whether it requires a tool.
It looks a bit like this.
new("S01", "Verify all parts and hardware against inventory list.",
["SidePanelLeft", "SidePanelRight", "Base", "Top", "BackPanel", "Shelf1", "Shelf2", "Shelf3"],
["Dowels", "CamLocks", "ScrewsLong", "ScrewsShort", "BackNails"],
Array.Empty<string>(),
requiresTool: false),
new("S02", "Insert dowels into side panels.",
["SidePanelLeft", "SidePanelRight"],
["Dowels"],
["S01"],
requiresTool: false),
new("S03", "Attach cam locks to base panel.",
["Base"],
["CamLocks"],
["S01"],
requiresTool: false),
new("S04", "Connect base to side panels using dowels and cam locks.",
["Base", "SidePanelLeft", "SidePanelRight"],
["Dowels", "CamLocks"],
["S02", "S03"],
The job of the orchestrator is to distribute the work to the minions to get the work done.
Each type of orchestrator has a name, some guidance and some constraints and uses it to plan the work. The orchestrator asks each agent to respond with some JSON describing what they did and then applies that change. There’s a fixed probability that each assembly step has a problem that Dave will notice and request rework.
The job finishes when the last part of put in, and Dave gives the seal of approval.
Command and Control
Command and Control is based on a theory that everyone that works for you requires explicit instructions. The orchestrator here decides what to do and has to approve each step. As you might imagine this isn’t much fun for the minions, but it makes the manager feel pretty good!
We model this by ensuring that all agents report back to the orchestrator for permission to do the action. As you might imagine for assembling a bookshelf it isn’t an ideal management style (though there’s plenty of times it might make sense - high-stakes security, safety-critical situations and so on). When running in this style, it’s very inefficient and the minions exchange a huge number of messages to get the job done (most of which are just responding with yes, they are doing the right things).
On the plus side, we have a working shelf.
Let’s try Taylorism
Taylorism, also known as scientific management, looks at workflows and applies process engineering to break the work down into small, discrete tasks.
It still keeps the overwhelming view that management is the clever part and offers little/no autonomy for the the workers. The manager in this case provides small steps with standardized instructions. There’s zero autonomy for the workers.
- Tick 11: Planned actions: Kevin (InstructionReader):Communicate(S02)
- Tick 11: Kevin (InstructionReader) communicates: Issue standardized instruction for FetchParts.
- Tick 12: Planned actions: Stuart (PartsManager):FetchParts(S02)
- Tick 12: Stuart (PartsManager) on S02 - I pick up the SidePanelLeft and SidePanelRight, grab the dowels, and insert them into the pre‑drilled slots.
- Tick 13: Planned actions: Kevin (InstructionReader):Communicate(S02)
- Tick 13: Kevin (InstructionReader) communicates: Issue standardized instruction for Assemble.
- Tick 14: Planned actions: Bob (Assembler):Assemble(S02)
- Tick 14: Bob (Assembler) on S02 - I insert dowels into the corresponding holes on SidePanelLeft and SidePanelRight.
The orchestrator is clearly explaining what to do, breaking the work down into small tasks. But one thing you’ll notice here is the lack of autonomy. Bob (whose entire role is assembling) is simply told to assemble. You’d think Bob would know this given that it’s his role. For the task of assembling the bookshelf, this works dramatically better than Command and Control, with much fewer messages exchanged.
But, perhaps we can do even better than this?
Outcome-focused management
Now we’re evolving again. In an outcome-focused management style, you assume that your team intrinsically wants to do a good job. They’re smart and get things done, they just need to know what needs to be achieved (rather than the individual steps to get there). However, we have to have some co-ordination, so as well as clear outcomes, we’ll try to limit work in progress and make sure we finish the subtasks before starting the next.
- Tick 16: Planned actions: Kevin (InstructionReader):ReadInstructions(S05)
- Tick 16: Kevin (InstructionReader) on S05 - I align the Top panel between the SidePanelLeft and SidePanelRight and secure it using the CamLocks.
- Tick 17: Planned actions: Kevin (InstructionReader):ReadInstructions(S06); Stuart (PartsManager):FetchParts(S05)
- Tick 17: Kevin (InstructionReader) on S06 - I attach the fixed shelf supports to SidePanelLeft and SidePanelRight using ScrewsShort.
- Tick 17: Stuart (PartsManager) on S05 - I attach the Top panel to the SidePanelLeft and SidePanelRight using the CamLocks.
- Tick 18: Planned actions: Kevin (InstructionReader):Communicate(n/a); Stuart (PartsManager):FetchParts(S06); Bob (Assembler):Assemble(S05)
- Tick 18: Kevin (InstructionReader) communicates: Deferring new work until outcomes are shipped.
- Tick 18: Stuart (PartsManager) on S06 - I attach fixed shelf supports to the SidePanelLeft and SidePanelRight using ScrewsShort.
- Tick 18: Bob (Assembler) on S05 - I attach the Top panel to the SidePanelLeft and SidePanelRight using CamLocks.
- Tick 19: Planned actions: Kevin (InstructionReader):Communicate(n/a); Bob (Assembler):Assemble(S06); Dave (QualityChecker):QualityCheck(S05)
- Tick 19: Kevin (InstructionReader) communicates: Deferring new work until outcomes are shipped.
- Tick 19: Bob (Assembler) on S06 - I install the fixed shelf supports on the left and right side panels using the short screws.
This example is notable for a couple of reasons:
We’re now seeing agents do actions at the same time (Tick 18 shows Bob and Stuart getting on with some work)
With our new focus on outcomes, Stuart’s developed some new skills and is assembling the parts too!
This is the most interesting thing that happened in the whole experiment. Stuart was defined as the parts manager (fetching, not building). But the outcome-focused orchestration gave him enough latitude to recognise that assembling was the bottleneck, and he could help. No one told him to. The orchestration style permitted emergent role-expansion. This is exactly what we want to see in our engineering teams too - if there’s work to be done and someone can pick up the task, they should. In the end, the goal-oriented team has completed the work five times faster than the command and control orchestrator, and 3x faster than Taylorism.
Fully autonomous
In a fully autonomous self-organizing team style we have minimal management, instead relying on peer coordination to achieve our objectives. This moves us more from orchestration to a jazz-based freeform vibe.
Even with minimal constraints, the agents got the shelf built. The path there was messy!
Tick 5: Dave (QualityChecker) on S03 - I attach the cam locks to the base panel.
Tick 6: Planned actions: Kevin (InstructionReader):ReadInstructions(S04); Stuart (PartsManager):FetchParts(S04); Bob (Assembler):Assemble(S04); Dave (QualityChecker):QualityCheck(S04)
Tick 6: Kevin (InstructionReader) on S04 - I insert the dowels into the base and side panels, then engage the cam locks to secure them together.
Tick 6: Stuart (PartsManager) on S04 - I locate and gather the Base, SidePanelLeft, SidePanelRight, and prepare the Dowels and CamLocks to connect the base to the side panels.
Tick 6: Bob (Assembler) on S04 - I insert the dowels into the side panel holes, align them with the base, and secure each panel in place with the cam locks.
Tick 6: Dave (QualityChecker) on S04 - I insert the dowels into the base and side panels, then secure them with the cam locks, confirming the joints are tight and aligned.
Tick 7: Planned actions: Kevin (InstructionReader):ReadInstructions(S05); Stuart (PartsManager):FetchParts(S05); Bob (Assembler):Assemble(S05); Dave (QualityChecker):Communicate(S05)
Tick 7: Kevin (InstructionReader) on S05 - I align the Top panel between SidePanelLeft and SidePanelRight and secure it with CamLocks.
Tick 7: Stuart (PartsManager) on S05 - I attach the top panel to both side panels using the CamLocks.
Tick 7: Bob (Assembler) on S05 - I place the top panel onto the side panels and secure it with the CamLocks.
Tick 7: Dave (QualityChecker) communicates: status update
Tick 8: Planned actions: Kevin (InstructionReader):ReadInstructions(S06); Stuart (PartsManager):FetchParts(S06); Bob (Assembler):Communicate(n/a); Dave (QualityChecker):QualityCheck(S05)
In this example, full autonomy has resulted in a lot of thrashing. I didn’t put enough processes in place in the code to stop minions assembling the same piece at the same time. Everyone is assembling everything all of the time, and some of the work is getting repeated.
Part of this is implementation. I could have added shared state or locking mechanisms to prevent duplicate work. But even with better code, fully autonomous agents need shared protocols to coordinate effectively. WIP limits working in the outcome-focused model precisely becuase they were a lightweight cosntaint that preserved autonomy whilst preventing thrashing. Without something like that, you get what you see here!
Autonomy without constraints is chaos (Kent Beck)
For this free-form jazz style to work, you need some guardrails (and perhaps some more intelligent folks than the minions).
Conclusion
Implementing this was fun, but wildly chaotic. Smaller models don’t have great instruction adherence, and each run was a bit of a lottery. If you wanted to do something similar for real, it’s genuinely challenging and not something you can just vibe-code over a weekend.
But the parallels to real engineering teams are hard to ignore. Command and Control works when the stakes are high and the agents (or people) are unreliable (you trade speed for certainty). Taylorism works when you can define the work precisely upfront. Outcome-focused management worked best here, and I don’t think that’s a coincidence - it’s the same model that works best with capable engineering teams. You define what done looks like, set some constraints around work-in-progress, and trust people to figure out the how.
The way you orchestrate agents mirrors the way you orchestrate people. If your agents are inexperienced and unfamiliar with the work, you micromanage them to get the job done. If they’re capable, you set outcomes and get out of the way.
The models are only getting more capable. The orchestration patterns we choose now will matter more than the models themselves.



The IKEA analogy lands perfectly. I built a 4-agent system with Claude Code and the biggest challenge was not the agents - it was me, playing the role of project manager without any of the tools.
Two months of live testing showed me: agents with clear escalation rules outperform agents with 'use your judgment' 3-to-1. Judgment is a bottleneck at scale.
Real comparison data from running both Claude Code and Codex: https://thoughts.jock.pl/p/claude-code-vs-codex-real-comparison-2026