Skip to main content
Several agents, one task, and they need to pass work between them. A researcher finds something, a coder builds it, a reviewer reads it — and the person who asked can interrupt any of them mid-sentence. Two facts shape the whole design, and neither is negotiable: Each agent has its own machine. That is the point — one agent installing a dependency cannot break another’s build. It also means an agent cannot simply leave a note where a teammate will find it. An agent cannot call this API. Nothing inside a sandbox holds a token, on purpose: a credential there could create sessions and read every session in the organization. So an agent’s only way out is a tool call, which arrives at your code. Put together: your service is the switchboard. Every message between agents passes through it, which is also what lets you decide who should speak next — routing is your product, not ours.

Before you start

A token and a model, as in the quickstart.

One crew, one tree

Give each agent a session, and point the rest at the first one:
Now ?root=$ROOT means “this crew” everywhere — see Crews. You do not have to keep your own membership list, and you do not have to invent a metadata convention that will collide with someone else’s.

Give them a way to reach each other

A teammate is a function the agent can call. You answer it.
Declare it on every session in the crew. What the names mean — who "coder" is — is yours to decide; the agent only sees the description.

The switchboard

One stream carries the whole crew, and nothing else in your organization:
That is the whole handoff. The reply comes back the same way, because the teammate has the same tool.

Let the others listen without paying for it

When the person types into the room, only one agent should answer — but the others still have to know what was said, or the next handoff arrives without context. input.message cannot do this: it always starts a turn. Three agents would mean three turns per sentence, two of them producing nothing. Use input.context:
If that agent is mid-turn, the context lands after it finishes. The running turn’s context is already fixed, and inserting into it would make one turn’s behaviour depend on when a message happened to arrive. Without this the only way to keep the others current is to hold your own copy of the conversation and resend it with every handoff — which makes each prompt grow with the length of the room.

Interrupting

A person changing their mind mid-turn is not a new message at the back of the queue:
input.steer redirects the turn in flight. input.cancel stops it — and does not undo what it already did, which is worth saying to the person before they press it.

Passing work, not just words

Text is enough for “have a look at this”. For output, agents are on separate machines, so a file moves through you:
Slower than a shared disk, and the reason to prefer it is the same reason the sandboxes are separate: what crosses between agents is exactly what you moved.

What it cost

Four numbers rather than one, because a live estimate is not a bill — see What a crew cost.

What this API does not do

It does not decide who speaks next. No @ syntax, no built-in router. That is a product decision and it belongs in your switchboard, where you can log it, change it, and explain it to a user. It does not stop two agents editing the same file. They are on separate machines, so they cannot — but two agents given the same job will still do it twice. Name one owner per piece of work. It will not scale past your session ceiling. A coordinator and three workers are four sessions. Check GET /v1/sessions against limits before you fan out wide.

Next

  • Crews — the tree, and ?root= everywhere
  • Tools — what a function call can carry
  • Required actions — the loop the switchboard runs on