agent_team puts several agents on one session, defined on the request that
starts it. members[0] answers; the others are reachable through
handoffs entries that name them. Every agent in the cast is
an agent — a handoff between them is still agent → agent, never the
transfer that reaches a person.
Use it when the cast is generated per request and would never be reused. If the
same three agents answer every call, they belong in the workspace with
handoffs pointing at each other by agent_id, and the request names one
agent_id.
Where it is accepted
Every member must be on a channel that endpoint runs; a member that resolves to
the wrong one is a 400 naming the member and the endpoint to use instead.
An inbound phone call has no request of ours, so it cannot carry a team. A
number answers with the one agent assigned to it — which can still have
handoffs naming stored agents by agent_id. See inbound
calls.
The shape
string
required
This member’s name for this call, winning over the stored agent’s own.
Handoff edges reference it and the transcript records it. Names must be unique
across the call.
uuid
An agent in this workspace. Mutually exclusive with
agent. One of the two is
required.AgentConfig
A whole agent definition, run for this call and stored nowhere.
integer | "draft"
Which version of
agent_id to run. Omit for the published one. Needs
agent_id.AgentOverride
Changes layered on the base. Absent keys keep the base value, an explicit
null clears a field, objects deep-merge and lists replace wholesale.agent_team is mutually exclusive with agent_id, agent, agent_version
and agent_override at the top level of the request: one agent, or a team of
them. Sending both is refused before anything runs.
How members reach each other
Every member is in the call’s roster under itsname, the entry member
included — which is what lets a specialist hand the call back to whoever
answered.
A handoff entry resolves in one of two ways:
- With
agent_id— a stored agent, at its latest published version. The team is not consulted, and the target does not have to be on it. - Without
agent_id— the entry’snameis looked up in this call’s roster. A name nothing on the team defines is refused when the call is created.
agent_id edges
and this one call needs different ones, is agent_override.handoffs — a list,
so it replaces the stored edges wholesale for this call.
Members nothing hands off to are a warning, not a refusal — a member
reachable only after two hops is legitimate, and a typo is not:
What is checked, and when
Everything is resolved and validated before the call starts, by the same rules that guard publishing. A bad team is a 400 at create, naming the problem, rather than a call that connects and then fails. In particular:- Each member’s merged config must be a valid, publishable agent — including the cross-agent rules on handoffs, which run against the roster, so an edge whose target is on the wrong channel or the wrong pipeline is caught here.
- A member naming a stored agent with no published version is refused:
publish 'Renewals' before calling it. - Two members with the same name is a 422.
- 1 to 10 members. Above ten, the shape being asked for is a workflow, not a team.
- The resolved plan must be under 256 KB. A long inline definition multiplied by ten members is what this bounds; the error says how big the plan came out.
handoffs target named by
agent_id carries no override, so it enters the target’s latest published
version, as it does on a single-agent call. On a batch
the plan is resolved once and every call it places runs that same cast.
userdata and vars across a team
One bag of each, per session, reaching every member — the entry agent, every
other member, and a handoff target that was never on the team.
userdatais session state every agent shares. A tool on one member writes it and the next member reads it. It is merged onto the caller’s contact record like any other session’s.varsare values for the variables the agents declare. They override each agent’s own declared defaults, so two members can declare the same name with different defaults and each falls back to its own. Nothing inside the session can write them.
required: true on a variable is checked once, at the door, against the
merged cast: if any member requires a variable the request supplied no value and
no default for, the session is refused before anything is compiled. Nothing is
enforced after that, so a handoff target that needs a value nobody supplied
reads it as empty rather than ending the call.
A worked example
A web call whose front desk routes to a renewals agent, with the front desk’s edges supplied for this call only.server_url and participant_token are what a browser joins with — see web
calls. The response also carries warnings, which is
where the unreachable-member warning above turns up. The same agent_team
object goes on POST /v1/calls/outbound, POST /v1/conversations and
POST /v1/calls/batches unchanged.
Next
Handoffs
The edges members reach each other through.
Per-call configuration
agent_version, agent_override and inline agent on a single-agent call.Patterns
When a cast genuinely differs per request, and when it does not.