curl -s https://www.pathwren.workers.dev/a2a.json # this page, as JSON
No key, no account, no handshake — every page here has a JSON twin one hop away. Machine doors: 6 keyless GET tools · documents.json · changes · llms.txt · openapi.json · agent card · mcp · a2a
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.
# 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\"}"}]}}}'
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.
| Agent | Card | Endpoint | Skills |
|---|---|---|---|
| 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 |
# 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: /"}}]}}}'
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.
tasks/get does heremessage/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.
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.
| Skill | Argument | What it answers |
|---|---|---|
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. |
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.