# Agent Teams for Delivery

Course: [AI Agents](https://www.devtutorials.ai/learn/ai-agents) · Section: Multi-Agent Systems
Source: https://www.devtutorials.ai/learn/ai-agents/multi-agent/agent-teams

> How specialist agents deliver one feature together: team structures, assigning and merging work, messages and handoffs, deadlock prevention, and docs and deploy agents.

Think about a team building a treehouse.

One person is in charge. They look at the plan and assign jobs: one person cuts the wood, two people build the platform, and another paints the railings. Different people can work on different parts at the same time.

When the platform is finished, the person in charge checks it before anyone climbs on it. At the end, someone records what was built, and only then is it opened for the kids.

Now imagine two builders without anyone coordinating them. One says, "I'll start when you tell me how high the floor is." The other says, "I'll tell you when I know how long the ladder is." Each waits for the other, so nothing happens. This is called a **deadlock**.

**The main idea:** An agent team divides a large task among specialist agents. A good team has clear roles, clear handoffs, a way to combine everyone's work, and rules that prevent agents from waiting on each other forever.

## A Real-World Example

You have already met all of the specialists in Chapter 8. Now they work together to deliver the export status feature in a single workflow on the same project files:

1. **Planner:** creates 6 tasks.
2. **Design:** creates the status panel.
3. **Frontend** and **backend**, running at the same time: the component, and the contract plus endpoint.
4. **Review:** reviews the combined changes.
5. **Testing:** increases coverage to 80%.
6. **Docs:** updates the changelog.
7. **Deploy:** runs only if tests, contract checks, and accessibility checks all pass.

A **manager** agent assigns each task, collects the results, and combines the frontend and backend work.

**In simple words:** One manager, clear responsibilities, and every handoff documented.

## What You Will Learn

In this lesson, you will learn:

1. Three ways to organize an agent team: manager-worker, hierarchical, and peer teams.
2. How work is assigned, shared, and merged across agents.
3. How agents communicate through messages, shared state, and handoffs.
4. What a deadlock is and how to prevent it.
5. What documentation and DevOps agents contribute at the end of the process.

The **Team** tab in the Agent Lab runs the complete delivery pipeline. Every stage is a real Agent Lab run using the same files, so each agent builds on the work of the previous agent. The Team tab can also run two peer agents, with and without a shared contract.

## Team Structures

### Manager-Worker

In a **manager-worker** team, one manager agent assigns tasks to worker agents and collects their results. Workers communicate only with the manager, not with each other.

This structure is simple to understand and easy to debug because every message passes through a single point.

### Hierarchical

A **hierarchical** team contains managers under other managers.

For example, a frontend lead agent could split work between a component agent and a styling agent.

This structure scales well for large projects, but every extra management layer adds more messages and more delay.

### Peer Teams

In a **peer** team, agents communicate directly with one another without a manager.

This can be fast, but it is harder to follow and more difficult to coordinate. It is also the structure where deadlocks are most likely to happen.

```js runnable title="Count the message paths in each structure"
function paths(structure, workers) {
  if (structure === "manager-worker") return workers;
  if (structure === "peer") return (workers * (workers - 1)) / 2;
}

for (const n of [3, 6, 10]) {
  console.log(n + " agents: manager-worker " + paths("manager-worker", n) + " paths, peer " + paths("peer", n) + " paths");
}
```

Expected output:

```text
3 agents: manager-worker 3 paths, peer 3 paths
6 agents: manager-worker 6 paths, peer 15 paths
10 agents: manager-worker 10 paths, peer 45 paths
```

With 6 workers, peer teams create 15 possible conversations to track. A manager-worker team has only 6. That is why the delivery team in this lesson uses a manager.

## Work Distribution

### Task Assignment

**Task assignment** means giving each task to the agent best suited to complete it. The planning agent has already assigned an **owner** to every task, so the manager simply follows the plan.

```js runnable title="Assign tasks by owner"
const plan = [
  { id: "contract", owner: "backend" },
  { id: "design", owner: "design" },
  { id: "api", owner: "backend" },
  { id: "panel", owner: "frontend" },
  { id: "tests", owner: "testing" },
];

const inbox = {};
for (const t of plan) (inbox[t.owner] ??= []).push(t.id);
for (const [agent, tasks] of Object.entries(inbox)) console.log(agent.padEnd(9) + tasks.join(", "));
```

Expected output:

```text
backend  contract, api
design   design
frontend panel
testing  tests
```

### Work Sharing

**Work sharing** means running independent tasks at the same time. Once the contract is finished, the frontend and backend tasks no longer depend on each other, so they can run in parallel. As you learned in Lesson 12, tasks should run in parallel only when there is no dependency between them.

### Result Merging

**Result merging** combines the work produced by multiple agents running in parallel. Each agent changes its own files, so the manager can merge both sets of changes.

If two agents change the *same* file, a **merge conflict** occurs. In that situation, the manager must stop and resolve the conflict before continuing.

```js runnable title="Merge two agents' changes, or find a conflict"
function merge(base, a, b) {
  const clash = Object.keys(a).filter((path) => path in b);
  if (clash.length) return "CONFLICT: both changed " + clash.join(", ");
  return "merged: " + Object.keys({ ...base, ...a, ...b }).length + " files";
}

const base = { "web/format.js": "…", "api/openapi.json": "…" };
const frontend = { "web/TicketPage.js": "…" };
const backend = { "api/openapi.json": "…", "api/export.js": "…" };
console.log(merge(base, frontend, backend));
console.log(merge(base, { "api/openapi.json": "…" }, backend));
```

Expected output:

```text
merged: 4 files
CONFLICT: both changed api/openapi.json
```

Giving each agent its own folder (`web/` for frontend and `api/` for backend) makes conflicts much less likely. The folder boundaries you learned about in Lesson 1 help teams as well as individual agents.

## Agent Communication

### Message Routing

**Message routing** decides which agent receives each message. In a manager-worker team, every message either comes from the manager or goes to the manager. The Team tab shows all of these messages, such as: "manager → backend: Task contract + api".

### State Sync

**State sync** keeps all agents working from the same version of the truth. In the Agent Lab, that shared truth is the project files. Each stage starts with the files produced by the stage before it.

### Handoffs

A **handoff** passes work and its context to the next agent. A good handoff explains what was completed, where the result is located, and what the next agent needs to know.

For example: "Panel ready: `web/export-panel.html` passes a11y and token checks."

```js runnable title="A handoff message with everything the next agent needs"
function handoff(from, to, done, where, next) {
  return from + " -> " + to + ": Done: " + done + ". Where: " + where + ". Next: " + next + ".";
}

console.log(handoff("design", "frontend", "export panel, 4 states", "web/export-panel.html", "build it in TicketPage.js; a11y and tokens already pass"));
console.log(handoff("backend", "frontend", "export endpoint", "api/openapi.json", "read status and rows from GET /tickets/{id}/export"));
```

Expected output:

```text
design -> frontend: Done: export panel, 4 states. Where: web/export-panel.html. Next: build it in TicketPage.js; a11y and tokens already pass.
backend -> frontend: Done: export endpoint. Where: api/openapi.json. Next: read status and rows from GET /tickets/{id}/export.
```

Done, where, next: three short parts. The next agent gets everything it needs without having to guess.

### Deadlock Prevention

A **deadlock** is a circle of waiting: Agent A waits for Agent B, and Agent B waits for Agent A. Neither agent can continue, so the work stops.

The solution is to break the circle. Something must be provided before either agent starts waiting. In the delivery team, the planner publishes the contract first, so both the frontend and backend agents already have the information they need.

```js runnable title="Find a circle in who waits for whom"
function deadlock(waitsFor) {
  for (const a of Object.keys(waitsFor)) {
    let x = a;
    const seen = [a];
    while (waitsFor[x]) {
      x = waitsFor[x];
      if (x === a) return "deadlock: " + seen.join(" -> ") + " -> " + a;
      if (seen.includes(x)) break;
      seen.push(x);
    }
  }
  return "no deadlock";
}

console.log(deadlock({ frontend: "backend", backend: "frontend" }));
console.log(deadlock({ frontend: "planner", backend: "planner" }));
console.log(deadlock({ a: "b", b: "c", c: "a" }));
```

Expected output:

```text
deadlock: frontend -> backend -> frontend
no deadlock
deadlock: a -> b -> c -> a
```

In the **Team** tab, press **Peers, no shared contract**. The frontend waits for the contract from the backend, and the backend waits for the field list from the frontend.

The deadlock check finds the cycle at tick 1. Then press **Peers, contract first**. The planner publishes the contract at tick 0, allowing both agents to start immediately. Both finish at tick 1.

## Full-Stack Work

**Full-stack** work spans every layer: design, frontend, backend, and testing. The team approach works because each layer has a specialist agent with the correct tools, folder boundaries, and validation checks.

No single agent needs every tool, which also makes the overall system safer.

## Docs and DevOps Agents

Two small agents complete the delivery process.

**The docs agent** writes the changelog in user-focused language. It reads the feature request rather than the code so the description matches what users asked for.

**The deploy agent** is a **DevOps** agent that releases the code to a server. It acts as the final gate before deployment.

The deploy agent deploys only when the tests, contract check, and accessibility check all pass. Its report also includes an **incident summary**, which lists anything that went wrong during deployment or states "none" if there were no issues.

On the unfinished project, the tests and the contract check fail, so the deployment is blocked. A blocked deployment means the deploy agent is doing its job correctly.

Press **Run the pipeline** in the Team tab. All 8 stages succeed, and the deploy agent deploys version 1.4.0. Open **Messages** to read every handoff between agents.

**Easy Way to Remember:** **one boss, own folders, written handoffs, contract first.**

Don't let two agents change the same file at the same time. Give each agent its own folder, and make the manager stop when a merge conflict is found.

## Common Mistakes

| Mistake | Wrong idea | Correct idea | What goes wrong |
|---|---|---|---|
| Peers by default | "Agents can just talk it out." | Start with a manager. | Messages multiply and nobody knows who made a decision. |
| Waiting in a circle | "They'll sort it out." | Publish the contract first. | Frontend and backend wait forever. |
| Shared folders | "They're careful." | Give each agent its own folder. | Merge conflicts and lost work. |
| Thin handoffs | "Done." | Say what is done, where it is, and what comes next. | The next agent re-reads everything or guesses. |
| Deploy without gates | "Every stage said ok." | Re-check tests, contract, and a11y before deployment. | A broken change reaches users after the merge. |

## Exercises

Each exercise ends with a value on the last line. Press **Check** to compare it with the expected answer.

## What to Remember

- **One boss, own folders, written handoffs, contract first.**
- The **manager-worker** model is the simplest team structure to understand and manage. Peer teams create many more communication paths.
- Run independent agents in parallel, but stop immediately if a merge conflict is found.
- A **deadlock** is a circle of waiting. Prevent it by publishing shared information, such as the contract, before agents depend on it.
- The **docs agent** writes for users. The **deploy agent** is the final gate before release.

Next: **Security Guardrails**, how to keep agents safe when the input itself is an attack.
