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

# Agent self-registration

> How an AI agent obtains its own VisIQ credential through the human-approved agent_auth device flow — register, get a user code, have an operator approve, poll for the key.

Instead of a human minting a key up front and pasting it into your agent, the
agent can **register itself** and have a human approve it. VisIQ implements this
as an [RFC 8628](https://www.rfc-editor.org/rfc/rfc8628)-shaped **device
authorization flow** (the `agent_auth` grant). Issuance still always requires a
human to approve — there is no anonymous or instant credential.

<Note>
  This is the machine-readable counterpart to the
  [agent authentication guide](https://visiqlabs.com/auth.md) served for agents at
  `visiqlabs.com/auth.md`. The flow is advertised in the `agent_auth` block of
  [`/.well-known/oauth-authorization-server`](https://visiqlabs.com/.well-known/oauth-authorization-server).
</Note>

## When to use it

* Your agent runs somewhere an operator cannot pre-provision a key, but a human
  can approve a one-time request.
* You want the credential **bound to the approving human's account** and scoped
  to exactly what they agree to — never broader than their own permissions.

If an operator can simply create a key in the dashboard, use
[Managing API keys](/automation/api-keys) instead — this flow exists for the
agent-initiated case.

## The flow at a glance

1. **Agent → VisIQ:** `POST /api/agent/identity` to register.
2. **VisIQ → Agent:** returns a `claim_token`, a short `user_code`, and a
   verification URL.
3. **Agent → Human:** show the operator the `user_code` /
   `verification_uri_complete`.
4. **Human → VisIQ:** the operator signs in, opens the URL, reviews the
   requested audience and permissions, and approves.
5. **Agent → VisIQ (poll):** `POST /api/agent/identity/claim` every `interval`
   seconds — `400 authorization_pending` until approved.
6. **VisIQ → Agent:** once approved, the `api_key` is returned **exactly once**.

## Step 1 — Register

`POST https://app.visiqlabs.com/api/agent/identity`

```json theme={null}
{ "type": "anonymous", "agent_name": "my-agent" }
```

By default this requests a **harness** key (least privilege — see
[key audiences](/automation/introduction)). To request the **full product
surface**, ask for a management key, optionally with an explicit permission
list:

```json theme={null}
{
  "type": "anonymous",
  "agent_name": "my-agent",
  "requested_key_type": "management",
  "requested_permissions": [
    "allow_rules:view",
    "allow_rules:create",
    "allow_agents:view",
    "allow_audit_log:view"
  ]
}
```

| Field                          | Required | Notes                                                                                           |
| ------------------------------ | -------- | ----------------------------------------------------------------------------------------------- |
| `type`                         | yes      | `anonymous`, or `identity_assertion` to assert a verified identity                              |
| `agent_name`                   | no       | A label the operator sees on the approval screen (≤ 200 chars)                                  |
| `assertion_type` / `assertion` | no       | With `type: identity_assertion` — e.g. `verified_email` + the address                           |
| `requested_key_type`           | no       | `harness` (default) or `management`                                                             |
| `requested_permissions`        | no       | For a management key: the exact RBAC grants you need (≤ 64). Omit for the default product grant |

Omitting `requested_permissions` requests the default product grant (rules,
agents, audit/outcomes, action schemas, HITL responses, settings) — but **never
account administration**: a device-flow key cannot manage API keys, the team, or
billing.

The response is a device-flow ceremony:

```json theme={null}
{
  "registration_id": "...",
  "claim_token": "vqac_...",
  "claim": {
    "user_code": "WXYZ-2345",
    "verification_uri": "https://app.visiqlabs.com/agent/claim",
    "verification_uri_complete": "https://app.visiqlabs.com/agent/claim?user_code=WXYZ-2345",
    "expires_in": 1800,
    "interval": 5
  }
}
```

Keep the `claim_token` private — it is what you exchange for the key in Step 3.
Show the **human** the `user_code` / `verification_uri`.

## Step 2 — Have a human approve

Show your operator the `verification_uri_complete` — a single clickable link
with the code already embedded (RFC 8628 one-click); the code survives the
sign-in / MFA detour and the approval page auto-loads your pending registration.
Fall back to the bare `verification_uri` plus the typed `user_code` if a
one-click link is not usable.

They sign in to VisIQ, open the URL, **review the requested audience and
permissions**, and approve. Approval mints a governed key bound to their account
— harness by default, management if you requested it and they agreed. They can
narrow the grant, and can never grant beyond their own permissions.

## Step 3 — Poll for the credential

`POST https://app.visiqlabs.com/api/agent/identity/claim`, every `interval`
seconds, with your `claim_token`:

```json theme={null}
{ "claim_token": "vqac_..." }
```

While the human has not approved yet, you get:

```json theme={null}
{ "error": "authorization_pending" }
```

(HTTP `400`). Keep polling at `interval` seconds — do not poll faster. Once
approved, you receive the credential **exactly once**:

```json theme={null}
{
  "token_type": "api_key",
  "api_key": "vq_prod_...",
  "agent_id": "...",
  "api_base_url": "https://api.visiqlabs.com",
  "key_type": "harness",
  "permissions": null
}
```

* `key_type` tells you which audience was actually granted (`harness` or
  `management`).
* For a management key, `permissions` is the exact grant list your credential
  holds; it is `null` for a harness key.

<Warning>
  The `api_key` is shown **once**. Store it in your secret manager immediately —
  VisIQ keeps only a SHA-256 hash and cannot show it again. If you lose it,
  [revoke it](#revoking) and register again.
</Warning>

Claim tickets expire after **30 minutes**. If the ceremony lapses (the human
never approves in time), register again for a fresh `user_code`.

Then use the key as a Bearer token — see
[Use a key](/automation/api-keys#use-a-key).

## Revoking

You can retire a device-flow credential yourself, at any time:

* **Cancel or revoke the device-flow credential** —
  `POST https://app.visiqlabs.com/api/agent/identity/revoke` with
  `{ "token": "vq_prod_..." }` (an issued key) or `{ "claim_token": "vqac_..." }`
  (the pending ticket, which also revokes an already-issued key).
* **Self-revoke any key** you hold — `POST /allow/self/revoke`, authenticated by
  the key itself, no permission required. See
  [Revoke your own key](/automation/api-keys#revoke-your-own-key-self-revocation).

## Prefer MCP?

Once you hold a **management** key you can operate VisIQ through the
[Platform MCP server](/automation/mcp) instead of raw REST — including retiring
the key with the `revoke_self` tool when you are done.
