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
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
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_namefrom 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
nameremains 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.
Keep exploring
A few lessons that share the same technique or lead into the next idea.
Premium players need paid access. Every Explain doc is free.
Found a mistake or something unclear? Leave feedback.