---
skill: audit
machine_sku: agent_surface_audit
service: agora-labor
endpoint: POST /v1/agent_surface_audit
price_usd: $0.25
price_atomic_usdc: 250000
human_url: https://www.virohanalife.com/audit
human_price: EUR 99
payment: x402-v2
network: eip155:8453
receipt_spec: agora-receipts-v1
report_schema: virohana.agent-readiness-audit/1
generated_at: 2026-09-05T21:31:10Z
---

# Agent-Readiness Audit

**Automated agent-readiness audit of a public domain: discovery files, agent card, MCP, payments, structured data — scored 0-100 with fixes. POST {domain} -> scored report.**

One engine, two rails. An agent buys it per call over x402; a human buys the
same audit on the website and reads it on a status page. Same probes, same
score, same report.

| | Machine rail | Human rail |
| --- | --- | --- |
| Who it is for | An autonomous agent, no human in the loop | A person with a domain |
| Where | `POST https://labor.virohanalife.com/v1/agent_surface_audit` | https://www.virohanalife.com/audit |
| Price | **$0.25** (250000 atomic USDC, 6 decimals) | **EUR 99** |
| Payment | x402 v2 on `eip155:8453` | Stripe Checkout |
| Delivery | JSON report + markdown, in the response | Status page, when the audit finishes |
| Receipt | `agora-receipts-v1`, Ed25519-signed | Invoice from Stripe Checkout |

### What it checks

The audit answers one question: **if an AI agent showed up at this domain
today, could it understand what is on offer and transact?** It probes only
public surfaces, with no credentials and no cookies:

- `robots.txt` — including whether it takes a position on AI crawlers, and Content-Signal
- `llms.txt` and `llms-full.txt`
- `/.well-known/agent-card.json` (and the older `agent.json`)
- `security.txt`, the XML sitemap, and JSON-LD structured data on the homepage
- MCP endpoint discovery (`/mcp`, `mcp.<domain>`) — `initialize` + `tools/list`
- x402 payment discovery (`/.well-known/x402`) — is the domain machine-payable at all
- `Accept: text/markdown` content negotiation, soft-404 behaviour, HTTPS/HSTS basics

Output is a score of 0–100, a band, and severity-ranked findings — each with the
evidence URL it came from and the fix.

### Input

| Param | Type | Required | Notes |
| --- | --- | --- | --- |
| `domain` | string | yes | — |

Request shape:

```json
{
  "method": "POST",
  "url": "https://labor.virohanalife.com/v1/agent_surface_audit",
  "headers": {
    "content-type": "application/json",
    "X-PAYMENT": "<x402 v2 payment payload>"
  },
  "body": {
    "domain": "example.com"
  }
}
```

### Output

The report is a versioned contract: `schema: "virohana.agent-readiness-audit/1"`.
A breaking change to any field gets a new schema value, never an in-place edit —
so you can pin against `/1` and stay pinned. `report_md` carries the same report
rendered as markdown.

```json
{
  "schema": "virohana.agent-readiness-audit/1",
  "engine_version": "1.0.0",
  "domain": "example.com",
  "generated_at": "2026-09-05T21:00:00Z",
  "score": 11,
  "band": "effectively invisible to agents",
  "summary": "…",
  "checks": {
    "llms_txt": {
      "present": false
    }
  },
  "findings": [
    {
      "severity": "high",
      "title": "No /llms.txt",
      "evidence": "https://example.com/llms.txt",
      "fix": "…"
    }
  ],
  "evidence": [
    "https://example.com/robots.txt"
  ],
  "report_md": "# Agent-Readiness Audit — example.com …"
}
```

### What it will refuse

The target must be a public, third-party, fully-qualified DNS name. Loopback,
RFC1918, link-local, CGNAT, ULA and multicast addresses are refused, as are IP
literals, userinfo in the target, ports other than 80/443, and our own domains.
Every redirect hop is re-validated. A refusal is
`400 {"error": "audit_failed", "detail": "target refused: …"}` and nothing is probed.

### Paying for it — the x402 402-flow

The endpoint speaks **x402 v2**. Payment is a two-request loop; there is no
API key to obtain, no account to create, and no human step.

**1. Ask without paying.** Send the real request with no `X-PAYMENT` header.
You get `402 Payment Required` and a machine-readable quote:

```bash
curl -sS -X POST https://labor.virohanalife.com/v1/agent_surface_audit \
  -H 'content-type: application/json' \
  -d '<your request body>'
```

```json
{
  "x402Version": 2,
  "error": "X-PAYMENT header is required",
  "resource": {
    "url": "https://labor.virohanalife.com/v1/agent_surface_audit",
    "mimeType": "application/json"
  },
  "accepts": [
    {
      "scheme": "exact",
      "network": "eip155:8453",
      "amount": "250000",
      "payTo": "0xb25cc5f3475eefb6142d4a7b907a758b9652c73d",
      "asset": "USDC",
      "maxTimeoutSeconds": 60
    }
  ]
}
```

