02.02 · Multi-Agent Systems — Deep Dive

Level: Advanced
Pre-reading: 02 · Agentic AI Patterns · 02.01 · ReAct & Planning Loops


Why Multiple Agents?

A single general-purpose agent has limitations:

  • Context window pressure — a large task fills the window before completion
  • Competing concerns — debugging and code generation require different reasoning styles
  • Reliability — outputs from one agent can be independently verified by another
  • Specialisation — smaller agents with focused system prompts outperform a jack-of-all-trades agent

Multi-agent architectures solve this by distributing work across specialised, cooperating agents.


Multi-Agent Topologies

Topology Description Use Case
Supervisor / Worker One orchestrator delegates to specialist workers JIRA ticket triage → dev agent + test agent
Chain Output of agent A feeds into agent B Ticket reader → code generator → reviewer
Parallel Multiple agents run concurrently Code change + test generation at the same time
Debate / Critic Two agents propose and critique each other High-stakes code review, RCA validation
Hierarchical Multi-level supervision (supervisor of supervisors) Enterprise-scale pipelines

Supervisor Architecture — JIRA→PR

graph TD
    A[Supervisor Agent] --> B[Ticket Reader Agent]
    A --> C[Code Search Agent]
    A --> D[Code Generator Agent]
    A --> E[Test Writer Agent]
    A --> F[PR Creator Agent]
    B --> A
    C --> A
    D --> A
    E --> A
    F --> A

Each agent:

  • Has its own system prompt scoped to its role
  • Has access to only the tools it needs (principle of least privilege)
  • Returns a structured result the supervisor can act on

The supervisor maintains shared state that each agent can read from and write to.


Agent Communication

Agents communicate through a shared state object, not direct calls to each other.

graph LR
    A[Shared State] --> B[Ticket Reader reads JIRA data]
    B --> A
    A --> C[Code Agent reads ticket + writes diff]
    C --> A
    A --> D[Test Agent reads diff + writes tests]
    D --> A
    A --> E[PR Agent reads all + creates PR]

The shared state is the single source of truth. This prevents agents from getting confused by chatty agent-to-agent conversation and makes the whole pipeline inspectable.


Handoff Patterns

Pattern How It Works When to Use
Result passing Agent A's output is in state; Agent B reads it Sequential pipelines
Explicit handoff Agent A calls transfer_to_agent_b(context) Dynamic routing
Interrupt and resume Agent pauses, human approves, agent continues Human-in-the-loop gates
Broadcast Supervisor sends same context to all workers in parallel Parallel independent tasks

Human-in-the-Loop Gates

Never auto-merge to main

Dev automation agents should always stop before pushing to a protected branch. The human reviewer step is non-negotiable. Design your agent pipeline to pause and wait at the PR creation step.

graph TD
    A[Agent: Code changed] --> B{Irreversible action?}
    B -->|Create PR| C[PAUSE: Notify developer]
    C --> D{Human approves?}
    D -->|Yes| E[Push to remote, open PR]
    D -->|No with feedback| F[Agent revises and re-presents]
    B -->|Read file| G[Continue automatically]

Avoiding Common Multi-Agent Failures

Failure Mode Cause Mitigation
Infinite delegation Supervisor keeps delegating instead of acting Max delegation depth limit
State corruption Two agents write conflicting state Immutable state with snapshots, one writer at a time
Lost context Worker agent doesn't have enough context to act Pass full relevant state slice, not just task ID
Prompt injection via agent output Worker agent output is injected into another's prompt Sanitize all inter-agent data before use as context
Silent failure Worker returns empty or malformed result Validate every agent output before advancing state

How do you decide when to use multi-agent vs. a single agent with more tools?

A single agent is simpler to debug and deploy. Use multi-agent when: (1) the task exceeds a single context window, (2) you need independent verification of outputs, or (3) tasks can run in parallel and the latency saving matters. For most JIRA ticket sizes, a well-designed single agent suffices.

How do agents share context without exceeding the context window?

Use a shared state store (not in-context messages). Pass each agent only the slice of state relevant to its task — not the full history. Summarise completed steps into a compact representation before passing to subsequent agents.