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

# Management Band

> The 21 MCP tools an organization key sees — provision, configure, and supervise a fleet of agents

Connect to the Reinx MCP server with an **organization key** (`reinx_org_live_…`) and you get
the **management band** instead of the [agent spend band](/mcp-tools/overview): tools for
provisioning and configuring agents, projects, and teams.

This is the "give one agent the orchestrator role" surface. An orchestrator can create a
worker agent, set its budget, pause it, and read its activity — but can never spend its money.

## Configuration

```json theme={null}
{
  "mcpServers": {
    "reinx": {
      "type": "http",
      "url": "https://mcp.reinx.ai/mcp",
      "headers": {
        "Authorization": "Bearer reinx_org_live_your_key_here"
      }
    }
  }
}
```

Same URL as the agent band — the credential prefix selects the band.

<Warning>
  **The bands are disjoint.** An organization key cannot see or call `request_wallet_payment` or any
  other spend tool. If you need one identity that both manages *and* spends, you need two
  credentials — that separation is the point.
</Warning>

## Every call needs a `purpose`

All 21 tools — including `search_docs` and `get_docs_page` — require a `purpose` string of
**3–500 characters** explaining why the orchestrator is acting. Omitting it fails schema
validation, so a client built without it fails on every call.

It is recorded in the organization's **append-only** audit ledger alongside the call outcome —
write something an operator would find useful, and **never put personal data in it**.

Note the ledger is append-only but not indefinitely *readable*: audit queries are clamped to the
organization's retention window (Free 7 days, Pro 30, Enterprise full history), so do not treat
this trail as a permanently queryable record of your own activity.

## What gates each call

The **19 resource-management tools** must pass three checks, independently:

1. **Scope** — does the key carry the required scope? Missing → `403 INSUFFICIENT_SCOPE`
   (the response names the `required_scope`).
2. **Binding rung** — may a key bound at this level call this route at all? No →
   `403 BINDING_NOT_ALLOWED`.
3. **Target scope** — the rung is fine, but is the object inside the key's container? No →
   `403 OUT_OF_SCOPE`, or `404` where the route hides the object's existence entirely.

The last two are easy to conflate and need different fixes: `BINDING_NOT_ALLOWED` means the
*route* is above your rung, `OUT_OF_SCOPE` means the *object* is outside your container.

<Warning>
  **Gate 3 fires only on per-target operations** — `get_*`, `set_*`, `pause_agent`, `archive_agent`,
  anything naming one object. The **list reads** (`list_agents`, `list_transactions`,
  `list_audit_events`) behave differently: an out-of-binding `projectId` / `teamId` filter is
  **intersected with the binding**, so it returns a **successful empty result**, not `403
      OUT_OF_SCOPE` or `404`. A bound key can never widen its view by passing a foreign filter — but it
  also never gets an *error* for trying, so do not wait for one. An empty list from a filtered read
  may simply mean the filter fell outside your binding.
</Warning>

<Note>
  **`search_docs` and `get_docs_page` are exempt from all three.** They need a valid org key and a
  `purpose`, but carry no scope requirement and no binding check — they only fetch public
  documentation, so there is no tenant resource to gate. A read-only key can call them.
</Note>

See [Authentication](/api-reference/authentication) for the scope vocabulary and the binding
matrix, and [limits and boundaries](/org-keys/deny-list) for what no key can ever do.

## Tools

### Reads (8)

| Tool                         | Scope               | Returns                                                                                                                                                                          |
| ---------------------------- | ------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `list_agents`                | `agents:read`       | Agents in the key's container. Narrowable by `projectId` / `teamId`                                                                                                              |
| `list_transactions`          | `transactions:read` | Transaction feed, binding-filtered                                                                                                                                               |
| `list_audit_events`          | `audit:read`        | Audit trail, binding-filtered — **and clamped to the plan's retention window** (Free 7 days, Pro 30, Enterprise full). A start date outside it is silently clamped, not rejected |
| `get_agent_budget_policy`    | `agents:write`      | Current agent budget + approval threshold, **with the `version` token**                                                                                                          |
| `get_project_budget`         | `projects:write`    | Project spend cap, with `version`                                                                                                                                                |
| `get_team_budget`            | `teams:write`       | Team spend cap, with `version`                                                                                                                                                   |
| `get_project_approval_rules` | `projects:write`    | Project approval rules, with `version`                                                                                                                                           |
| `get_team_approval_rules`    | `teams:write`       | Team approval rules, with `version`                                                                                                                                              |

<Note>
  The last five require a **write** scope, not a read scope. They are write *preconditions* — a
  full-replacement write needs the current `version` first — so the write scope covers them. An
  `agents:write` key is self-sufficient for the agent read-modify-write loop.
