Skip to content
AI development tutorialintermediate · 2 min read · 2026-11-01

Why AI Agent Swarms Stall: A Python Simulation

Build a small deterministic Python simulation that shows how multi-agent systems can stall when task ownership is unclear, approval rules are excessive, and agents contend for the same shared state.

What you will learn

  • After this lesson you can model a multi-agent workflow as tasks, owners, approvals, and resources.
  • After this lesson you can identify three coordination bottlenecks: unclear ownership, approval deadlock, and shared-state contention.
  • After this lesson you can explain why adding more agents does not automatically improve an AI swarm.
  • After this lesson you can improve an agent design by reducing approval gates and assigning explicit responsibility.

The coordination problem behind agent swarms

The trend story is not just about Minecraft. It points to a general engineering problem in multi-agent AI systems: agents can spend more effort coordinating than doing useful work.

In an agent swarm, each agent may have a role, a memory, a tool set, and a goal. But if nobody clearly owns a task, if every action needs too many approvals, or if all agents fight over the same shared state, the system can stall even when each individual agent behaves reasonably.

A minimal model: owners, approvals, and shared resources

The simulation below treats a task as four things: a name, an owner, an approval requirement, and a resource it must modify. A task completes after two units of progress.

The model tracks four failure signals: - ownership_stalls: work exists but has no owner. - approval_waits: an agent spends its turn waiting for, or collecting, approval. - contentions: multiple agents try to use the same shared resource in the same step. - idle: an agent has no owned task available.

Runnable Python simulation

The first scenario represents a bureaucratic swarm. One task has no owner, one task requires more independent non-owner approvers than are available, and several agents compete for the same world_state resource.

The second scenario uses explicit ownership, feasible approvals, and separated resources. It is not smarter; it is better coordinated. This is a toy model for reasoning about coordination, not a benchmark of any real AI system.

How to read the result

In the bureaucratic run, only 2 of 5 tasks finish. The unowned market task stalls every day. The charter task becomes selectable only after A finishes farm, then it waits because A needs 3 independent approvals but only B and C can approve.

In the accountable-team run, all 4 tasks finish. There is still one approval wait, but it is feasible and bounded. This is the design lesson: coordination rules should make progress easier to prove, not harder.

Design lesson for AI agent systems

For real AI agents, the same pattern appears in planner-worker systems, tool-using assistants, code agents, and simulation agents. You need more than prompts saying collaborate.

Use explicit task ownership, bounded approval paths, and narrow shared state. If an agent cannot tell whether it owns a task, whether approval is possible, or whether it may safely write to memory, the swarm can look busy while making little progress.

Code

Python · Simulating bureaucracy in a small agent swarm✓ Executed & verified · Python 3.11.2
from dataclasses import dataclass, field


@dataclass
class Task:
    name: str
    owner: str | None
    approvals_required: int
    resource: str
    progress: int = 0
    approvals: set[str] = field(default_factory=set)


def simulate(label: str, agents: list[str], tasks: list[Task], days: int) -> str:
    metrics = {
        "ownership_stalls": 0,
        "approval_waits": 0,
        "contentions": 0,
        "idle": 0,
    }

    for _ in range(days):
        used_resources = set()
        metrics["ownership_stalls"] += sum(
            1 for task in tasks if task.owner is None and task.progress < 2
        )

        for agent in agents:
            task = next(
                (t for t in tasks if t.owner == agent and t.progress < 2),
                None,
            )
            if task is None:
                metrics["idle"] += 1
                continue

            if len(task.approvals) < task.approvals_required:
                approvers = [a for a in agents if a != task.owner]
                if len(approvers) < task.approvals_required:
                    metrics["approval_waits"] += 1
                    continue
                for approver in approvers:
                    if approver not in task.approvals:
                        task.approvals.add(approver)
                        metrics["approval_waits"] += 1
                        break
                continue

            if task.resource in used_resources:
                metrics["contentions"] += 1
                continue

            used_resources.add(task.resource)
            task.progress += 1

    done = sum(1 for task in tasks if task.progress >= 2)
    total = len(tasks)
    return (
        f"{label}: done={done}/{total} "
        f"ownership_stalls={metrics['ownership_stalls']} "
        f"approval_waits={metrics['approval_waits']} "
        f"contentions={metrics['contentions']} "
        f"idle={metrics['idle']}"
    )


agents = ["A", "B", "C"]

bureaucratic_tasks = [
    Task("farm", "A", 0, "world_state"),
    Task("wall", "B", 0, "world_state"),
    Task("road", "C", 0, "world_state"),
    Task("market", None, 0, "world_state"),
    Task("charter", "A", 3, "council"),
]

accountable_tasks = [
    Task("farm", "A", 0, "land"),
    Task("wall", "B", 0, "stone"),
    Task("road", "C", 0, "path"),
    Task("market", "A", 1, "trade"),
]

print(simulate("bureaucratic_swarm", agents, bureaucratic_tasks, days=4))
print(simulate("small_accountable_team", agents, accountable_tasks, days=5))

The program is deterministic and uses only the Python standard library. It compares a poorly coordinated swarm with a smaller accountable workflow using the same simple execution rules.

Common mistakes

  • ✕ Assuming more agents always means more throughput.

    ✓ Measure coordination costs. More agents can increase collisions, duplicated work, and waiting unless ownership and resource access are clear.

  • ✕ Using approval rules that are impossible to satisfy, such as requiring more independent non-owner approvers than the team can provide.

    ✓ Validate workflow constraints before execution. In this model, the owner cannot approve their own task, so required approvals must be less than or equal to the number of other agents.

  • ✕ Letting every agent write to the same shared state at the same time.

    ✓ Partition state by task or domain, or introduce an explicit scheduling policy so only one agent modifies a contested resource at a time.

Practice

  1. Change the bureaucratic scenario so road uses a separate path resource instead of world_state. Which metric should decrease?
  2. Run the bureaucratic scenario for 6 days instead of 4. Which task remains blocked because its approval rule is impossible in this model?
  3. Modify the simulation so agents choose the owned task with the fewest remaining approvals instead of the first owned task.

Quick quiz

Q1. What is the exact output of the runnable simulation?
Q2. Which metric most directly indicates that multiple agents tried to modify the same shared resource in the same simulation step?
Q3. Why does the `charter` task in the bureaucratic scenario fail to progress?
Q4. What is the best general fix for the unowned `market` task in the bureaucratic scenario?

Key takeaways

  • Agent swarms can fail because of coordination design, not only because of weak individual agents.
  • Every task should have a clear owner or an explicit routing rule for assigning one.
  • Approval workflows must be feasible and bounded; impossible approval rules create deadlock.
  • Shared state should be partitioned or scheduled to avoid agents blocking each other.
  • Measure stalls, waits, and contention instead of assuming more agents improve throughput.

References

See the full Python learning path