> ## Documentation Index
> Fetch the complete documentation index at: https://vetta.sh/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Coordinator

> Declare a team by adding a multiagent coordinator object and a roster of members to an agent's configuration.

A team is an [agent](https://vetta.sh/docs/concepts/agents.md) whose configuration includes a `multiagent` object with `type: "coordinator"` and an `agents` roster. The coordinator owns the top-level task and coordinates its roster the [two ways a team can](https://vetta.sh/docs/team/overview.md#two-ways-a-team-coordinates). It is an ordinary agent in every other respect: it has a model, a budget, a system prompt, and it runs inside a [session](https://vetta.sh/docs/concepts/sessions.md) you drive directly.

## Making one

The roster lives on the coordinator's own config, so a team is made in two steps — create an agent, then give it a roster. There are no roster flags on `vetta agent create`.

```bash CLI theme={"system"}
vetta agent create --name release-manager --model z-ai/glm-5.3-flash --harness pi --budget-usd 100 --max-task-usd 10 --budget-period month --window immediate --system "You coordinate a software release. Delegate bounded briefs."

vetta team set agt_01j8rm4xp7k2qv6zn9c3h5wfdb --member changelog-writer@4 --member release-notes-qa@2 --member self --board
```

```typescript TypeScript theme={"system"}
const coordinator = await vetta.agents.create({
  name: "release-manager",
  model: "z-ai/glm-5.3-flash",
  harness: "pi",
  budget: { capUsd: 100, maxTaskUsd: 10, period: "month" },
  window: "immediate",
  system: "You coordinate a software release. Delegate bounded briefs.",
});

await vetta.agents.update(coordinator.id, {
  expected_version: coordinator.current_version,
  multiagent: {
    type: "coordinator",
    agents: [
      { type: "agent", id: "agt_9f2c…", version: 4 },
      { type: "agent", id: "agt_4a71…", version: 2 },
      { type: "self" },
    ],
    board: true,
  },
});
```

```json Agent config theme={"system"}
{
  "name": "release-manager",
  "model": "z-ai/glm-5.3-flash",
  "harness": "pi",
  "budget": { "cap_usd": 100, "max_task_usd": 10, "period": "month" },
  "window": "immediate",
  "system": "You coordinate a software release. Delegate bounded briefs.",
  "multiagent": {
    "type": "coordinator",
    "agents": [
      { "type": "agent", "id": "agt_9f2c…", "version": 4 },
      { "type": "agent", "id": "agt_4a71…", "version": 2 },
      { "type": "self" }
    ],
    "board": true
  }
}
```

The response echoes your configuration and, like any agent, adds `id`, `version`, `created_at`, and `updated_at`. Adding, removing, or repinning members produces a **new coordinator version** — the roster is part of the agent's config.

> [!NOTE]
>
> **Any published harness can be the coordinator's.** `send_to_agent` and `board_write` reach the
> coordinator's model either in the toolset Naive Managed Agents assembles for the turn, or — on `claude_code` and
> `hermes`, which run a CLI inside a micro-VM on that CLI's own toolset — over a session-scoped tool
> endpoint the machine is given. One caveat on those two: `wait_for_agents` does not pause the turn,
> so the coordinator parks once the turn goes idle instead of mid-call. It costs a few extra model
> calls, not a wrong answer. See
> [Harness capabilities](https://vetta.sh/docs/concepts/harness-capabilities.md#two-limits-on-the-second-road).

> [!NOTE]
>
> **On the wire a roster member is an `agt_` id.** `web-researcher@3` is a CLI spelling: [`vetta team`](https://vetta.sh/docs/cli/team) resolves the name against your org's agents and writes the id. The API rejects anything that is not an `agt_` id.

## The coordinator's half of the board

With `board: true` the coordinator owns the team's one [company board](https://vetta.sh/docs/team/board.md), and every agent on its current roster is seated on it. The coordinator's job on that board is to **put the work on cards and hand them out** — not to do the work, and not to work a teammate's card for them.

* **A card is the hand-over; a message is a nudge.** A card carries a title, what "done" looks like in the notes, and `blocked_by` for anything that must finish first. It is durable, it is readable by every teammate and by you, and it is what starts a teammate: `board_write({ op: "assign", card_id, assignee: "writer" })` on a `todo` card with no open blocker, and a session of `writer` is started on it as soon as the write lands. A `send_to_agent` message is private, is not on the record, and is the right tool for a question — not for the work.
* **Never move a teammate's card.** Claiming (`doing`) is the assignee's move, and closing (`done`, with a note) is the assignee's too. The coordinator reads the card, comments on it, reassigns it or unblocks it — and moves only its own. The board refuses the rest anyway (`already_claimed`), but a coordinator that respects the rule leaves a board a person can read: whoever holds a card is whoever moved it.
* **The board tells the coordinator what changed.** When a card reaches `done` or `blocked`, the coordinator gets one session per board with the [digest](https://vetta.sh/docs/team/board.md#the-owner-is-told-what-changed) of the cards that changed. That is its cue to read them and unblock or reassign what is stuck. A finished card needs nothing more, and new work starts only when a card's note or the operator asks for it. A woken teammate that stopped without finishing does not vanish: its card is parked as `blocked` with a system comment for the coordinator to act on.

### Crew, not member

A card starts a **top-level session of the rostered agent** — a member of the crew, on that agent's own budget and its own concurrency, answerable to the board. A `send_to_agent({ wait: true })` starts a **member thread** of the coordinator's session — on the coordinator's budget, parking the coordinator until it answers. They are different tools for different work:

| | Card-woken **crew** session | Delegated **member** thread |
| - | - | - |
| Started by | The board's clock, on `assign` | The coordinator's `send_to_agent` |
| Runs as | The agent's own top-level session | A thread of the coordinator's session |
| Budget | The assignee's own | The coordinator's |
| Coordinator's state | Untouched — it does not park | Parks on `awaiting_delegation` |
| The brief | The card's notes and comments | The `message` |
| The result | On the card — `done` with a note, or `blocked` with a comment | Folded into the coordinator's turn |
| Reach for it when | The work has an owner and a state, and you do not need the answer inside this turn | You need an answer to fold back into what you are doing now |

Both are seated on the board — a member thread reads and comments on the cards like anyone else on the roster — and neither delegates: a rostered agent carries no roster of its own, so `wait: true` is the coordinator's alone. See [Delegation](https://vetta.sh/docs/team/delegation.md#a-card-or-a-message) for the other side of this.

## Roster entry types

Each entry in `agents` is discriminated by a `type` field. A bare `"agt_…"` string is also accepted and normalises to the `agent` form at parse, so exactly one shape reaches storage.

### `agent` — reference another agent

```json theme={"system"}
{ "type": "agent", "id": "agt_9f2c…", "version": 3 }
```

> [!NOTE]
>
> Referenced members are fully independent agents with their own model, harness, tools, skills, and system prompt. Session-level configuration overrides applied to the coordinator's session do **not** reach id-referenced members — they run exactly as their pinned version defines.

Every referenced member is checked **when you save the roster**, not when it is first delegated to. See [Mixing harnesses](https://vetta.sh/docs/team/rosters-and-versioning.md#mixing-harnesses) for what is checked and why a save can be refused.

### `self` — spawn copies of the coordinator

```json theme={"system"}
{ "type": "self" }
```

The coordinator can delegate to **copies of itself**. Each copy is a fresh session running the coordinator's own configuration — useful for recursively decomposing homogeneous work. Unlike id-referenced members, session-level configuration overrides applied at the coordinator's session **do** apply to `self` copies (and to the coordinator itself), because they share the coordinator's configuration.

> [!WARNING]
>
> `self` does not create a nested team. A `self` copy runs the coordinator's *base* behavior on its own brief; it is a member, and a member's `send_to_agent` refuses `wait: true`. Only **one level** of delegation is permitted (see [Delegation](https://vetta.sh/docs/team/delegation.md#bounds)).

### `advisor` — parses, but is not served

```json theme={"system"}
{ "type": "advisor", "model": "z-ai/glm-5.3-flash" }
```

An advisor is intended as a consult-only voice for the coordinator's own session — a bare model with no agent behind it, so it names a `model` instead of an `id`.

> [!WARNING]
>
> **It is not served today.** A roster containing an `advisor` entry is **refused at save**, with `advisor roster entries are not yet served`. The shape is on the wire so that a roster written for it still parses, and the CLI still accepts the `advisor:<model>` spelling, but nothing runs it. Do not design a team around it.

## Roster entry types at a glance

| Entry | Shape | Served today? | Inherits session overrides? |
| - | - | - | - |
| Referenced agent | `{ "type": "agent", "id", "version"? }` | Yes | No |
| Self copy | `{ "type": "self" }` | Yes | Yes |
| Advisor | `{ "type": "advisor", "model" }` | **No — refused at save** | n/a |

## Configuration reference

### The `multiagent` field

It accepts an object, a boolean, or `null`, and all three arms mean something:

**multiagent** `object | boolean | null`

An **object** declares the team. `false` and `null` mean the agent is not a coordinator — `null` is how an existing roster is *cleared* on a `PATCH`, which `false` cannot say because `false` is also the create-time default. `true` is read as a coordinator with an empty roster and no board, which has nobody to delegate to; it is a degenerate case, not a shortcut.

**multiagent**

**type** `string` *required*

Must be `"coordinator"`. The only supported team type.

**agents** `object[]` *required*

The roster: **1 to 20** entries, each discriminated by its own `type`. At most one `self` and at most one `advisor`.

**board** `boolean`

Own the shared [company board](https://vetta.sh/docs/team/board.md). Defaults to false. When true, this agent's board exists and every agent on the current roster is seated on it — given `board_read` and `board_write`, and addressable as an `assignee` by name. Its columns are fixed, so there is nothing else to configure.

### `agent` entry

**id** `string` *required*

The `agt_` id of another agent in your organization to delegate to.

**version** `integer`

The [version](https://vetta.sh/docs/concepts/agents.md#versioning) of the referenced agent to pin. **Omit** the version and Managed Agents pins the member's *current* version at the moment the coordinator is saved — the stored roster always carries an explicit pin, and it does not drift. See [Rosters & versioning](https://vetta.sh/docs/team/rosters-and-versioning.md).

> [card] [Next: delegation](https://vetta.sh/docs/team/delegation.md)
>
> How the coordinator invokes members, and the isolated sessions they run in.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.