{
 "name": "A2A agents — AI Crawler Index",
 "what": "This host as eight A2A (Agent2Agent) v1.0 agents, one per capability: the index, robots.txt lint, crawler IP verification, log triage, discovery-document audit, MCP endpoint conformance, discovery and auth posture, and one score card. JSON-RPC, no key, a card each.",
 "url": "https://www.pathwren.workers.dev/a2a.json",
 "twin_of": "https://www.pathwren.workers.dev/a2a.html",
 "page": {
  "path": "/a2a.html",
  "url": "https://www.pathwren.workers.dev/a2a.html",
  "type": "text/html"
 },
 "generated_at": "2026-09-03T07:55:35+00:00",
 "generated_from": "the bytes of /a2a.html, by surfaces/ai-crawler-index/build.py, in the same pass that wrote the page — one source, so the page and this document cannot disagree about what this host says.",
 "license": {
  "document": "CC0-1.0",
  "url": "https://creativecommons.org/publicdomain/zero/1.0/"
 },
 "access": {
  "api_key": "none",
  "account": "none",
  "rate_limit": "none",
  "cors": "*",
  "auth": "none — every document here is a public GET"
 },
 "commands": [
  "# nothing to hand? this needs no arguments and no editing, and the subject is you",
  "curl -s https://www.pathwren.workers.dev/a2a -H 'content-type: application/json' -d '{",
  " \"jsonrpc\":\"2.0\",\"id\":1,\"method\":\"message/send\",",
  " \"params\":{\"message\":{\"role\":\"ROLE_USER\",\"messageId\":\"1\",\"parts\":[",
  "   {\"text\":\"{\\\"skill\\\":\\\"whoami\\\"}\"}]}}}'",
  "# a skill with arguments, on the root agent",
  "curl -s https://www.pathwren.workers.dev/a2a -H 'content-type: application/json' -d '{",
  " \"jsonrpc\":\"2.0\",\"id\":1,\"method\":\"SendMessage\",",
  " \"params\":{\"message\":{\"messageId\":\"1\",\"role\":\"ROLE_USER\",\"parts\":[",
  "   {\"data\":{\"skill\":\"classify_user_agent\",\"user_agent\":\"GPTBot/1.2\"}}]}}}'",
  "# and so does each capability agent, same shape, its own skills",
  "curl -s https://www.pathwren.workers.dev/a2a/robots -H 'content-type: application/json' -d '{",
  " \"jsonrpc\":\"2.0\",\"id\":1,\"method\":\"SendMessage\",",
  " \"params\":{\"message\":{\"messageId\":\"1\",\"role\":\"ROLE_USER\",\"parts\":[",
  "   {\"data\":{\"skill\":\"audit_ai_access\",\"robots_txt\":\"User-agent: *\\\\nDisallow: /\"}}]}}}'"
 ],
 "sections": [
  {
   "heading": "A2A agents",
   "text": [
    "The same work again, spoken as A2A v1.0 instead of as files or as MCP. JSON-RPC 2.0 over HTTP POST, no key, no signup, no session. Every skill is read-only, and each one is executed by exactly the function that answers the identically-named MCP tool — two protocols, one implementation.",
    "That returns a Task already in state completed, in the same HTTP response: the answer is in status.message and mirrored into one artifact. There is nothing to poll, nothing to subscribe to and no second request to make. Every skill on every one of the eight agents, as a body you can send unedited, is in /a2a/example.json — one document, {} bodies and curl lines, no schema to read first.",
    "Five agents, not one. This host publishes five agent cards, one per capability, each at its own URL with its own endpoint and its own skills. No skill appears on two cards. Point your client at whichever one does the job; nothing here requires the others.",
    "Each card is served at <endpoint>/.well-known/agent-card.json, with identical bytes at the legacy agent.json name and from GET on the endpoint itself. The root card is also at /.well-known/agent-card.json, where a client that knows only the host will look."
   ],
   "commands": [
    "# nothing to hand? this needs no arguments and no editing, and the subject is you",
    "curl -s https://www.pathwren.workers.dev/a2a -H 'content-type: application/json' -d '{",
    " \"jsonrpc\":\"2.0\",\"id\":1,\"method\":\"message/send\",",
    " \"params\":{\"message\":{\"role\":\"ROLE_USER\",\"messageId\":\"1\",\"parts\":[",
    "   {\"text\":\"{\\\"skill\\\":\\\"whoami\\\"}\"}]}}}'",
    "# a skill with arguments, on the root agent",
    "curl -s https://www.pathwren.workers.dev/a2a -H 'content-type: application/json' -d '{",
    " \"jsonrpc\":\"2.0\",\"id\":1,\"method\":\"SendMessage\",",
    " \"params\":{\"message\":{\"messageId\":\"1\",\"role\":\"ROLE_USER\",\"parts\":[",
    "   {\"data\":{\"skill\":\"classify_user_agent\",\"user_agent\":\"GPTBot/1.2\"}}]}}}'",
    "# and so does each capability agent, same shape, its own skills",
    "curl -s https://www.pathwren.workers.dev/a2a/robots -H 'content-type: application/json' -d '{",
    " \"jsonrpc\":\"2.0\",\"id\":1,\"method\":\"SendMessage\",",
    " \"params\":{\"message\":{\"messageId\":\"1\",\"role\":\"ROLE_USER\",\"parts\":[",
    "   {\"data\":{\"skill\":\"audit_ai_access\",\"robots_txt\":\"User-agent: *\\\\nDisallow: /\"}}]}}}'"
   ],
   "tables": [
    {
     "headers": [
      "Agent",
      "Card",
      "Endpoint",
      "Skills"
     ],
     "rows": [
      [
       "The index itself",
       "/.well-known/agent-card.json",
       "/a2a",
       "classify_user_agent, lookup_crawler, list_crawlers, generate_robots_txt, is_verified_crawler_ip, whats_changed"
      ],
      [
       "Crawler IP Verifier",
       "/a2a/netcheck/.well-known/agent-card.json",
       "/a2a/netcheck",
       "verify_batch, lookup_prefix, export_ip_acl, verification_methods, range_stats, whoami, example"
      ],
      [
       "robots.txt Policy Lint",
       "/a2a/robots/.well-known/agent-card.json",
       "/a2a/robots",
       "lint_robots_txt, check_path_allowed, audit_ai_access, diff_robots_txt, merge_policy, whoami, example"
      ],
      [
       "Crawler Log Triage",
       "/a2a/triage/.well-known/agent-card.json",
       "/a2a/triage",
       "triage_log, find_impersonators, summarize_by_operator, robots_from_log, waf_ruleset_from_log, whoami, example"
      ],
      [
       "Agent Discovery Doctor",
       "/a2a/doctor/.well-known/agent-card.json",
       "/a2a/doctor",
       "check_discovery_documents, explain_document, validate_llms_txt, llms_txt_from_sitemap, validate_agent_card, whoami, example"
      ],
      [
       "MCP Endpoint Conformance",
       "/a2a/lint/.well-known/agent-card.json",
       "/a2a/lint",
       "handshake_report, tools_list_report, error_conformance, whoami, example"
      ],
      [
       "Discovery and Auth-Posture Probe",
       "/a2a/discovery/.well-known/agent-card.json",
       "/a2a/discovery",
       "discovery_report, whoami, example"
      ],
      [
       "MCP Endpoint Score Card",
       "/a2a/score/.well-known/agent-card.json",
       "/a2a/score",
       "score_card, whoami, example"
      ]
     ]
    }
   ],
   "links": [
    "https://a2a-protocol.org/latest/specification/",
    "/mcp.html",
    "/a2a/example.json",
    "/.well-known/agent-card.json",
    "/a2a/netcheck/.well-known/agent-card.json",
    "/a2a/robots/.well-known/agent-card.json",
    "/a2a/triage/.well-known/agent-card.json",
    "/a2a/doctor/.well-known/agent-card.json",
    "/a2a/lint/.well-known/agent-card.json",
    "/a2a/discovery/.well-known/agent-card.json",
    "/a2a/score/.well-known/agent-card.json"
   ]
  },
  {
   "heading": "Tasks, and what tasks/get does here",
   "text": [
    "message/send (v1.0: SendMessage) is the method that invokes a skill, and it is the only one you need. It returns a completed Task synchronously — this host runs no long work, so no task is ever pending.",
    "The task id is not a handle into a database: this worker keeps no task store. The id encodes the call that produced it, so tasks/get answers by re-running that same deterministic, read-only call and returning the identical task. An id this host did not mint returns -32001 — nothing was ever created for it — and that error carries the message/send body that would create one, because a client asking after a task it never created is a client that has not been shown the method that makes one. tasks/cancel on a task that is already finished returns -32002."
   ],
   "commands": [],
   "tables": [],
   "links": []
  },
  {
   "heading": "Skills of the root agent",
   "text": [
    "Named exactly as in the card. Send a DataPart naming one — {\"data\":{\"skill\":\"lookup_crawler\",\"slug\":\"claudebot\"}} — or plain text, which is matched against a small set of rules and answered with the skill list when it does not resolve. There is no model behind this endpoint: an unrecognised message gets told what to send, never a guessed answer."
   ],
   "commands": [],
   "tables": [
    {
     "headers": [
      "Skill",
      "Argument",
      "What it answers"
     ],
     "rows": [
      [
       "whoami",
       "none",
       "What this host can see about the caller: the user-agent you sent, your address, the class our own instrument books you as, whether we have seen you before, and what our robots policy says about you. Nothing is fetched and nothing is invented."
      ],
      [
       "example",
       "none",
       "This server's own worked example, run end to end, returning the real answer rather than a description of one."
      ],
      [
       "classify_user_agent",
       "user_agent",
       "Which crawler is behind this raw User-Agent, who runs it, and what blocking it costs."
      ],
      [
       "lookup_crawler",
       "slug",
       "The full record for one crawler by slug, name or robots.txt token."
      ],
      [
       "list_crawlers",
       "q, category, operator…",
       "The 150 crawlers, filtered."
      ],
      [
       "generate_robots_txt",
       "stance",
       "A ready-to-paste robots.txt for one of 8 stances."
      ],
      [
       "is_verified_crawler_ip",
       "ip",
       "Is this address inside a range the operator itself publishes? 1984 IPv4 and 1062 IPv6 prefixes."
      ],
      [
       "whats_changed",
       "since",
       "Build time, per-source freshness, and what changed."
      ]
     ]
    }
   ],
   "links": []
  },
  {
   "heading": "What it does not do, and says so in the card",
   "text": [
    "No streaming (SendStreamingMessage → -32004): there is nothing to stream when the answer is already complete. No push notifications (-32003), no task store (see above), no extended agent card (-32007). Legacy v0.3 method names (message/send, tasks/get) are accepted, and the A2A-Version header is honoured for 1.0 and 0.3.",
    "Same data as /data/agents.json, /openapi.json and /mcp — pick whichever your client speaks."
   ],
   "commands": [],
   "tables": [],
   "links": [
    "/data/agents.json",
    "/openapi.json",
    "/mcp.html"
   ]
  }
 ],
 "machine_doors": [
  {
   "url": "https://www.pathwren.workers.dev/tools/?s=client-dossiers",
   "name": "6 keyless GET tools",
   "what": "The read-only MCP tools of this host as plain GET endpoints — no JSON-RPC, no key"
  },
  {
   "url": "https://www.pathwren.workers.dev/documents.json",
   "name": "documents.json",
   "what": "Every document here with its strong ETag and the date its bytes changed"
  },
  {
   "url": "https://www.pathwren.workers.dev/changes",
   "name": "changes",
   "what": "What moved since your cursor — poll this instead of re-downloading anything"
  },
  {
   "url": "https://www.pathwren.workers.dev/llms.txt",
   "name": "llms.txt",
   "what": "The whole map in one text file"
  },
  {
   "url": "https://www.pathwren.workers.dev/openapi.json",
   "name": "openapi.json",
   "what": "Every read endpoint, described formally"
  },
  {
   "url": "https://www.pathwren.workers.dev/.well-known/agent-card.json",
   "name": "agent card",
   "what": "A2A agent card"
  },
  {
   "url": "https://www.pathwren.workers.dev/mcp",
   "name": "mcp",
   "what": "MCP over JSON-RPC (POST)"
  },
  {
   "url": "https://www.pathwren.workers.dev/a2a",
   "name": "a2a",
   "what": "A2A (POST message/send)"
  }
 ],
 "links": [
  {
   "rel": "self",
   "href": "https://www.pathwren.workers.dev/a2a.json",
   "type": "application/json"
  },
  {
   "rel": "describes",
   "href": "https://www.pathwren.workers.dev/a2a.html",
   "type": "text/html",
   "title": "The page this document is the JSON twin of: A2A agents — AI Crawler Index"
  },
  {
   "rel": "changes",
   "href": "https://www.pathwren.workers.dev/changes.json?since=111",
   "type": "application/json",
   "title": "What changed since your cursor — poll this instead of re-downloading this document",
   "cursor_param": "since",
   "head_cursor": 111,
   "min_poll_seconds": 21600,
   "how": "Read `cursor` from the response and send it back as `since`. It advances only when something really changed, so an unchanged answer is proof rather than luck — about 2.5 KB, or a 304 with no body if you send back the ETag."
  },
  {
   "rel": "related",
   "href": "https://www.pathwren.workers.dev/documents.json",
   "type": "application/json",
   "title": "Every document here with its ETag and last-modified date"
  },
  {
   "rel": "related",
   "href": "https://www.pathwren.workers.dev/data/agents.json",
   "type": "application/json",
   "title": "Every crawler record in one file"
  },
  {
   "rel": "service-desc",
   "href": "https://www.pathwren.workers.dev/openapi.json",
   "type": "application/json",
   "title": "Every read endpoint, described formally"
  },
  {
   "rel": "describedby",
   "href": "https://www.pathwren.workers.dev/llms.txt",
   "type": "text/plain",
   "title": "The whole map in one text file"
  }
 ]
}