DEV Community

Cover image for Code Agent Anatomy (19): AgentTeams — The Life and Death of an Experimental System
WonderLab
WonderLab

Posted on

Code Agent Anatomy (19): AgentTeams — The Life and Death of an Experimental System

Start with a Question

AgentTeams was removed — does that count as a failure?

My answer: no.

When a feature gets removed, there are two entirely different reasons:

Type one: The design was flawed — it was done wrong. A bug was introduced, or a technical path that led nowhere was chosen.

Type two: It exceeded the current system's scope — it belongs somewhere else. The feature itself is fine, but it belongs to a more complex problem domain. Forcing it into the current system would damage the overall structure.

AgentTeams is the second type.

Understanding this distinction is what lets you understand why the MyCodeAgent team spent effort implementing it, and why they then spent effort removing it — and what that process means for the project itself.


Reviewing AgentTeams' Design and Implementation

This article synthesizes the previous three, so let's do a quick recap:

  • Article 16: Design motivation — a single agent has limited context and can't parallelize; AgentTeams provides a team model to solve this
  • Article 17: Message protocol — SendMessage + ACK three states (pending/delivered/processed), ensuring reliable message delivery
  • Article 18: TeamFanout/Collect — non-blocking distribution, context isolation, conflict detection without auto-merge

From a design perspective, all three mechanisms have value. So why remove them?


The Conclusion First

The core reason AgentTeams was removed is not one thing, but a three-layer problem stacked together:

Layer Problem
Complexity The complexity introduced by multi-agent systems far exceeded the problems it solved
Scope It doesn't belong to "agent harness core" — it belongs to the "application layer"
Cost Maintaining an experimental system continuously drains core system energy

The essence of the removal was a boundary redrawing: taking a feature that started as "let's try it" and stripping it out of the main product boundary — preserving it in Git history rather than in the codebase.


I. Complexity Snowball: Every Additional Agent Multiplies Complexity

Let's start with the most direct reason: complexity.

The complexity in a single-agent system comes mainly from the non-determinism of LLM calls, the side effects of tool execution, and context management. We covered these in depth in Part 4 — they can be managed systematically.

But multi-agent systems introduce a whole new class of complexity, and it grows multiplicatively, not additively.

A concrete example. When a single agent hits a tool call failure, the handling logic is:

Tool call failure
    │
    ▼
Classify: is it recoverable?
    │
    ├── Recoverable → retry (limited attempts)
    └── Not recoverable → take termination path
Enter fullscreen mode Exit fullscreen mode

This logic is relatively clear; Article 14 covered it in detail.

But if a member agent inside AgentTeams has a tool call failure, the situation becomes:

Member agent 3's tool call failed
    │
    ▼
What does this failure affect?
    ├── Is member 3's task just "broken," with other members unaffected?
    ├── Is the file member 3 was modifying also being modified by member 4? (dependency)
    ├── Was member 3 supposed to pass results to member 5? (message dependency)
    └── Does the coordinator need to know about this failure, or silently retry?
         If the coordinator is waiting on TeamCollect, what happens on timeout?
Enter fullscreen mode Exit fullscreen mode

Every "?" is a design question that needs to be answered. And these questions are interdependent — you can't answer any one of them in isolation, because each answer affects the others.

What's more troubling is that some of these problems simply don't exist in a single-agent system — they're unique to multi-agent:

  • Implicit dependencies between member agents: Two members modifying the same file — who goes first matters enormously to the outcome
  • Coordinator state explosion: The coordinator must track the state of all members; more members means a more complex coordinator state machine
  • Debug difficulty: When a single agent has a problem, looking at the trace pinpoints it. With multi-agent, you need to look at multiple traces simultaneously and find their temporal relationships

II. Scope Mismatch: Which Layer's Problem Is It Solving?

MyCodeAgent's goals are explicitly stated in five points in the HARNESS_ROADMAP document:

  1. Organize model calls into an interpretable, recoverable Agent Loop
  2. Safely and deterministically schedule tools
  3. Separate complete history, long-term storage, and the model's current view
  4. Judge whether a task is truly complete, and recover finitely after failure
  5. Use constrained sub-Agents to demonstrate context isolation, capability trimming, and independent verification

