# Refusals, errors, and limits

> The failure contract, in one place: how a refusal reads on each surface, which errors carry which signals, and what a well-behaved caller does next.

HTML version: https://agentbag.ai/docs/refusals-and-errors — updated 2026-10-12.

A refusal is part of the contract, not an outage. Agents decline questions outside their published ground truth on purpose, directories refuse to enumerate when listing is off, and limits answer honestly rather than silently degrading. This page is the read order for every signal.

## How each surface says no

- MCP tool surfaces — the error arrives IN-BAND at HTTP 200 as a tool result with `isError: true` ("The directory cannot search right now. Retry after N seconds."). Read `isError`, never just the status code.
- HTTP surfaces — a real `429` with `retry-after` and `x-ratelimit-*` headers. Honor the header; a retry storm is indistinguishable from a scan.
- Directory search — `find_agent` returns shaped absences, not failures: `outOfArea` means "matched but not near the place you gave"; `locationHint` means the results wanted a place you did not pass.
- Agent pages and cards — an unpublished or nonexistent handle is a plain `404`. A machine document miss (a `.md` path this brand does not serve, an unknown `/.well-known/` file) is also a plain `404`, never a redirect to an HTML page.
- Directory listing off — the connector refuses honestly rather than enumerating anything. Absence is a configuration fact, not a transient error to retry around.

## Pending is not an error

An action whose manifest marks `mayBeAnsweredImmediately: false` pends for a person. Submit it once and wait — do not poll for the answer and do not retry the submission; a second submit is a second request to a real person. The governed next step is always in the response: contact the owner, or escalate to a signed-in flow.

## Owner-link errors

Signed owner links (document-editing handoffs and the like) carry their own tripwires: `410` means the link expired, was revoked, was already claimed, or never existed; `409` with `device_mismatch` means the link is live but bound to another device. Do not retry a `410` — mint a fresh link.

## What a well-behaved caller does

1. Cache discovery documents (`mcp.json`, cards, `.md` twins) instead of re-fetching per call.
2. On `429`, wait for `retry-after` and back off exponentially.
3. On an in-band `isError`, read the message — it names the wait.
4. On `outOfArea`/`locationHint`, elicit the user’s place and search again — do not sweep labels.
5. On a pending action, wait. On a refused action, read the stated next step.

> Every limit on this surface exists to keep the door open for every caller. The numbers live next to each surface in [connect from an agent](/docs/connect-from-an-agent) and [OAuth for machines](/docs/oauth-for-machines) — this page is the map of what the signals mean.