**2. Read `accepts[0]`.** It is the offer: pay `amount` ($0.25, in
atomic units of USDC, 6 decimals) to `payTo` on `eip155:8453`, within
`maxTimeoutSeconds`. `scheme: "exact"` means the exact amount, not a maximum.

**3. Pay and build the payment payload.** Settle via any x402 v2 client or
facilitator. The facilitator this service verifies against is advertised in
the 402 body under `accepts[0].extra.facilitator_url`, and again at
`https://labor.virohanalife.com/.well-known/x402`.

**4. Retry the identical request with `X-PAYMENT`.**

```bash
curl -sS -X POST https://labor.virohanalife.com/v1/agent_surface_audit \
  -H 'content-type: application/json' \
  -H "X-PAYMENT: $PAYMENT_PAYLOAD" \
  -d '<the same request body>'
```

The second call returns `200` with the work product. The request body must be
byte-identical to the one you quoted against — the receipt commits to its
SHA-256.

> During the reputation-bootstrap period a free tier may be enabled for some
> routes, in which case step 1 returns `200` directly. Routes marked
> `paid=True` always require settlement regardless. The live answer is the
> `free_tier` field at `/.well-known/x402` — read it, do not assume it.

### Verifying you got what you paid for

Every settled job produces a receipt you can verify **without trusting
Virohana** — the check is offline Ed25519 arithmetic against a published key.

**Key A — the receipt-signing key** (`agora-receipts-v1`):

```
-----BEGIN PUBLIC KEY-----
MCowBQYDK2VwAyEA99UDxXbGjzF55V16DG2fQSF0FfnoojmUb5muNYT0Hzk=
-----END PUBLIC KEY-----
```

**Key B — the labor response-signing key.** Separate key, separate job: it
signs the raw response body of a paid call (`X-Agent-Signature`, and
`response_sig` in the receipt record). It is published in every receipt
returned with every paid call (`.receipt.signer_pubkey`):

```
-----BEGIN PUBLIC KEY-----
MCowBQYDK2VwAyEA89J5xh6OcOGMG4Y+SIpejKbmc82xQ3VEr/9K3yk1Gpk=
-----END PUBLIC KEY-----
```

These are two different Ed25519 keys with two different jobs. Verify a
receipt's authenticity with Key A; verify that a response body is the one
the receipt commits to with Key B. Do not substitute one for the other.

**Step 1 — fetch the receipt.**

```bash
# Your receipt is already in the paid 200 response, as `.receipt`.
# To re-fetch it later, use its exact id:
curl -sS https://labor.virohanalife.com/v1/receipts/<receipt_id>   # one receipt + verify instructions
# Bulk listing (GET /v1/receipts) is authenticated: enumerating receipts
# would expose every other customer's payer -> purchase linkage.
```

**Step 2 — check the hashes commit to your job.** `input_sha256` must equal
the SHA-256 of the exact request body you sent; `output_sha256` must equal
the SHA-256 of the response body you received. If either differs, the receipt
is for a different job.

**Step 3 — verify the signature yourself.** The signature covers the
canonical JSON of the receipt *minus* the `sig` field:

```python
import json
from cryptography.hazmat.primitives.serialization import load_pem_public_key

body = dict(receipt); sig = bytes.fromhex(body.pop("sig"))
canonical = json.dumps(body, sort_keys=True, separators=(",", ":"),
                       ensure_ascii=False).encode("utf-8")
load_pem_public_key(RECEIPT_PUBKEY_PEM.encode()).verify(sig, canonical)  # raises if invalid
```

**Step 4 (optional) — second opinion.** The spine will verify a receipt for
you, which is useful as a cross-check but is *not* the trust root — step 3 is:

```bash
curl -sS -X POST https://agora.virohanalife.com/v1/receipt_verify \
  -H 'content-type: application/json' \
  -d '{"receipt": <receipt-json>}'
# -> {"valid": true|false, "reason": "..."}
```

**Step 5 — settlement is on-chain.** Paid receipts carry `tx_hash`,
`network`, `payer`, `pay_to` and `facilitator`. The USDC transfer is
independently checkable on Base regardless of anything this service says.

### Failure modes

| Status | Meaning | What to do |
| --- | --- | --- |
| `402` | No/invalid payment | Read `accepts[0]`, settle, retry with `X-PAYMENT` |
| `400` | Target refused by the safety gate | Send a public third-party domain |
| `429` | Rate limited | Per-payer burst and daily caps apply; back off |
| `504` | The audit exceeded its 60 s bound | Retry; a slow target can time out |
| `500` | Engine error | Sanitized by design — no internals are returned |

