---
name: vinkius-agent-fleet
description: 'Teaches the agent-fleet pattern on @vinkius/connect: every autonomous agent is its own user with a stable external_id, scoped to exactly the connectors its role needs, with per-agent metering, timeouts, handoff that preserves scope, and one-call revocation through a governor agent. Explains naming, the AGENTS registry, headless connector choice, loop bounds and emergency cutoff. Use when building multi-agent systems, orchestration, or scoped tool access per agent with @vinkius/connect. Prerequisite: vinkius-connect-core.'
license: Apache-2.0
metadata:
  author: Vinkius
  package: "@vinkius/connect"
  pattern: "user = autonomous agent"
  docs: "https://vinkius.com/learn/connect-sdk/build-agent-fleet"
---

# A fleet of AI agents, each its own user

Applies vinkius-connect-core. The insight: an agent that shares your credentials is a liability; an agent that owns its own isolated identity is a governed worker. Here each agent becomes a user, which means least privilege stops being a policy document and becomes a property of the platform.

## Identity rules

- Derive the id from the agent's role, plus its instance if you scale workers (`agent-triage`, `agent-ops-3`), and always prefix it so an agent id can never collide with a human or department id.
- Encode least privilege in a declarative registry: one entry per agent role listing exactly the connector slugs it may connect. The registry, not code paths, is the source of truth, so scope changes are config diffs.
- Tag actors with `user.ensure({ kind: 'agent', role })` so governance and spend views can filter the fleet by actor type.

## How the pieces fit

- Provisioning is headless by design: agents have no browser and no human to click "Authorize", so prefer connectors that accept a static token or key via `credentials.set()`. OAuth connectors need one human consent at least once; provision those from a console, then the agent runtime only reads `status()`.
- At run time the agent's loop is identical to a human's turn: load its capabilities (the fan-out returns only this agent's ready connectors, so an agent literally cannot see a tool another agent holds), convert to your model's shape, execute with per-call controls, feed results back, bound the loop with a step budget.
- Handoffs preserve scope: when triage escalates to ops, the ops agent runs under its own id with its own connectors. Pass the task, never your capabilities; a hand-off that shares an identity destroys the audit trail and the blast radius at once.
- Model a governor agent: read-only inspection tools plus the authority to `disconnect()` a worker. Emergency revocation is then one call per agent, immediate and final, with zero impact on the rest of the swarm. Because each connection's `vk_live_*` token is its own meter and kill switch, spend is attributable per agent and termination is surgical.
- Between agents, pass `structuredContent` (the connector's typed object) rather than serialized text: more precise, more token-efficient, unambiguous.

## Rules that keep this safe

- Cap every loop with a max-steps budget and every call with `timeoutMs`; on step exhaustion, return a controlled "stopped" string rather than throwing.
- Give every mutating action a per-task `idempotencyKey` (derive from the task id plus the specific operation), so a retried loop cannot double-execute.
- `isError: true` results go back to the model as data; thrown errors (auth, quota) are the agent's own failure path, not the user's.
- One Vinkius client for the whole fleet: isolation comes from ids, not from instances.

## Verify it works before shipping

Provision two agents with disjoint registries; assert each capabilities() lists only its own tools; trigger disconnect() from the governor and assert the other agent keeps working and the revoked one fails closed.

Docs with the full walkthrough: https://vinkius.com/learn/connect-sdk/build-agent-fleet
