Which thread gets which tool
send_to_agent is not merely refused for a member — it is never constructed, so a member cannot delegate, cannot be talked into delegating, and does not pay the tokens its schema would cost on every turn. That is how the one-level depth bound is enforced at runtime; the save-time check is the other half.
The delegation tools
tool
Hand one teammate one brief. It returns immediately — with the new thread’s id and
status: "running" — so a coordinator can start several and then wait once, rather than serialising them. The member’s answer arrives later, when the coordinator wakes.tool
Park until the delegations you name are done. The coordinator’s turn ends here and resumes with the results. A session yielding here reports the
awaiting_delegation stop reason and nothing else — awaiting_input would claim a person can unblock it and end_turn would claim the task is finished, and a caller acts on both.With nothing outstanding it is an immediate no-op — { parked: false, outstanding: 0 } — rather than a park, because parking a coordinator that has delegated nothing is a session that never wakes.The park is the turn’s, not the call’s. send_to_agent returns at once, so a coordinator can start four and wait once; the whole fan-out is dispatched when the turn ends, and this is what ends it. Calling it in a turn that delegated reports awaiting_delegation. Calling it in a turn that delegated nothing — you were resumed by one teammate and another is still running — parks the session idle instead, and the wake gate resumes you on the last one. Either way the turn stops here: it does not run on and it does not poll.tool
Who is on the team, and how much of the concurrency budget is spent. Each teammate comes back with its
name, id, pinned version, description (truncated to 160 characters), harness, and typed — whether that harness can honour an output_schema at all. Alongside them: concurrency: { running, limit }.typed is derived for the model rather than left for it to infer from harness, because the model does not carry the harness catalogue and this is the one fact that decides whether a send_to_agent call may carry output_schema.Nothing throws — a refusal is a tool result
Every way a delegation can fail to happen comes back as a tool result the model can read and act on, never as an exception that would end the turn.Delegation is about context isolation
The point of delegation is not parallelism first and foremost — it is context isolation and cost. When the coordinator callssend_to_agent, the member’s session starts fresh: its opening context is only the brief, not the coordinator’s (possibly enormous) transcript. That has two consequences:
- Focus. The member reasons over a small, relevant context instead of wading through unrelated history.
- Cost. Every model call in that session carries far fewer tokens, so the same work is materially cheaper than expanding the coordinator’s own context. See Context & budgets.
Isolated sessions, and what carries between them
Every member runs in its own session with its own conversation history. Two sessions never share conversation context: a member cannot see the coordinator’s transcript or any sibling’s, only thebrief it was handed and its own turns.
That isolation is the point, but it means the brief is the whole hand-off. There is no argument that continues an earlier member session — a delegation is one-shot. If a member needs to know what another member already did, that has to reach it some other way, and the way is the board: a card’s notes are readable by every thread on the team, which a transcript is not.
A member’s board write also wakes a parked coordinator, even before that member’s session finishes. So a member that discovers something the coordinator should act on now does not have to finish first — it comments on a card, and the coordinator gets a turn. That is the clearest case of the two mechanisms composing.
Typed results
By default a member returns free-form text. Pass anoutput_schema on send_to_agent and the hand-off becomes a typed contract instead: the member’s session must go idle producing a structured_output object that validates against the schema.
Not every harness can do this. list_agents reports typed per member, and a call carrying output_schema for a member that cannot is refused up front as no_structured_output — named, rather than quietly served as prose the coordinator’s merge code then has to parse. The refusal is deliberately at call time and not at save time: whether any delegation will carry a schema is unknowable when the roster is written, and banning a text-only teammate outright would also ban the prose work it serves well.
Fan-out: several members at once
The coordinator may have several members running at the same time — each in its own session with its own isolated history — and then park once onwait_for_agents. Give each the same output_schema and merging the batch is just collecting typed objects.
CLI
thread.created when a member session is spawned (with its agent_id and member name), and thread.idle as each result folds back. See Context & budgets.
Each member is billed independently and quoted against the org balance before it runs.
Bounds
Delegation is deliberately shallow and bounded to keep teams reproducible and cost-safe.Next: the team board
The other mechanism — durable, broadcast, and the one that outlives the run.