# AGENTS.md — building against the AgentPass API

AgentPass exposes one scan endpoint, two cached report endpoints and one MCP server. Everything returns JSON. There is nothing to render and no OAuth dance for the free tier.

When to use this API: you have a URL, you want a deterministic agent-readiness score and a machine-readable list of what to fix, and you want to feed those fixes into a coding agent without a human rewriting them.

## Install

No package to install. The API is HTTP; the MCP server is JSON-RPC over POST.

```bash
# nothing to install — verify the host is up
curl -s https://www.agentpass.page/healthz
# {"ok":true,"service":"agentpass","reports":0,...}
```

If you prefer a typed client, generate one from the OpenAPI document:

```bash
npx openapi-typescript https://www.agentpass.page/openapi.json -o agentpass.d.ts
```

## Configuration

| Variable | Default | Meaning |
|---|---|---|
| `AGENTPASS_BASE_URL` | `https://www.agentpass.page` | API origin. Override for a self-hosted instance. |
| `AGENTPASS_API_KEY` | unset | Bearer token for paid limits. Free tier works without it. |
| `AGENTPASS_TIMEOUT_MS` | `20000` | Client timeout. A cold scan of a slow origin can take ten seconds. |

```bash
export AGENTPASS_BASE_URL="https://www.agentpass.page"
export AGENTPASS_API_KEY="ap_live_..."   # optional
```

## Worked example

Request:

```bash
curl -s "$AGENTPASS_BASE_URL/api/scan?url=https://example.com" \
  -H "Accept: application/json" \
  -H "Idempotency-Key: 7f3c1a9e-scan-1"
```

Response (HTTP 200, trimmed):

```json
{
  "url": "https://example.com",
  "finalUrl": "https://example.com/",
  "scannedAt": "2026-11-09T18:22:41.108Z",
  "engine": "ARI-100",
  "score": 78,
  "grade": "B",
  "gradeLabel": "Agent-aware",
  "level": 3,
  "accessScore": 91,
  "accessCoverage": { "tested": 27, "of": 29 },
  "a11yScore": 86,
  "domains": [
    { "id": "access", "name": "Reachability & Access", "weight": 20, "score": 88.6, "passed": 11, "checks": 14 }
  ],
  "crawlers": [
    { "ua": "OAI-SearchBot", "platform": "ChatGPT search", "role": "search", "weight": 10, "status": 200, "verdict": "allowed" }
  ],
  "fixes": [
    { "id": "md-negotiation", "domain": "discovery", "title": "Markdown is served when asked", "weight": 3, "result": "fail", "recoverable": 3, "evidence": "Accept: text/markdown → text/html", "prompt": "..." }
  ],
  "counts": { "total": 120, "applicable": 96, "pass": 71, "partial": 8, "fail": 17, "notApplicable": 24, "inconclusive": 2 }
}
```

Then read the cached report and hand the fix pack to a coding agent:

```bash
curl -s "$AGENTPASS_BASE_URL/report/example.com.md" -H "Accept: text/markdown"
```

Or call it as a tool:

```bash
curl -s "$AGENTPASS_BASE_URL/mcp" -H 'content-type: application/json' -d '{
  "jsonrpc": "2.0", "id": 1, "method": "tools/call",
  "params": { "name": "scan_site", "arguments": { "url": "https://example.com" } }
}'
```

## The loop an agent should run

1. `scan_site` with the URL you are about to ship.
2. Read `fixes`, highest `recoverable` first.
3. Apply each `prompt` verbatim; every prompt names the check id that will be re-run.
4. Re-scan and compare `score`. A drop is a regression, not noise.

## Errors and retries

| Status | Meaning | What to do |
|---|---|---|
| 400 | `url` missing or not absolute | fix the input; the body names the field |
| 404 | no cached report for that host | call `/api/scan` first |
| 429 | rate limit | back off using `RateLimit-Reset`; retry after that many seconds |
| 502 | the target site did not answer | retry once, then report the origin as unreachable |

Errors are JSON: `{ "type", "title", "status", "detail" }`. Safe to retry GETs; use `Idempotency-Key` on any call that could start a paid scan twice.

## Discovery order

1. This file.
2. `https://www.agentpass.page/openapi.json` — schemas and descriptions.
3. `https://www.agentpass.page/.well-known/ard.json` — every interface with type and url.
4. `https://www.agentpass.page/mcp` — tool list, if you are an MCP client.