</Note>

### Writes (11)

| Tool                         | Scope            | Effect                                                               |
| ---------------------------- | ---------------- | -------------------------------------------------------------------- |
| `create_agent`               | `agents:write`   | Provisions an agent + wallet + policy. **Requires `idempotencyKey`** |
| `update_agent_budget_policy` | `agents:write`   | Sets total budget and/or approval threshold                          |
| `pause_agent`                | `agents:write`   | Reversible stop. Keeps the key; policy stays attached                |
| `resume_agent`               | `agents:write`   | Reverses a manual pause                                              |
| `archive_agent`              | `agents:write`   | Terminal. **Heavily restricted for machines** — see below            |
| `create_project`             | `projects:write` | New project. **Requires `idempotencyKey`**                           |
| `create_team`                | `teams:write`    | New team. **Requires `idempotencyKey`**                              |
| `set_project_budget`         | `projects:write` | Full-replacement PUT, requires `version`                             |
| `set_team_budget`            | `teams:write`    | Full-replacement PUT, requires `version`                             |
| `set_project_approval_rules` | `projects:write` | Full-replacement PUT, requires `version`                             |
| `set_team_approval_rules`    | `teams:write`    | Full-replacement PUT, requires `version`                             |

### Docs (2)

| Tool            | Returns                         |
| --------------- | ------------------------------- |
| `search_docs`   | Search these docs               |
| `get_docs_page` | Fetch a page from docs.reinx.ai |

An escape hatch for deeper recovery and how-it-works questions. Tool descriptions remain the
primary contract — reach for these when a description isn't enough. `get_docs_page` is pinned
to docs.reinx.ai and refuses any other host with `INVALID_PATH`.

## Creating: the idempotency contract

**All three create tools — `create_agent`, `create_project`, `create_team` — require a
caller-owned `idempotencyKey`.** `create_agent` additionally provisions external resources (a
wallet, a policy) and returns a **one-time** API key, so a naive retry there could duplicate the
agent or lose the key; the key prevents both. Project and team creates are simpler but take the
same key for the same reason.

<Warning>
  `idempotencyKey` is **required** on every create — `create_agent`, `create_project`, and
  `create_team`. Each tool's input schema enforces it, so on the **MCP path** omitting it fails
  **argument validation** before the call is made (not the REST `400 IDEMPOTENCY_KEY_REQUIRED` —
  that is the direct-REST contract). Generate a stable, high-entropy value per logical resource and
  **persist it before you call** — you need it to recover.
</Warning>

**On any ambiguous failure — timeout, network error, code-less 5xx, `409 REQUEST_IN_PROGRESS`,
`409 ORG_NOT_READY`, or (agents only) `503 CREATE_RETRYABLE` — retry with the SAME key and the SAME
payload.** It dedupes or resumes and returns the committed resource, never a second one. (Project
and team creates dedupe the same way but never emit `503 CREATE_RETRYABLE` — that is the
agent-saga-only contention code.)

Retries are **not re-charged against your quota within the same UTC day** — the attempt marker
dedupes them whether or not the create completed. The one exception: resuming an **incomplete**
create **after 00:00 UTC** consumes a unit from the new day, because the marker is day-scoped.

Reusing a key with a **different** payload returns `409 IDEMPOTENCY_KEY_REUSE` — that's a bug
in your code, not a transient condition.

## Reconfiguring: the version loop

Every reconfiguring write carries a `version` token, and the loop is always the same:

1. Read the current state (`get_*`) — it includes `version`.
2. Modify it.
3. Write it back with that same `version`.

If anything else changed it in between you get a `409` — re-read and retry, never blind-write.
**The code differs by tool**, so branch on all three:

| Tool                                                    | Stale-version code     |
| ------------------------------------------------------- | ---------------------- |
| `update_agent_budget_policy`                            | `VERSION_CONFLICT`     |
| `set_project_budget`, `set_team_budget`                 | `STALE_BUDGET`         |
| `set_project_approval_rules`, `set_team_approval_rules` | `STALE_APPROVAL_RULES` |

<Warning>
  **The two write shapes differ on omitted fields. This is the easiest thing to get wrong.**

  * **`update_agent_budget_policy` is a PARTIAL patch.** A field you omit is **left
    unchanged**. To clear a spend ceiling you must send it explicitly as `null` — omitting it
    silently keeps the old limit in force.
  * **`set_project_budget` / `set_team_budget` are STRUCTURED full replacements.** `capCents`,
    the **complete** child array (`teams` for a project, `agents` for a team), and `version` are
    all **required**. You cannot omit a child to leave it alone — a missing one is rejected
    `422`. Clearing a cap is `capCents: null`, never omission.
  * **`set_project_approval_rules` / `set_team_approval_rules` replace the whole `rules`
    array.** Leaving an entry out of the array deletes that rule. There is no per-field merge.
