Guide

How to make a website agent-ready

"Agent-ready" means three different things to three different kinds of AI agent — and they stack. Here is exactly how we made this validator agent-ready, with the code we shipped, so you can copy the pattern.

There are three independent layers. Adopt any one on its own; together they cover a crawler reading your site, an agent driving your UI in the browser, and another agent calling you over the network.

Layer 1 — llms.txt: context for crawlers

The baseline. A plain-text llms.txt at your root tells an AI crawler what your site is and which pages matter, in priority order. It's read at fetch time — no JavaScript, no protocol. Start here: how to create one.

Layer 2 — WebMCP: tools for in-browser agents

WebMCP lets a page expose callable tools to an AI agent running inside the browser, so the agent invokes a typed action instead of guessing at your form. There are two ways, and we ship both.

Declarative — annotate a real form and the browser synthesizes a tool from it:

<form toolname="open_llms_txt_report"
      tooldescription="Validate a site's llms.txt and open its report.">
  <input name="url" toolparamdescription="Domain or URL to validate">
</form>

Imperative — register a tool in JavaScript that returns structured data directly:

navigator.modelContext?.registerTool({
  name: "validate_llms_txt",
  description: "Validate a website's llms.txt; returns a 0-100 score and findings.",
  inputSchema: { type: "object", properties: { url: { type: "string" } }, required: ["url"] },
  execute: (input) => fetch("/api/validate?url=" + encodeURIComponent(input.url))
    .then(r => r.json())
    .then(data => ({ content: [{ type: "text", text: JSON.stringify(data) }] }))
});

Guard the imperative call behind if (navigator.modelContext) so it's a no-op where WebMCP is absent. It's a Chrome origin trial today, so real reach is small — treat it as a forward signal, not traffic.

Layer 3 — A2A: a callable agent for other agents

The Agent2Agent (A2A) protocol lets other agents discover and call your service. You publish an agent card and back it with a JSON-RPC endpoint:

// GET /.well-known/agent-card.json
{
  "name": "llms.txt Validator",
  "url": "https://llms-txt-validator.dev/a2a",
  "skills": [{ "id": "validate_llms_txt", "name": "Validate llms.txt" }]
}

The url must point at a working endpoint that speaks A2A — we implement the synchronous message/send method, wrapping the same validation logic as a skill. The card is a contract, not a meta tag.

The one rule: don't publish a signal you can't back

It's tempting to drop an empty agent card or fake form annotations to turn an audit green. Don't. An agent that fetches your card and calls a dead endpoint — or invokes a tool that does nothing — trusts you less afterward. Every signal here should resolve to something real. That's why this validator reports a WebMCP or A2A signal as "present" only when a working implementation backs it.

How to verify each layer

Keep reading

Validate your llms.txt →