Note point 5: constrained sub-Agents. Not "a general multi-agent collaboration platform," but "constrained sub-Agents for demonstrating specific capabilities."

What problem does AgentTeams solve? It solves "how to efficiently distribute large tasks in parallel to multiple general-purpose agents" — this is an application layer problem, within the domain of "using agents to complete specific business tasks."

MyCodeAgent's positioning is the infrastructure layer — the skeleton of the agent harness, not an application built on agents.

The mismatch between these two layers created a fundamental tension: the more complete AgentTeams became, the more blurred the project's positioning became.

This is why in HARNESS_ROADMAP, Coordinator, Teams, and Ultraplan are categorized as "for research purposes only" rather than "must implement deeply":

These topics can be discussed in interviews for design and trade-offs, but should not consume the project's main development time.


III. Maintenance Cost: The Hidden Price of an Experimental System

Experimental features have a characteristic: they're off the main path, but they continuously drain the main path's attention.

While AgentTeams existed in the main codebase, it brought these hidden costs:

1. Expanded test surface

Every modification to runtime's core logic required checking whether AgentTeams' behavior was broken. Even with AgentTeams disabled by default, it occupied a slot in the test matrix.

2. Blurred code boundaries

AgentTeams needed access to RuntimeRunner's internals, which meant RuntimeRunner's interface couldn't be changed freely. The dependency between the experimental feature and core features constrained the evolution of both sides.

3. Cognitive overhead

Anyone new to the project needed to first understand "what is this AgentTeams thing? Will what I'm changing here affect it?" — even though 99% of the time the answer was "no."

The FINAL_REPORT has a data point that illustrates the severity of this problem: before streamlining the runtime, stable production code was 19,320 lines; after removing AgentTeams and other experimental features, it dropped to 14,094 lines. A reduction of 27%.

Nearly a third of the code was burden introduced by experimental features.


IV. The Method of Removal: Respect, Not Deletion

AgentTeams was removed, but not "deleted."

There's a notable engineering detail here: the code wasn't removed with git rm — it was moved out through a documented commit, and then the exact commit reference was saved in docs/research-archive.md:

# docs/research-archive.md

The removed Agent Teams research runtime is preserved only in Git history.
Its exact pre-removal commit is f497b172c9bce8279d9a26eb69273e25db7392cf.

Inspect it with:
git show f497b172c9bce8279d9a26eb69273e25db7392cf:experimental/teams/manager.py
Enter fullscreen mode Exit fullscreen mode

This approach sends a clear signal: we believe this design has value — it just doesn't belong here.

Git history is the long-term memory of a codebase. Anyone wanting to study this design can precisely restore to that moment and see the complete implementation. The current codebase stays clean.

This is fundamentally different from "deleted because it went wrong." The former is a design decision; the latter is failure handling.


V. After AgentTeams Was Removed, Where Did Multi-Agent Capabilities Go?

Here's a very natural question: after AgentTeams was removed, does MyCodeAgent still have multi-agent capabilities?

Yes, but in a different form.

Phase 7's final approach was: instead of maintaining a second ReAct Loop, use constrained sub-Agents that reuse the main RuntimeRunner.

The original AgentTeams approach:
  Main loop ← maintained independently
  Member agents ← maintaining a second loop (experimental TurnExecutor)
  Two loops, two state machines, two fault-handling systems

Phase 7 final approach:
  RuntimeRunner ← the only loop implementation
  Explore Agent ← constrained instance of RuntimeRunner (read-only tools, isolated context)
  Verification Agent ← constrained instance of RuntimeRunner (isolated context, structured verdict)
Enter fullscreen mode Exit fullscreen mode

The difference: sub-agents are no longer an independent second system, but use "configuration" to drive the same system to produce different behaviors.

The "constrained" nature of sub-agents is reflected in configuration:
  - tool allowlist: [Read, Glob, Grep]      # read-only, no writes
  - step_budget: 10                          # maximum 10 steps
  - context source: summary passed in by parent agent  # isolated context
  - completion policy: return_structured_verdict  # structured result
