---
title: "Agent Teams"
description: "Teammates keep separate contexts. Follow a contract update through a mailbox, then check whether their API and UI artifacts agree."
source: https://vizlearn.app/ai/agents/agent-teams
access: premium (interactive player requires Lifetime; this doc is free)
---

# Agent Teams

Agent teams coordinate several agents that work in separate contexts toward
one goal. A shared task list records ownership and progress, while messages
carry information between teammates. Finishing a task does not automatically
update another agent's understanding: a changed interface still needs to reach
the teammate that uses it.

Think of three engineers with their own notebooks and one shared task board.
Someone checks off "build the API." That tells you the work is finished. It
doesn't tell you that the response field changed from `name` to `display_name`.
You need that detail before connecting the page.

Teams are useful when work can proceed independently and the workers need to
exchange findings. Here, API work and page layout can overlap. Connecting the
data waits for both, so adding another worker would not remove that dependency.

## How Agent Teams Work

The lead coordinates the goal, Backend owns the API, and Frontend owns the
page. Each has a private context containing its assignment and the evidence
it has received. The task board is a separate object. It records tasks,
owners, prerequisites, and statuses, so two teammates can work on independent
tasks without claiming the same one.

A mailbox is a third place information can live. Backend can send a contract
update directly to Frontend. The message enters Frontend's mailbox first;
when delivered into its context, the update becomes available for its next
decision. The sender does not have to wait for the recipient to finish using
the information.

