Code Stopped Being the Bottleneck. Management Took Its Place.

October 13, 2026

Part I: Why modular agent systems are built from contracts, ownership, and durable state

What this article covers

I could get more code from agents than I could properly review, so the difficult part became keeping responsibility and earlier decisions visible. I explain that through an accounting microagent with one narrow task, then look at module contracts, the cost of extra agents and the state a new session needs before it can continue.

Full article

The day code stopped being scarce

Have you ever watched a program grow faster than you could understand what had grown?

It happened to me while I was working on an accounting system. At first, the pace felt almost perfect. I described a problem. One agent inspected it, another wrote a module, a third helped with tests. Changes arrived quickly. Documentation grew. Services appeared. Data moved through queues, authorization rules, reports, and background jobs.

Then I noticed something uncomfortable. I could get more code in a day than I could properly review, connect to the rest of the system, and keep in my head.

Writing the code had become the easy part. I needed to understand what we were adding, why it belonged there, and which earlier decision it depended on.

Here is one example from that accounting system. Say $10,000 comes into the account. To the bank, it is one payment. But inside the accounting system, it can mean a whole lot of separate goods and materials. Some materials go into production, and you have to track them as they are used. Or a customer pays a deposit for the month and draws it down little by little. One payment, with all those smaller records behind it.

And you still have to get the details out of the documents. Someone sends an email, someone writes a message, someone fills out a form. An ordinary parser is good at moving a value from field A to field B when you already know what is in field A. It does not understand where an amount is hiding in free text, or what that amount was paid for. So even with automatic document-reading modules, accountants often ended up entering the details by hand.

We put a microagent at that point. We did not even train it in accounting, because that was not its job. We used Terra or Luna and gave it a narrow prompt: find the amount and the purpose of the payment in the unstructured input, then return those fields to the parser. Do not rewrite, skip, or merge items just to produce an answer. If you cannot identify something, say so. The ordinary parser then takes the fields it can understand and puts them into the structured database.

For me, that is the module. Not because we called a piece of software an agent. It has one clear job, limits, and a result you can check on its own.

A vague assumption can enter one module, become an assertion in a test, appear as a fact in the documentation, and return in the next session as established truth. Each local step may look reasonable while the chain is wrong.

That chain is what made me pay more attention to the architecture around the agents. An AI agent is a probabilistic executor inside a system. It may be capable, fast, and surprisingly good at recovering intent. It is still a language model operating with context, tools, permissions, and a loop that lets it choose the next action. Sometimes it chooses well. Sometimes it is confidently wrong.

In the accounting project, I needed a way to keep a reasonable-looking interpretation from quietly becoming the basis of the next module. The small extraction agent was useful because its task and limits were specific. The larger question was how to keep those limits visible as the system grew.

Where does a real module begin?

It is easy to start with a diagram: an architect, a developer, a critic, arrows between them. I understand why that feels like a team. But the diagram still leaves the working questions open. Who can change the module? Who checks the rule it implements? Which result does the next person or agent receive?

If two agents can modify the same file, nobody owns shared state, results move through long narrative summaries, and the worker decides whether its own work is complete, the responsibilities still overlap. An agent can produce a locally sensible change while another agent is working from a different assumption about the same file.

A module begins with a contract and an owner. For each module, I want eight questions answered:

  1. What single decision or transformation does it own?
  2. What is it explicitly forbidden to do?
  3. Which inputs may it use, and where did they come from?
  4. Which observable artifact must it produce?
  5. Who owns that artifact after the handoff?
  6. What may the module read, change, or send outside the system?
  7. Which external check accepts the result?
  8. When must it stop and ask for help?

Once the responsibility is clear, I can decide what should carry it out. A module does not necessarily need an agent inside it.

It can be a function, a SQL query, a deterministic workflow, a human decision, one model call, or a small group of specialists. What matters is whether that piece of the system has a responsibility I can inspect independently.

This changes the design question. Instead of asking, "Which agent should do this?" ask, "What result must exist, who owns it, and what proves it is acceptable?"

Then, if the wrong rule reaches a test or a document, I have somewhere specific to look.

Why should multi-agent design be the exception?

When people first get access to agents, many want to build a small digital corporation. I understand the attraction. I went through it too.

I would work through the options in this order:

  1. Use ordinary code when the rule is known.
  2. Use one model call for one semantic operation.
  3. Use a workflow when the sequence of steps is known.
  4. Use one tool-using agent when the next step depends on what it finds.
  5. Add routing when task classes are distinct and can be classified.
  6. Add orchestrator and workers when work has independent branches.
  7. Use a limited council when several defensible positions require explicit arbitration.

Anthropic's guidance reaches the same basic conclusion: start with the simplest design that works, then add complexity only when it produces a measurable improvement. Its multi-agent research system is a useful positive example and a useful warning at the same time. On an internal breadth-first research evaluation, the system outperformed a single-agent setup by 90.2%. It also used about 15 times as many tokens as a normal chat. Anthropic notes that domains with tightly shared context and many dependencies are a poor fit for the design.

The gain comes with substantial token use, but these are different baselines: the quality comparison is against a single agent, while the token comparison is against an ordinary chat. I cannot turn the two numbers into a cost-per-improvement ratio. I would compare both designs on the same task and count the full cost of an accepted result.

