All field notes

AI agents · Multi-agent systems · Architecture

Agent Swarms: When Multiple AI Agents Help—and When They Make Things Worse

A practical decision framework for choosing a multi-agent architecture, plus a minimal coordinator that keeps concurrency, budgets, and failure handling explicit.

Published
Updated
Reading time
10 minutes

An agent swarm is useful when several genuinely independent lines of work can produce a better result than one agent working sequentially. It is harmful when “more agents” merely multiplies model calls, coordination overhead, and ways to fail.

This field note gives you a test you can apply before adding a supervisor, specialists, shared memory, or agent-to-agent messaging. The goal is not to build the most autonomous system. The goal is to build the smallest system that reliably completes the job.

What changes when one agent becomes many

A single tool-using agent already has a control loop: understand the goal, choose a tool, inspect the result, and decide whether to continue. A multi-agent system adds a second control problem on top of that loop.

The system must now decide:

  • how to split work;
  • which agent owns each part;
  • what context each agent receives;
  • how many tasks may run at once;
  • how agents communicate uncertainty;
  • how partial results are checked and merged;
  • what happens when one worker times out or disagrees; and
  • when the whole system must stop.

Those are distributed-systems concerns wearing an AI label. The language model does not make them disappear.

The emerging Agent2Agent protocol makes the distinction concrete: messages communicate, tasks track stateful work, and artifacts carry results. You do not need A2A to build a swarm, but its vocabulary is a useful reminder that conversation and reliable delivery are different concerns.

If you are deciding where protocol boundaries belong, MCP vs. A2A separates tool access from peer-agent delegation with a concrete architecture.

Start with the single-agent baseline

Before introducing specialists, build one agent with explicit tools, a bounded loop, and observable outcomes. This baseline tells you whether the problem is actually decomposition or simply weak instructions, missing tools, or poor evaluation.

A useful baseline records at least:

SignalWhat it tells you
Task success rateWhether the system completes the user’s goal
Tool-call countWhether the plan is efficient or wandering
Input and output tokensThe cost of carrying context and producing work
Wall-clock latencyWhat parallelism could realistically improve
Retry countWhether tools or model decisions are unstable
Human correctionsWhere the system misunderstands intent or quality

If the single agent cannot complete a task because it lacks a capability, add the capability first. If it can complete the task but takes too long because three independent investigations run sequentially, specialization may help.

The three tests for useful parallelism

I use three tests before splitting a workflow across agents. A candidate architecture should pass all three.

1. The independence test

Can two workers make progress at the same time without repeatedly asking each other for intermediate state?

Researching a codebase, checking current documentation, and designing a test plan can often proceed in parallel. Editing the same function, then editing its caller based on the first change, cannot. The second task has a dependency and should wait.

Draw the work as a dependency graph. Parallel branches justify workers; a mostly straight line does not.

2. The contract test

Can each worker receive a narrow input and return a result that another component can validate?

“Investigate the repository and help” is not a contract. “Return the three call sites of this function, their argument shapes, and any behavior that would break if the return type changed” is much closer.

The contract should define:

  • the task objective;
  • the context the worker may use;
  • the output shape;
  • a time, token, or tool-call budget;
  • acceptance criteria; and
  • what uncertainty looks like.

Structured output helps, but a schema alone is not enough. A syntactically valid answer can still be wrong.

3. The synthesis test

Can you determine whether the combined result is better than the parts?

If five research agents return overlapping prose, the coordinator still has to judge truth, resolve contradictions, and produce one answer. Without a synthesis rule, parallelism moves the hardest work to the end.

Useful synthesis mechanisms include:

  • deterministic merging for non-overlapping artifacts;
  • tests for code changes;
  • a rubric applied to every candidate;
  • citations checked against primary sources;
  • a reviewer that sees both the request and proposed result; and
  • human approval before consequential actions.

A minimal coordinator architecture

Start with a coordinator and stateless workers. Give the coordinator authority to create tasks and merge results. Give workers only the tools and context required for their assignment.

User goal
   │
   ▼
Coordinator ── creates bounded tasks ──┐
   │                                  │
   ├── Worker: repository analysis ───┤
   ├── Worker: documentation check ───┤──► typed results
   └── Worker: test design ────────────┤
                                      │
   ◄──────── validate and synthesize ─┘
   │
   ▼
Final result or explicit escalation

The coordinator owns global state. Workers receive snapshots. This avoids a shared scratchpad becoming an unreviewed source of truth.

Here is a framework-neutral TypeScript shape for the orchestration layer:

interface AgentTask<Input> {
  readonly id: string;
  readonly input: Input;
  readonly maxAttempts: number;
  readonly timeoutMs: number;
}

interface AgentResult<Output> {
  readonly taskId: string;
  readonly output?: Output;
  readonly error?: string;
  readonly attempts: number;
}

interface Worker<Input, Output> {
  run(input: Input, signal: AbortSignal): Promise<Output>;
}

async function runTask<Input, Output>(
  task: AgentTask<Input>,
  worker: Worker<Input, Output>,
): Promise<AgentResult<Output>> {
  for (let attempt = 1; attempt <= task.maxAttempts; attempt += 1) {
    const controller = new AbortController();
    const timeout = setTimeout(() => controller.abort(), task.timeoutMs);

    try {
      const output = await worker.run(task.input, controller.signal);
      return { taskId: task.id, output, attempts: attempt };
    } catch (error) {
      if (attempt === task.maxAttempts) {
        return {
          taskId: task.id,
          error: error instanceof Error ? error.message : "Unknown worker failure",
          attempts: attempt,
        };
      }
    } finally {
      clearTimeout(timeout);
    }
  }

  return { taskId: task.id, error: "Attempt budget exhausted", attempts: 0 };
}

