> ## 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](/docs/concepts/agents) 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](/docs/team/overview#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](/docs/concepts/sessions) 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`.

<CodeGroup>
  ```bash CLI theme={"system"}
  vetta agent create --name release-manager --model zai-org/GLM-5.2-FP8 --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 release-manager --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: "zai-org/GLM-5.2-FP8",
    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": "zai-org/GLM-5.2-FP8",
    "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
    }
  }
  ```
</CodeGroup>

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 Vetta 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](/docs/concepts/harness-capabilities#two-limits-on-the-second-road).
</Note>

<Note>
  **On the wire a roster member is an `agt_` id.** `web-researcher@3` is a CLI spelling: [`vetta team`](/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.
</Note>

## 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.
</Note>

Every referenced member is checked **when you save the roster**, not when it is first delegated to. See [Mixing harnesses](/docs/team/rosters-and-versioning#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 is never handed `send_to_agent` at all. Only **one level** of delegation is permitted (see [Delegation](/docs/team/delegation#bounds)).
</Warning>

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

```json theme={"system"}
{ "type": "advisor", "model": "zai-org/GLM-5.2-FP8" }
```

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.
</Warning>

## 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:

<ParamField path="multiagent" type="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.

  <Expandable title="multiagent">
    <ParamField path="type" type="string" required>
      Must be `"coordinator"`. The only supported team type.
    </ParamField>

    <ParamField path="agents" type="object[]" required>
      The roster: **1 to 20** entries, each discriminated by its own `type`. At most one `self` and at most one `advisor`.
    </ParamField>

    <ParamField path="board" type="boolean">
      Opt into the shared [team board](/docs/team/board). Defaults to false. Its columns are fixed, so there is nothing else to configure.
    </ParamField>
  </Expandable>
</ParamField>

### `agent` entry

<ParamField path="id" type="string" required>
  The `agt_` id of another agent in your organization to delegate to.
</ParamField>

<ParamField path="version" type="integer">
  The [version](/docs/concepts/agents#versioning) of the referenced agent to pin. **Omit** the version and Vetta 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](/docs/team/rosters-and-versioning).
</ParamField>

<Card title="Next: delegation" icon="share-nodes" href="/docs/team/delegation">
  How the coordinator invokes members, and the isolated sessions they run in.
</Card>