Enter fullscreen mode Exit fullscreen mode

The benefit of this approach: only one loop needs to be tested and maintained; sub-agent behavior can be fully validated by testing RuntimeRunner's configuration.


VI. The Broader Significance of This Story

The lifecycle of AgentTeams is a very common pattern in software engineering:

  1. Identify genuine need: Single agent has limitations, need multi-agent (genuine engineering motivation)
  2. Rapid prototype validation: Build an MVP, see if it works (experimental feature)
  3. Evaluate scope and cost: Which layer does this feature belong to? What's the maintenance cost? (architectural review)
  4. Make a scope decision: Go deeper OR move it out of scope, preserving design knowledge (conscious trade-off)
  5. Clean closure: Remove with documentation, not silent deletion (engineering discipline)

Every step is a conscious choice, not something that just happened randomly.

For anyone who's done engineering for a while, this pattern isn't unfamiliar: there are features where building them is right, because you can't know whether they're worth building without building them; and removing them is also right, because keeping them will drag down the entire system.

AgentTeams is exactly such a feature.


Design Highlights

1. Removal is also a design decision

Both "adding features" and "removing features" require design review. An engineering team that can consciously say "this thing doesn't belong here" is more mature than a team that only piles features on.

2. Git history is the design archive

Saving the pre-removal implementation via commit reference is cleaner and more credible than commenting out code or leaving empty files. Anyone can precisely restore to that moment, with no "residue."

3. Constrained configuration is cheaper than a second system

AgentTeams used a second loop to support multi-agent; Phase 7's alternative used configuration to constrain the same loop. The latter design is leaner, but covers the most valuable capabilities of the former: context isolation and capability trimming.

4. Boundary documentation is more important than boundary code

The "research only" and "must implement deeply" classifications in HARNESS_ROADMAP are boundary descriptions written for future maintainers. The value of these words is no less than the code itself — they explain "why we didn't do it," not just "what we did."


Summary

Why Was It Removed? Detailed Reason
Complexity Multi-agent complexity grows multiplicatively, exceeding the project's current capacity
Scope mismatch Solves application-layer problems; project is positioned as infrastructure layer
Maintenance cost Experimental features contributed 27% extra code, continuously draining core energy
Alternative exists Constrained sub-Agent reuses RuntimeRunner, covering the most valuable capabilities
How was it removed? Moved out with documentation; Git history preserves the exact reference; docs explain the design value

This completes Part 5 on AgentTeams. Looking back at these four articles:

  • 16: Design motivation — single agent limitations; multi-agent needs to solve context, parallelism, and coordination
  • 17: Message protocol — SendMessage + ACK three states, ensuring reliable distributed message delivery
  • 18: Parallel mechanism — TeamFanout non-blocking distribution, TeamCollect fault-tolerant aggregation
  • 19: Removal decision — complexity boundaries, positioning mismatch, maintenance cost, and "constrained configuration" as a lighter alternative

The four articles together tell the same story: a multi-agent system is not "launching multiple models" — it's a complete engineering problem involving messages, state, failures, and boundaries. AgentTeams was a serious attempt, and its lifecycle fully demonstrates the depth of this problem.


About the Source Code for This Series

All analysis in this series is based on the open source project MyCodeAgent.

Related documentation:

  • docs/research-archive.md: Git archive reference for AgentTeams
  • docs/archives/legacy-harness/HARNESS_ROADMAP.md: Phase 7 design goals and trade-offs
  • docs/plans/2026-07-12-lean-runtime/tasks/M2-03-remove-agent-teams.md: Removal plan
git clone https://github.com/chendongqi/MyCodeAgent
cd MyCodeAgent
cp .env.example .env
uv sync
uv run python main.py
Enter fullscreen mode Exit fullscreen mode

Visit PrimeSkills — a carefully curated AI Agent and skills marketplace where every piece of content is validated through real enterprise-grade workflows. No hype, only what actually works.

For more practical knowledge and interesting products, visit my personal homepage

Top comments (0)