The important features are not framework-specific:

  • every task has an identity;
  • retries and timeouts are bounded;
  • cancellation reaches the worker;
  • failure is data the coordinator can reason about; and
  • the result retains enough provenance to debug later.

Bound concurrency instead of starting everything

Promise.all is appropriate for a small, known set of independent tasks. It is dangerous when the coordinator can create an unbounded number of workers.

The bounded-parallelism guide provides a tested worker pool plus a method for finding the concurrency point where rate limits and tail latency begin to erase the benefit.

Use a queue or semaphore and set limits at several levels:

  • concurrent workers per user request;
  • total model calls per workflow;
  • tool calls per worker;
  • tokens or cost per workflow;
  • runtime per task; and
  • retries per failure class.

The stop condition belongs in code, not only in a prompt. A model can recommend stopping; the orchestrator must enforce it.

Context is a budget, not a shared drive

Passing the full conversation and every prior result to every worker feels convenient. It also increases cost, dilutes instructions, and lets irrelevant or hostile content travel farther than necessary.

Build each worker’s context from four explicit parts:

  1. the global user goal;
  2. the worker’s narrow assignment;
  3. the minimum trusted background required; and
  4. references to artifacts it is allowed to read.

Do not copy credentials, approval tokens, or raw secrets into model context. Treat external pages, documents, emails, and tool results as untrusted data. The OWASP AI Agent Security Cheat Sheet recommends least-privilege tools, structured validation, human approval for high-impact actions, and adversarial testing before production.

MCP makes a similar separation useful at the tool boundary: servers can expose model-controlled tools, application-controlled resources, and user-controlled prompts. The MCP server specification is worth reading even if your first implementation uses ordinary functions.

For a working implementation, build the TypeScript MCP server and its companion MCP client.

Failure modes that look like intelligence

Multi-agent demos often appear impressive because activity is visible. Production systems need to distinguish useful work from motion.

Recursive delegation

A worker decides the task is hard and creates more workers, which create more workers. Cost rises while ownership becomes unclear.

Keep delegation depth at one until metrics demonstrate a need for deeper planning. Enforce the depth in code.

Consensus without evidence

Three agents repeat the same plausible mistake, and the coordinator treats agreement as verification.

Independence of model calls is not independence of evidence. Require citations, tests, or separate data sources for claims that matter.

Shared-memory poisoning

One worker writes a malicious or incorrect instruction into shared memory. Later workers treat it as trusted context.

Separate observations from instructions. Record the author, source, timestamp, and trust level of persistent memories. Make sensitive memory append-only or review-gated, and design a rollback path.

The Postgres and pgvector memory guide turns those requirements into a tenant-safe schema, hybrid retrieval query, and forgetting workflow.

Non-idempotent retries

A timed-out worker actually completed a payment, message, or deployment. Retrying performs the action twice.

Use idempotency keys for side-effecting tools. Record intent before execution and reconcile ambiguous outcomes before retrying.

See Durable AI Agents for the state machine, approval binding, and crash-recovery pattern.

The polished synthesis

The final agent turns incomplete results into confident prose, hiding which branches failed.

Make missing work visible. A synthesis should carry coverage, uncertainty, and failed-task information forward—not smooth it away.

Evaluate the architecture, not the personalities

Compare the swarm against the single-agent baseline on the same task set. Do not evaluate only the final prose.

Track:

  • end-to-end task success;
  • median and tail latency;
  • total model and tool cost;
  • duplicated work across agents;
  • failed or abandoned branches;
  • unsupported claims in the synthesis;
  • human intervention rate; and
  • recovery after injected tool, network, and model failures.

A swarm earns its complexity when it materially improves an outcome you care about. For example, research coverage might rise enough to justify higher token cost, or latency might fall because three slow but independent checks now run concurrently.

If success stays flat while cost triples, the architecture is telling you something.

Put the comparison into a repeatable agent eval release gate, then use OpenTelemetry agent traces to explain which branch caused a regression.

A production readiness checklist

Before a multi-agent workflow can take consequential actions, verify that you can answer yes to these questions:

  • Every worker has a narrow role expressed as an input and output contract.
  • The orchestrator enforces concurrency, retry, time, tool-call, and cost limits.
  • Side-effecting tools use least privilege and idempotency controls.
  • Untrusted content is labeled and cannot silently become instructions.
  • Persistent memory records provenance and can be corrected or rolled back.
  • The final result exposes missing branches and uncertainty.
  • Traces connect the user request, coordinator decisions, worker calls, and tool actions.
  • A repeatable evaluation suite compares the design with a simpler baseline.
  • High-impact actions pause for explicit human approval.
  • Browser workers isolate credentials, origins, downloads, and untrusted page content; the Playwright security guide provides the boundary.
  • An operator can cancel the workflow and inspect what already happened.

Choose the smallest architecture that passes the tests

Most teams should evolve through these shapes in order:

  1. a deterministic workflow with ordinary code;
  2. one model call with structured output;
  3. one tool-using agent with a bounded loop;
  4. one coordinator with a few stateless parallel workers; and only then
  5. independently deployed agents communicating through a protocol such as A2A.

Each step introduces a new reason the previous shape is insufficient. That reason should appear in your measurements, not just in the architecture diagram.

The best agent swarm is not the one with the most specialists. It is the one where parallel work is genuinely independent, every boundary has a contract, and the system can prove that the additional complexity helped.

Continue with the implementation guides