</Warning>

Omission is therefore never a clearing strategy: on the agent patch it means "leave alone", and
on the project/team setters it is either a validation failure or a deletion. Use explicit
`null` on the agent patch and on `capCents`.

On the agent patch, `null` also means different things per field: on `perTransactionLimitCents`
and `dailySpendLimitCents`, `null` = **no limit**; on `hourlyVelocityLimit` and
`dailyVelocityLimit`, `null` = **fall back to the platform default**, which is not unlimited.

## Archiving: why your key usually cannot

Archiving is terminal, so a machine may archive **only a zombie of its own making**. Every one
of these must hold:

* The agent was created by **this key's lineage** (a rotated key still qualifies).
* Its bundled key's re-delivery window has **closed**.
* The credential **never authenticated**, and the agent has **no activity**.
* The wallet balance is **zero**.
* **No human has ever minted or revoked a key for it.** Any human key management permanently
  disqualifies the machine path — the agent is no longer a machine orphan, so it is a human's
  to archive even if everything else passes.

If **any** of these fails to hold, archiving returns a terminal `403 MACHINE_ARCHIVE_DENIED` — not
retryable, ask a human to archive from the dashboard. Two cases are **not** this terminal 403, though: while
the key window is still open or the non-delivery proof hasn't been stamped, the route returns a
**recoverable `409`** (`KEY_STILL_DELIVERABLE` / `KEY_DELIVERY_UNPROVEN`) instead — recover the key
or stamp the proof rather than escalating (next section).

<Warning>
  **The server cannot prove the key was never delivered — only that it can no longer be
  re-delivered, and was never used.** An expired re-delivery window says nothing about whether your
  *original* create response reached you; a key you received and simply never used looks identical
  to the gate. **You** hold the missing evidence. Before archiving, confirm from your own records
  that no credential was ever stored for this create. Archiving on the gate's say-alone can destroy
  an agent whose key you are actually holding.
</Warning>

Two `409`s are recoverable and mean specific things:

* **`409 KEY_STILL_DELIVERABLE`** — the new agent's key window (\~30 min) is still open. **Do not
  archive.** Replay `create_agent` with the same `idempotencyKey` to recover the key and keep
  the agent.
* **`409 KEY_DELIVERY_UNPROVEN`** — replay `create_agent` (it returns `apiKey: null` and
  `keyDelivery: "expired"`, which *attempts* to stamp the non-delivery proof), *then* re-issue
  `archive_agent`. The stamp is **best-effort** — a transient DB failure can drop it and leave the
  archive returning `KEY_DELIVERY_UNPROVEN` again, so retry replay + re-archive a few times with
  backoff (the stamp is idempotent, and each replay re-attempts it) — but a persistent recurrence
  means the stamp itself is failing (a durable fault), so escalate to a human rather than looping.
  (Same-key replays within the day are not re-charged against your create quota — the quota dedupes
  them internally; they only consume request rate-limit capacity — so the cost of a bounded retry is
  rate limit, not quota.) Only do this after
  confirming from your own records that the original create response was genuinely lost.

Also retryable: `409 BALANCE_UNVERIFIABLE` (retry later), and a `200` carrying a non-empty
`walletsFailed` array (re-issue until it comes back empty).

## Limits

* **Management writes:** 20/min per key, 40/min per organization — on top of the general
  per-organization ceiling. Reads use the general buckets only.
* **Creation quota:** agents, projects, and teams share one counter, 100/day by default,
  resetting 00:00 UTC. Exhaustion is `429 CREATE_QUOTA_EXHAUSTED` and will **not** clear by
  waiting out a rate-limit window. Same-UTC-day retries are not re-charged; resuming an
  incomplete create after 00:00 UTC charges the new day.

## Audit

Management calls that reach a handler are written to the organization's audit trail as
`mcp.tool_invoked`, attributed to the **key** (name, prefix, last 6) — never to a human user,
and never carrying the key's secret. The project/team recorded is taken from the key's binding,
not from anything the caller supplies. Denials are audited too, so a scope or binding failure is
visible to the humans who own the organization.

<Note>
  The audit write is **best-effort**: it is fire-and-forget, so a database outage can drop a row
  while the management call still succeeds. That keeps an outage from breaking your integration, but
  it means the trail is an operational log rather than a guaranteed compliance record — do not rely
  on it as your own system of record.
</Note>