For a concrete implementation, Claude Code documents private teammate
contexts, shared tasks, recipient mailboxes, and automatic message delivery.
The diagram here isolates those mechanisms using an authored schedule; it is
not a recording of Claude choosing tasks or generating code.
[Official Agent Teams documentation](https://code.claude.com/docs/en/agent-teams)

There are three tasks in this example:

| Task | Owner | Needs |
|---|---|---|
| t1: Build profile API | Backend | Nothing |
| t2: Build page layout | Frontend | Nothing |
| t3: Connect profile data | Frontend | t1 and t2 completed |

The first two can overlap. The third waits for both. A dependency establishes
when work is eligible; it does not insert the API contract into Frontend's
context. That is the distinction to keep track of.

## Agent Teams Step by Step

The default uses **Send update** with the API field **`display_name`**. The
existing frontend contract uses `name`. The requested page must display `Ada`.

### Give each teammate its assignment

The lead begins with the profile-page goal. Backend starts with an assignment
to build the API using `display_name`; Frontend starts with layout and binding
work, plus its existing `name` contract. These are separate contexts. Giving
Backend a new field does not silently replace the field in Frontend's context.

The lead creates the three-task plan. Backend claims t1, then Frontend claims
t2. Both tasks are now in progress. The claim gives each task one owner before
the work starts.

### Complete the API and send its contract

Backend produces `{"display_name":"Ada"}` and marks t1 completed. Frontend
is still working on the layout. At this exact point, the board says t1 is
complete, Frontend's mailbox is empty, and Frontend still knows `name`.

Backend sends Frontend a message whose payload identifies the API field as
`display_name`. The message is now in Frontend's mailbox. It is addressed to
Frontend, so it does not pass through the lead's context. Frontend's context
still contains the old field while the message waits outside it.

Frontend finishes the layout and marks t2 completed. Its next task is now
eligible because both prerequisites have finished. At the next modeled turn
boundary, automatic delivery moves the contract message into its context.
The known field changes from `name` to `display_name`, and the mailbox becomes
empty. The delivery timing is schematic; no model latency is being measured.

### Build the binding and check the result

Frontend claims t3. It builds a binding that reads `response.display_name`,
using the field now present in its own context, then marks t3 completed.
The task board shows three completed tasks. The integration result is still
unknown.

Frontend reports the actual binding key to Lead. That report enters Lead's
mailbox and then its context. Lead combines the report with the API artifact
and performs the lookup: `{"display_name":"Ada"}` read with `display_name`
returns `Ada`. The profile preview now displays that value. Before the check,
its name slot stays empty: a built binding is not yet a verified result.

The teammates are idle at the end of this example, with their contexts still
present. An idle teammate is available for more work; finishing one task is
not the same event as shutting down its session.

## Why Completed Tasks Can Still Fail Integration

Keep `display_name` selected and switch to **Status only**, or choose the
**Stale contract** scenario to jump to the check. This counterfactual removes
the Backend-to-Frontend contract message. The tasks, ownership, prerequisites,
and API response remain the same. Frontend still sends its final report to
Lead, but the binding key in that report follows Frontend's current context.

Frontend reaches the receive boundary with an empty mailbox. In this policy
it also performs no read of the API artifact, so its known field remains
`name`. It builds `response.name` and finishes its task. Lead then tries that
key against `{"display_name":"Ada"}`. The property is absent.

All three tasks are completed. The preview shows **Name unavailable** because
the selected property is missing. Completion is evidence that
the recorded unit of work finished, not evidence that two independently
produced artifacts agree.

Now keep **Status only** and select `name`. Integration passes because the
response still has the field Frontend expected. This is the control case:
success with an unchanged interface does not establish that the coordination
policy can handle a changed one.

| Handoff | API field | Frontend binding | Integration read |
|---|---|---|---|
| Send update | `display_name` | `response.display_name` | `Ada` |
| Status only | `display_name` | `response.name` | Missing field |
| Send update | `name` | `response.name` | `Ada` |
| Status only | `name` | `response.name` | `Ada` |

The useful design question is what information must cross each task boundary.
An explicit message is one answer. Reading the shared artifact, including the
contract in a task description, or having the lead relay the update can also
work. The failed run omits all of these. It demonstrates missing information,
not an inherent inability of agents to inspect shared files.

## When a Team Is Worth the Coordination

Use a team when workers can own separate pieces and need to keep exchanging
findings: for example, an API change alongside a page update, or reviewers
examining different parts of a design. A focused task that only needs to
return one result may fit a subagent. If every task waits on the previous one,
or everyone must edit the same file, one session often needs less coordination.
Separate contexts also add token cost; this short animation measures neither
cost nor speedup.
[Agent Teams use cases and tradeoffs](https://code.claude.com/docs/en/agent-teams#when-to-use-agent-teams)

Before splitting the work, identify the information each consumer will need.
For this page, a useful handoff says which field to read, gives an example
response, and names the consumer that must change. Give the combined check an
owner too. A message such as “API finished” leaves the same gap as a completed
task status when the consumer still assumes `name`.

## Edge Cases

- **Empty mailbox.** Receiving no update leaves the known field unchanged.
  The simulator does not infer `display_name` from a completed task.
- **Only one prerequisite completed.** t3 remains unavailable while t2 is
  unfinished, even when t1 is complete.
- **Two claims for one task.** The model rejects a second claim once an owner
  holds the task. This does not prevent two different tasks from writing the
  same file in a real project; file ownership needs its own coordination.
- **Message addressed elsewhere.** A message for Frontend cannot update
  Lead's context. A report to Lead cannot update Backend's context.
- **Duplicate delivery.** A previously consumed message ID is not appended
  to the recipient context again in this model.
- **Unchanged contract.** Status only passes when `name` remains correct.
  The update has no effect on the output value in this particular case.

## Common Mistakes

- **Treating the task board as shared memory.** Its statuses tell the team
  what finished. They do not contain every detail from another agent's work.
- **Treating a send as evidence of understanding.** A queued message and a
  context entry are different states. Even receipt alone does not prove that
  an arbitrary real agent will use the information correctly.
- **Sending everything through the lead.** Direct peer messages can supply
  an interface detail without copying both conversations into the coordinator.
- **Using more agents to solve a missing dependency.** A new worker still
  needs the required information. Divide independent work, then make the
  information exchanges explicit.
- **Skipping the combined check.** Separate tasks can finish with outputs
  that disagree. Check the artifacts together before calling the goal done.

## A Note on Simplification

This is a deterministic explainer, not a substitute for formal training or
the documentation of your agent runtime. Tasks, assignments, and their schedule
are authored. The browser computes claims, dependency checks, mailbox
delivery, context updates, response objects, bindings, and integration reads;
it does not run an LLM. A real agent may inspect an artifact or ask a question
instead of following this schedule. Delivery failures, retries, permission
checks, file conflicts, and shutdown handling are omitted. Presentation time
does not represent model execution time or demonstrate a speedup.