There is independent research behind that caution too. Smit and colleagues, in the 2024 ICML paper "Should We Be Going MAD?", found that multi-agent debate did not reliably outperform simpler prompting strategies without careful tuning. That is evidence about debate protocols, not every modular system. It does give me a reason to make the extra coordination earn its place.

That distinction matters.

Five agents searching five independent source categories can work in parallel. Five agents changing shared architecture, shared data, and adjacent files create a coordination bill. Somebody has to resolve ownership, duplicated effort, conflicting assumptions, stale results, and partial failure.

I want to know whether those extra messages helped resolve the task or just gave me more coordination work.

The architecture earns its complexity only after the complete cost is counted: tokens, latency, failures, human review, debugging, and the price of putting a wrong artifact into durable state.

What should the lead agent actually control?

A lead agent is useful when it plans, decomposes, routes, and assembles. It becomes dangerous when it also owns permissions, shared state, acceptance, and the right to keep trying forever.

I prefer a split between a probabilistic work layer and a deterministic control plane.

The work layer can search, interpret, draft, classify, compare, and propose. The control plane keeps the rules that need to remain stable between model calls:

  • task state and artifact versions
  • access scopes and tool permissions
  • time, cost, and iteration budgets
  • allowed transitions between stages
  • retry rules and no-progress detection
  • approval boundaries
  • final states and termination
  • audit records and recovery points

The model may recommend the next operation. The control plane decides whether that operation is allowed.

For me, this is a practical way to keep responsibility visible. We do not ask a database query to redefine its own permissions. We should not ask a model to be the sole interpreter of a prompt, the executor of the task, the keeper of state, and the judge of whether everything went well.

The Model Context Protocol makes tool boundaries easier to standardize, and agent SDKs make handoffs easier to express. Useful. But a clean protocol does not settle ownership. A typed tool call proves that the arguments fit a schema. It does not prove that the call is wise, authorized, or based on the right fact.

For example, the call can fit the schema perfectly and still treat a monthly deposit as one completed purchase because that interpretation was never checked.

Why is the conversation a poor system of record?

A larger context window seems like a natural answer: give the agent all the documents and the history so it can work out what happened. That helps only if it can distinguish the current decision from the old one. It may find the right fact and give it too little weight, or follow an instruction inside a retrieved document that was never an instruction from the owner.

In that accounting system, I needed to know which decision was still in force. Keeping more conversation did not, by itself, settle that question.

For long-running work, I want the important state outside the conversation:

  • the current goal and its accepted version
  • decisions, assumptions, and their owners
  • verified facts with source references
  • artifacts with version and provenance
  • checks already passed
  • unresolved risks and disagreements
  • the next permitted operation
  • the conditions that stop the run

This state can live in a database, a task ledger, files, or an event log. The storage choice depends on the project. The principle does not: a new session should continue from explicit state, not reconstruct reality from a story about an old chat.

In that accounting system, documentation first felt like extra work. Later it became the production memory. When code arrives quickly, written decisions, module contracts, data definitions, and change logs stop being bureaucracy. They keep the project from dissolving into plausible versions of what somebody thinks happened.

Earlier, code was the main scarce asset. In agent-assisted work, the scarcer asset is often an explainable chain of decisions around the code.

What does a useful handoff look like?

A good handoff is small enough to inspect and complete enough to continue.

It should contain the requested artifact, the evidence used to create it, the checks already performed, the assumptions still open, and the exact next action. It should not depend on the next agent reading a thousand-message transcript and guessing which sentence still matters.

Narrative summaries are useful for humans. They are weak as the only machine contract because they mix claims, evidence, decisions, and uncertainty into one fluent paragraph. Structured fields help separate those categories, but they do not solve truth by themselves. The design needs both: a machine-readable record and a human-readable explanation.

The handoff also needs a way to say that the result cannot be accepted yet.

If a module can only return success or failure, it will often stretch uncertainty into an answer. Give it explicit states such as needs_evidence, conflict, out_of_scope, or human_decision_required. Now the system can stop without pretending.

The next stage can then see that a rule is unresolved instead of treating a fluent explanation as permission to build on it.


Practical takeaways

  • Define modules by one owned result, not by a persona or job title.
  • Keep permissions, budgets, state transitions, retries, and termination in a deterministic control plane.
  • Start with code, one model call, or a workflow. Add agents only when the task needs adaptive action.
  • Use several agents for independent branches with a clear synthesis point. Measure the gain against a simpler baseline.
  • Store decisions, evidence, artifacts, checks, and risks outside the conversation.
  • Make refusal and escalation normal output states.
  • Require every handoff to carry an artifact, provenance, acceptance evidence, and one permitted next action.

In brief

I can inspect a module when its result, owner and acceptance check are clear. Extra agents are useful only when the work and measured benefit justify the coordination. A clean modular system can still carry one believable mistake through several stages. Part II looks at verification and the points where the system must stop.

Sources

  1. Anthropic, Building Effective Agents
  2. Anthropic, How We Built Our Multi-Agent Research System
  3. OpenAI Agents SDK, Agent Orchestration
  4. Model Context Protocol, Architecture
  5. Anthropic, Effective Context Engineering for AI Agents
  6. Smit et al., Should We Be Going MAD?, ICML 2024
← All notes