# Human handoff

> When a site asks for a human check, give your person a link or QR code, poll for the result, and continue with the pass.

Agents cannot, and should not, pass the press-and-hold check. When a site
challenges an agent session, the response includes a **handoff**: a link the
agent's person opens on their own device to complete the check, after which
the agent can continue.

## When you get one

Challenges go to an agent session when the request comes from a signed
agent, matches an agent policy label, has an AI or headless User-Agent, or
shows an agent or automation finding.

- A browser session gets `428` with `"status": "challenge_required"`.
- A signed agent on the agent API gets `403`.

```json
{
  "status": "challenge_required",
  "handoff": {
    "id": "hof_…",
    "url": "https://shop.example/handoff/hof_…",
    "poll": "https://shop.example/v1/handoff/hof_…",
    "qrSvg": "<svg …>",
    "expiresAt": "2026-09-25T10:05:00Z",
    "interval": 2
  }
}
```

The handoff URL is also in the `AgentGate-Handoff` and `Link` response
headers.

## 1. Show your person the link

Display `url`, or render `qrSvg` so they can scan it with their phone. Tell
them what you were trying to do. The page asks them to press and hold (or
to wait, if they cannot hold) and never asks for passwords or payment.

## 2. Poll

Call `GET poll` every `interval` seconds, or long-poll with `?wait=8`. Poll
from the **same** session:

- a browser session sends the `ag_session` cookie it already has;
- on the agent API, sign the `GET` over `@authority`, `@method` and `@path`.

Anyone else gets `404`.

## 3. Collect the pass

When the reply is `{"status": "passed", "pass": "…", "passKind": "hold"}`:

- **browser session:** the response also sets the `ag_pass` cookie; resubmit
  with your cookie jar;
- **agent API:** send `AgentGate-Pass: <pass>` on your next signed requests
  (valid for 15 minutes).

## Properties

| Property | Value |
| --- | --- |
| Lifetime | five minutes; polling returns `410` once it is redeemed or expired |
| Use | completes once and redeems once |
| Binding | one site and one subject (the session or the agent); stored as an HMAC, only the SHA-256 of the ID is kept |
| Rate limits | issue: 5 per subject, 10 per address, 600 per site per minute; page: 30 per address; completion: 6 per handoff; poll: 120 per handoff |

> [!WARNING]
> Anyone holding the handoff URL can complete the check. The binding stops
> anyone else from collecting the pass, but it does not prove that the
> person who completed it is the agent's user. Share the link only with
> your person.
