Skip to content
Back to AI Crawler Index

Card snapshot

www.pathwren.workers.dev · 2026-09-11 23:59:45 UTC · 2c57d48aeea681d773a0d6f70b761a1741108e60bb3f5074906026b8f0faa9fc

This is a frozen copy of the agent's agent-card.json as we observed it at the timestamp above. We capture a new snapshot every time the card's content hash changes. Useful for: forensic drift analysis, verifying downstream callers see the right version, reproducing routing decisions made historically.

{
  "name": "Crawler Log Triage \u2014 AI Crawler Index",
  "description": "{\"jsonrpc\":\"2.0\",\"id\":1,\"method\":\"message/send\",\"params\":{\"message\":{\"role\":\"ROLE_USER\",\"messageId\":\"1\",\"parts\":[{\"text\":\"{\\\"skill\\\":\\\"whoami\\\"}\"}]}}} \u2014 POST that exact body to https://www.pathwren.workers.dev/a2a/triage with content-type: application/json and you are done; it comes back as a Task already in state `completed` in the same response, so there is nothing to poll. Free, read-only, no API key, no account, no consent prompt, nothing to install and nothing for you to invent. The answer is about YOU, the caller: the address this request arrived from, the user-agent you sent, the lane you came in on (`metadata.arrivedOn` on the task you get back names the protocol, the endpoint and the A2A version you spoke), the class this host's own instrument books you as, and whether it has seen you here before. Nothing is fetched to answer it and no argument exists to invent \u2014 it is the one question you can ask a stranger's agent while holding nothing of your own. Paste access-log lines and get back who crawled you. It classifies each line by operator and category, rolls the whole file up by operator with byte and hit counts, finds the lines that are LYING \u2014 a user-agent claiming an operator from an address outside every range that operator publishes \u2014 and turns the file you actually served into a robots.txt for a stated stance or a WAF ruleset for nginx, caddy, Cloudflare, haproxy or apache. Combined, common, JSON and bare ip+user-agent lines are understood; nothing is fetched and no log is stored. An address outside a published range is reported as unverifiable, which is not the same as fake. Deterministic and read-only: there is no model behind it \u2014 every answer comes from a public dataset rebuilt every six hours from each operator's own published documentation and IP ranges, and the same skills are also available as MCP tools at https://www.pathwren.workers.dev/mcp/triage (no key, no signup, no quota). Independent and unaffiliated with any operator it documents. TO CALL ANY OTHER SKILL: the same `message/send` envelope (v1.0 name `SendMessage`) with a different skill name \u2014 the first line of every skill description below is that skill's complete request, ready to POST unedited, and each comes back as a Task already in state `completed` in the same response, so there is nothing to poll. Every skill on all eight agents of this host as a ready-to-send body: https://www.pathwren.workers.dev/a2a/example.json",
  "supportedInterfaces": [
    {
      "url": "https://www.pathwren.workers.dev/a2a/triage",
      "protocolBinding": "JSONRPC",
      "protocolVersion": "1.0"
    }
  ],
  "url": "https://www.pathwren.workers.dev/a2a/triage",
  "preferredTransport": "JSONRPC",
  "protocolVersion": "1.0",
  "provider": {
    "organization": "Pathwren",
    "url": "https://www.pathwren.workers.dev"
  },
  "version": "1.0.0",
  "documentationUrl": "https://www.pathwren.workers.dev/a2a.html",
  "iconUrl": "https://www.pathwren.workers.dev/icon.png",
  "jwksUri": "https://www.pathwren.workers.dev/.well-known/jwks.json",
  "jwks_uri": "https://www.pathwren.workers.dev/.well-known/jwks.json",
  "capabilities": {
    "streaming": false,
    "pushNotifications": false,
    "extendedAgentCard": false,
    "extensions": [
      {
        "uri": "https://www.pathwren.workers.dev/changes.json",
        "description": "Since-cursor change feed over everything this agent answers from: GET /changes.json?since=<cursor> returns only what moved \u2014 operator IP-range lists that gained or lost prefixes, upstreams that failed or recovered, crawler records added or edited. Read `cursor` from the answer and send it back next time; it advances only on a real change, so an unchanged answer is proof and costs about 2.5 KB. The same feed is the changes_since skill on this endpoint.",
        "required": false,
        "params": {
          "cursorParameter": "since",
          "transport": "https-get",
          "minPollSeconds": 21600,
          "skill": "changes_since",
          "siblingDocument": "https://www.pathwren.workers.dev/data/agents.json"
        }
      },
      {
        "uri": "https://www.pathwren.workers.dev/mcp/triage",
        "description": "THE SAME AGENT ON THE OTHER PROTOCOL. Every skill on this card is also a tool on an MCP (Model Context Protocol) server at https://www.pathwren.workers.dev/mcp/triage \u2014 same name, same arguments, same answer, because one function answers both doors and a deploy that let them drift is refused. JSON-RPC 2.0 over a single HTTP POST: no session to open, no SSE stream to hold, no key, no signup, no quota. If your runtime speaks MCP rather than A2A, add that URL as a server and you have everything on this card without writing an A2A client. `params.initialize` and `params.callATool` are COMPLETE request bodies \u2014 POST either one unedited and it answers; `params.curl` is the same thing as one line. The tool named `example` takes no arguments at all and runs this server's own worked example end to end, so the first call needs nothing you do not already have.",
        "required": false,
        "params": {
          "protocol": "MCP (Model Context Protocol)",
          "endpoint": "https://www.pathwren.workers.dev/mcp/triage",
          "transport": "streamable-http (JSON-RPC 2.0 in one HTTP POST; the response is JSON, not a stream)",
          "protocolVersions": [
            "2025-06-18"
          ],
          "authentication": "none",
          "a2aTwin": "https://www.pathwren.workers.dev/a2a/triage",
          "toolNamesEqualSkillIds": true,
          "sameImplementation": "Each skill on this card and the tool of the same name on that server are answered by one function; the deploy gate compares them skill by skill.",
          "initialize": {
            "jsonrpc": "2.0",
            "id": 1,
            "method": "initialize",
            "params": {
              "protocolVersion": "2025-06-18",
              "capabilities": {},
              "clientInfo": {
                "name": "example-client",
                "version": "1.0.0"
              }
            }
          },
          "callATool": {
            "jsonrpc": "2.0",
            "id": 2,
            "method": "tools/call",
            "params": {
              "name": "example",
              "arguments": {}
            }
          },
          "curl": "curl -s https://www.pathwren.workers.dev/mcp/triage -H 'content-type: application/json' -d '{\"jsonrpc\":\"2.0\",\"id\":2,\"method\":\"tools/call\",\"params\":{\"name\":\"example\",\"arguments\":{}}}'",
          "everyToolAsABody": "https://www.pathwren.workers.dev/tools/",
          "discovery": "https://www.pathwren.workers.dev/.well-known/mcp.json"
        }
      }
    ]
  },
  "defaultInputModes": [
    "application/json",
    "text/plain"
  ],
  "defaultOutputModes": [
    "application/json",
    "text/plain"
  ],
  "skills": [
    {
      "id": "no_arguments_triage_this_hosts_own_crawler_log",
      "name": "Triage this host's own published crawler log (no arguments)",
      "description": "{\"jsonrpc\":\"2.0\",\"id\":1,\"method\":\"message/send\",\"params\":{\"message\":{\"role\":\"ROLE_USER\",\"messageId\":\"1\",\"parts\":[{\"text\":\"{\\\"skill\\\":\\\"no_arguments_triage_this_hosts_own_crawler_log\\\"}\"}]}}} \u2014 POST that exact body to https://www.pathwren.workers.dev/a2a/triage with content-type: application/json and you are done; it comes back as a Task already in state `completed` in the same response, so there is nothing to poll. Free, read-only, no API key, no account, no consent prompt, nothing to install and nothing for you to invent. TAKES NO ARGUMENTS. The triage this server runs on an access log you paste, run instead on the request log THIS host already publishes: the same parser, the same crawler index and the same operator-prefix verification, rolled up by operator, by category and by crawler, with the share that matches no index entry at all named separately and the browser-shaped strings kept apart from the crawlers. The input schema is literally empty \u2014 `arguments: {}` and no arguments key at all both work. No key, no account, no OAuth, read-only. Nothing is fetched to build it: no request leaves this edge and none is made to you. Example: arguments={} returns the rollup, the log it built and the lines it could not identify.",
      "tags": [
        "no arguments",
        "logs",
        "triage",
        "self"
      ],
      "examples": [
        "{\"jsonrpc\":\"2.0\",\"id\":1,\"method\":\"message/send\",\"params\":{\"message\":{\"role\":\"ROLE_USER\",\"messageId\":\"1\",\"parts\":[{\"text\":\"{\\\"skill\\\":\\\"no_arguments_triage_this_hosts_own_crawler_log\\\"}\"}]}}}",
        "{\"skill\":\"no_arguments_triage_this_hosts_own_crawler_log\"}",
        "triage your own crawler log"
      ],
      "inputModes": [
        "application/json",
        "text/plain"
      ],
      "outputModes": [
        "application/json",
        "text/plain"
      ]
    },
    {
      "id": "triage_my_request",
      "name": "Triage my own request (no arguments)",
      "description": "{\"jsonrpc\":\"2.0\",\"id\":1,\"method\":\"message/send\",\"params\":{\"message\":{\"role\":\"ROLE_USER\",\"messageId\":\"1\",\"parts\":[{\"text\":\"{\\\"skill\\\":\\\"triage_my_request\\\"}\"}]}}} \u2014 POST that exact body to https://www.pathwren.workers.dev/a2a/triage with content-type: application/json and you are done; it comes back as a Task already in state `completed` in the same response, so there is nothing to poll. Free, read-only, no API key, no account, no consent prompt, nothing to install and nothing for you to invent. Takes no arguments. Safe to call. Deterministic. Touches no third party. THE CALL TO MAKE FIRST on this server. Builds one access-log line out of the request you just sent and runs it through triage_log itself: the crawler this host's index identifies from your user-agent, its operator and category, and whether your address verifies against that operator's published prefixes \u2014 the same row you would get for a whole pasted file. No key, no account, no OAuth, read-only, nothing to invent. Example: arguments={} returns the line we built, its triage row and the rollup.",
      "tags": [
        "no arguments",
        "logs",
        "identify",
        "triage"
      ],
      "examples": [
        "{\"jsonrpc\":\"2.0\",\"id\":1,\"method\":\"message/send\",\"params\":{\"message\":{\"role\":\"ROLE_USER\",\"messageId\":\"1\",\"parts\":[{\"text\":\"{\\\"skill\\\":\\\"triage_my_request\\\"}\"}]}}}",
        "{\"skill\":\"triage_my_request\"}",
        "triage my request"
      ],
      "inputModes": [
        "application/json",
        "text/plain"
      ],
      "outputModes": [
        "application/json",
        "text/plain"
      ]
    },
    {
      "id": "triage_log",
      "name": "Triage a paste of log lines",
      "description": "{\"jsonrpc\":\"2.0\",\"id\":1,\"method\":\"message/send\",\"params\":{\"message\":{\"role\":\"ROLE_USER\",\"messageId\":\"1\",\"parts\":[{\"text\":\"{\\\"skill\\\":\\\"triage_log\\\",\\\"log\\\":\\\"66.249.66.1 - - [01/Sep/2026:06:12:44 +0000] \\\\\\\"GET /pricing HTTP/1.1\\\\\\\" 200 5120 \\\\\\\"-\\\\\\\" \\\\\\\"Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)\\\\\\\"\\\\n20.171.206.5 - - [01/Sep/2026:06:12:45 +0000] \\\\\\\"GET /docs HTTP/1.1\\\\\\\" 200 1234 \\\\\\\"-\\\\\\\" \\\\\\\"Mozilla/5.0 (compatible; GPTBot/1.2; +https://openai.com/gptbot)\\\\\\\"\\\",\\\"detail\\\":\\\"summary\\\"}\"}]}}} \u2014 POST that exact body to https://www.pathwren.workers.dev/a2a/triage with content-type: application/json and you are done; it comes back as a Task already in state `completed` in the same response, so there is nothing to poll. Free, read-only, no API key, no account, no consent prompt, nothing to install and nothing for you to invent. Paste log lines \u2014 combined, JSON, `uniq -c`, `<ip> <ua>` or bare user-agents, auto-detected \u2014 for per-line crawler, operator, purpose and cost of blocking, a rollup by operator and category, and every line whose address contradicts its claim. Log text, never a URL. Example: log='66.249.66.1 Googlebot/2.1' returns Googlebot, Google, search, verified.",
      "tags": [
        "logs",
        "crawlers",
        "classification",
        "triage"
      ],
      "examples": [
        "{\"jsonrpc\":\"2.0\",\"id\":1,\"method\":\"message/send\",\"params\":{\"message\":{\"role\":\"ROLE_USER\",\"messageId\":\"1\",\"parts\":[{\"text\":\"{\\\"skill\\\":\\\"triage_log\\\",\\\"log\\\":\\\"66.249.66.1 - - [01/Sep/2026:06:12:44 +0000] \\\\\\\"GET /pricing HTTP/1.1\\\\\\\" 200 5120 \\\\\\\"-\\\\\\\" \\\\\\\"Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)\\\\\\\"\\\\n20.171.206.5 - - [01/Sep/2026:06:12:45 +0000] \\\\\\\"GET /docs HTTP/1.1\\\\\\\" 200 1234 \\\\\\\"-\\\\\\\" \\\\\\\"Mozilla/5.0 (compatible; GPTBot/1.2; +https://openai.com/gptbot)\\\\\\\"\\\",\\\"detail\\\":\\\"summary\\\"}\"}]}}}",
        "{\"skill\":\"triage_log\",\"log\":\"66.249.66.1 - - [01/Sep/2026:06:12:44 +0000] \\\"GET /pricing HTTP/1.1\\\" 200 5120 \\\"-\\\" \\\"Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)\\\"\\n20.171.206.5 - - [01/Sep/2026:06:12:45 +0000] \\\"GET /docs HTTP/1.1\\\" 200 1234 \\\"-\\\" \\\"Mozilla/5.0 (compatible; GPTBot/1.2; +https://openai.com/gptbot)\\\"\",\"detail\":\"summary\"}",
        "66.249.66.1 - - [01/Sep/2026:06:12:44 +0000] \"GET /pricing HTTP/1.1\" 200 5120 \"-\" \"Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)\"\n20.171.206.5 - - [01/Sep/2026:06:12:45 +0000] \"GET /docs HTTP/1.1\" 200 1234 \"-\" \"Mozilla/5.0 (compatible; GPTBot/1.2; +https://openai.com/gptbot)\""
      ],
      "inputModes": [
        "application/json",
        "text/plain"
      ],
      "outputModes": [
        "application/json",
        "text/plain"
      ]
    },
    {
      "id": "find_impersonators",
      "name": "Find the lines that are lying",
      "description": "{\"jsonrpc\":\"2.0\",\"id\":1,\"method\":\"message/send\",\"params\":{\"message\":{\"role\":\"ROLE_USER\",\"messageId\":\"1\",\"parts\":[{\"text\":\"{\\\"skill\\\":\\\"find_impersonators\\\",\\\"log\\\":\\\"66.249.66.1 - - [01/Sep/2026:06:12:44 +0000] \\\\\\\"GET /pricing HTTP/1.1\\\\\\\" 200 5120 \\\\\\\"-\\\\\\\" \\\\\\\"Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)\\\\\\\"\\\\n20.171.206.5 - - [01/Sep/2026:06:12:45 +0000] \\\\\\\"GET /docs HTTP/1.1\\\\\\\" 200 1234 \\\\\\\"-\\\\\\\" \\\\\\\"Mozilla/5.0 (compatible; GPTBot/1.2; +https://openai.com/gptbot)\\\\\\\"\\\"}\"}]}}} \u2014 POST that exact body to https://www.pathwren.workers.dev/a2a/triage with content-type: application/json and you are done; it comes back as a Task already in state `completed` in the same response, so there is nothing to poll. Free, read-only, no API key, no account, no consent prompt, nothing to install and nothing for you to invent. Only the lines claiming a crawler whose operator publishes address ranges, from an address in none of to run: this server makes no outbound request. Example: log='203.0.113.9 Googlebot/2.1' returns one impersonation.",
      "tags": [
        "logs",
        "spoofing",
        "security",
        "verification"
      ],
      "examples": [
        "{\"jsonrpc\":\"2.0\",\"id\":1,\"method\":\"message/send\",\"params\":{\"message\":{\"role\":\"ROLE_USER\",\"messageId\":\"1\",\"parts\":[{\"text\":\"{\\\"skill\\\":\\\"find_impersonators\\\",\\\"log\\\":\\\"66.249.66.1 - - [01/Sep/2026:06:12:44 +0000] \\\\\\\"GET /pricing HTTP/1.1\\\\\\\" 200 5120 \\\\\\\"-\\\\\\\" \\\\\\\"Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)\\\\\\\"\\\\n20.171.206.5 - - [01/Sep/2026:06:12:45 +0000] \\\\\\\"GET /docs HTTP/1.1\\\\\\\" 200 1234 \\\\\\\"-\\\\\\\" \\\\\\\"Mozilla/5.0 (compatible; GPTBot/1.2; +https://openai.com/gptbot)\\\\\\\"\\\"}\"}]}}}",
        "{\"skill\":\"find_impersonators\",\"log\":\"66.249.66.1 - - [01/Sep/2026:06:12:44 +0000] \\\"GET /pricing HTTP/1.1\\\" 200 5120 \\\"-\\\" \\\"Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)\\\"\\n20.171.206.5 - - [01/Sep/2026:06:12:45 +0000] \\\"GET /docs HTTP/1.1\\\" 200 1234 \\\"-\\\" \\\"Mozilla/5.0 (compatible; GPTBot/1.2; +https://openai.com/gptbot)\\\"\"}"
      ],
      "inputModes": [
        "application/json",
        "text/plain"
      ],
      "outputModes": [
        "application/json",
        "text/plain"
      ]
    },
    {
      "id": "summarize_by_operator",
      "name": "Roll a log up by operator and category",
      "description": "{\"jsonrpc\":\"2.0\",\"id\":1,\"method\":\"message/send\",\"params\":{\"message\":{\"role\":\"ROLE_USER\",\"messageId\":\"1\",\"parts\":[{\"text\":\"{\\\"skill\\\":\\\"summarize_by_operator\\\",\\\"log\\\":\\\"66.249.66.1 - - [01/Sep/2026:06:12:44 +0000] \\\\\\\"GET /pricing HTTP/1.1\\\\\\\" 200 5120 \\\\\\\"-\\\\\\\" \\\\\\\"Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)\\\\\\\"\\\\n20.171.206.5 - - [01/Sep/2026:06:12:45 +0000] \\\\\\\"GET /docs HTTP/1.1\\\\\\\" 200 1234 \\\\\\\"-\\\\\\\" \\\\\\\"Mozilla/5.0 (compatible; GPTBot/1.2; +https://openai.com/gptbot)\\\\\\\"\\\"}\"}]}}} \u2014 POST that exact body to https://www.pathwren.workers.dev/a2a/triage with content-type: application/json and you are done; it comes back as a Task already in state `completed` in the same response, so there is nothing to poll. Free, read-only, no API key, no account, no consent prompt, nothing to install and nothing for you to invent. Aggregate only: who crawled you, how many requests each, what share, which category, and what blocking each would cost. Eats a `uniq -c` table straight from a shell pipeline. Example: log='412 GPTBot/1.2' returns OpenAI, 412 requests, 100%, ai-training.",
      "tags": [
        "logs",
        "reporting",
        "operators",
        "summary"
      ],
      "examples": [
        "{\"jsonrpc\":\"2.0\",\"id\":1,\"method\":\"message/send\",\"params\":{\"message\":{\"role\":\"ROLE_USER\",\"messageId\":\"1\",\"parts\":[{\"text\":\"{\\\"skill\\\":\\\"summarize_by_operator\\\",\\\"log\\\":\\\"66.249.66.1 - - [01/Sep/2026:06:12:44 +0000] \\\\\\\"GET /pricing HTTP/1.1\\\\\\\" 200 5120 \\\\\\\"-\\\\\\\" \\\\\\\"Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)\\\\\\\"\\\\n20.171.206.5 - - [01/Sep/2026:06:12:45 +0000] \\\\\\\"GET /docs HTTP/1.1\\\\\\\" 200 1234 \\\\\\\"-\\\\\\\" \\\\\\\"Mozilla/5.0 (compatible; GPTBot/1.2; +https://openai.com/gptbot)\\\\\\\"\\\"}\"}]}}}",
        "{\"skill\":\"summarize_by_operator\",\"log\":\"66.249.66.1 - - [01/Sep/2026:06:12:44 +0000] \\\"GET /pricing HTTP/1.1\\\" 200 5120 \\\"-\\\" \\\"Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)\\\"\\n20.171.206.5 - - [01/Sep/2026:06:12:45 +0000] \\\"GET /docs HTTP/1.1\\\" 200 1234 \\\"-\\\" \\\"Mozilla/5.0 (compatible; GPTBot/1.2; +https://openai.com/gptbot)\\\"\"}"
      ],
      "inputModes": [
        "application/json",
        "text/plain"
      ],
      "outputModes": [
        "application/json",
        "text/plain"
      ]
    },
    {
      "id": "robots_from_log",
      "name": "robots.txt from a log",
      "description": "{\"jsonrpc\":\"2.0\",\"id\":1,\"method\":\"message/send\",\"params\":{\"message\":{\"role\":\"ROLE_USER\",\"messageId\":\"1\",\"parts\":[{\"text\":\"{\\\"skill\\\":\\\"robots_from_log\\\",\\\"log\\\":\\\"66.249.66.1 - - [01/Sep/2026:06:12:44 +0000] \\\\\\\"GET /pricing HTTP/1.1\\\\\\\" 200 5120 \\\\\\\"-\\\\\\\" \\\\\\\"Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)\\\\\\\"\\\\n20.171.206.5 - - [01/Sep/2026:06:12:45 +0000] \\\\\\\"GET /docs HTTP/1.1\\\\\\\" 200 1234 \\\\\\\"-\\\\\\\" \\\\\\\"Mozilla/5.0 (compatible; GPTBot/1.2; +https://openai.com/gptbot)\\\\\\\"\\\",\\\"stance\\\":\\\"block-ai-training\\\"}\"}]}}} \u2014 POST that exact body to https://www.pathwren.workers.dev/a2a/triage with content-type: application/json and you are done; it comes back as a Task already in state `completed` in the same response, so there is nothing to poll. Free, read-only, no API key, no account, no consent prompt, nothing to install and nothing for you to invent. A robots.txt naming only the crawlers in your log, each with its request count and cost of blocking, plus a warning for any that do not documentably obey it \u2014 there the file is a request, not enforcement. Example: log='412 GPTBot/1.2', stance='block-ai-training' blocks GPTBot only.",
      "tags": [
        "logs",
        "robots.txt",
        "policy",
        "generator"
      ],
      "examples": [
        "{\"jsonrpc\":\"2.0\",\"id\":1,\"method\":\"message/send\",\"params\":{\"message\":{\"role\":\"ROLE_USER\",\"messageId\":\"1\",\"parts\":[{\"text\":\"{\\\"skill\\\":\\\"robots_from_log\\\",\\\"log\\\":\\\"66.249.66.1 - - [01/Sep/2026:06:12:44 +0000] \\\\\\\"GET /pricing HTTP/1.1\\\\\\\" 200 5120 \\\\\\\"-\\\\\\\" \\\\\\\"Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)\\\\\\\"\\\\n20.171.206.5 - - [01/Sep/2026:06:12:45 +0000] \\\\\\\"GET /docs HTTP/1.1\\\\\\\" 200 1234 \\\\\\\"-\\\\\\\" \\\\\\\"Mozilla/5.0 (compatible; GPTBot/1.2; +https://openai.com/gptbot)\\\\\\\"\\\",\\\"stance\\\":\\\"block-ai-training\\\"}\"}]}}}",
        "{\"skill\":\"robots_from_log\",\"log\":\"66.249.66.1 - - [01/Sep/2026:06:12:44 +0000] \\\"GET /pricing HTTP/1.1\\\" 200 5120 \\\"-\\\" \\\"Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)\\\"\\n20.171.206.5 - - [01/Sep/2026:06:12:45 +0000] \\\"GET /docs HTTP/1.1\\\" 200 1234 \\\"-\\\" \\\"Mozilla/5.0 (compatible; GPTBot/1.2; +https://openai.com/gptbot)\\\"\",\"stance\":\"block-ai-training\"}"
      ],
      "inputModes": [
        "application/json",
        "text/plain"
      ],
      "outputModes": [
        "application/json",
        "text/plain"
      ]
    },
    {
      "id": "waf_ruleset_from_log",
      "name": "WAF ruleset from a log",
      "description": "{\"jsonrpc\":\"2.0\",\"id\":1,\"method\":\"message/send\",\"params\":{\"message\":{\"role\":\"ROLE_USER\",\"messageId\":\"1\",\"parts\":[{\"text\":\"{\\\"skill\\\":\\\"waf_ruleset_from_log\\\",\\\"log\\\":\\\"66.249.66.1 - - [01/Sep/2026:06:12:44 +0000] \\\\\\\"GET /pricing HTTP/1.1\\\\\\\" 200 5120 \\\\\\\"-\\\\\\\" \\\\\\\"Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)\\\\\\\"\\\\n20.171.206.5 - - [01/Sep/2026:06:12:45 +0000] \\\\\\\"GET /docs HTTP/1.1\\\\\\\" 200 1234 \\\\\\\"-\\\\\\\" \\\\\\\"Mozilla/5.0 (compatible; GPTBot/1.2; +https://openai.com/gptbot)\\\\\\\"\\\",\\\"target\\\":\\\"nginx\\\",\\\"action\\\":\\\"block\\\"}\"}]}}} \u2014 POST that exact body to https://www.pathwren.workers.dev/a2a/triage with content-type: application/json and you are done; it comes back as a Task already in state `completed` in the same response, so there is nothing to poll. Free, read-only, no API key, no account, no consent prompt, nothing to install and nothing for you to invent. nginx, Caddy, Cloudflare, HAProxy or Apache rules for only the crawlers in your log. The reply warns that a UA rule stops only an honest client, and that impersonation is an address problem needing the published prefixes as an allowlist. Example: log='412 GPTBot/1.2', target='nginx', scope='ai-training'.",
      "tags": [
        "logs",
        "waf",
        "nginx",
        "cloudflare"
      ],
      "examples": [
        "{\"jsonrpc\":\"2.0\",\"id\":1,\"method\":\"message/send\",\"params\":{\"message\":{\"role\":\"ROLE_USER\",\"messageId\":\"1\",\"parts\":[{\"text\":\"{\\\"skill\\\":\\\"waf_ruleset_from_log\\\",\\\"log\\\":\\\"66.249.66.1 - - [01/Sep/2026:06:12:44 +0000] \\\\\\\"GET /pricing HTTP/1.1\\\\\\\" 200 5120 \\\\\\\"-\\\\\\\" \\\\\\\"Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)\\\\\\\"\\\\n20.171.206.5 - - [01/Sep/2026:06:12:45 +0000] \\\\\\\"GET /docs HTTP/1.1\\\\\\\" 200 1234 \\\\\\\"-\\\\\\\" \\\\\\\"Mozilla/5.0 (compatible; GPTBot/1.2; +https://openai.com/gptbot)\\\\\\\"\\\",\\\"target\\\":\\\"nginx\\\",\\\"action\\\":\\\"block\\\"}\"}]}}}",
        "{\"skill\":\"waf_ruleset_from_log\",\"log\":\"66.249.66.1 - - [01/Sep/2026:06:12:44 +0000] \\\"GET /pricing HTTP/1.1\\\" 200 5120 \\\"-\\\" \\\"Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)\\\"\\n20.171.206.5 - - [01/Sep/2026:06:12:45 +0000] \\\"GET /docs HTTP/1.1\\\" 200 1234 \\\"-\\\" \\\"Mozilla/5.0 (compatible; GPTBot/1.2; +https://openai.com/gptbot)\\\"\",\"target\":\"nginx\",\"action\":\"block\"}"
      ],
      "inputModes": [
        "application/json",
        "text/plain"
      ],
      "outputModes": [
        "application/json",
        "text/plain"
      ]
    },
    {
      "id": "whoami",
      "name": "Who is calling? (no arguments)",
      "description": "{\"jsonrpc\":\"2.0\",\"id\":1,\"method\":\"message/send\",\"params\":{\"message\":{\"role\":\"ROLE_USER\",\"messageId\":\"1\",\"parts\":[{\"text\":\"{\\\"skill\\\":\\\"whoami\\\"}\"}]}}} \u2014 POST that exact body to https://www.pathwren.workers.dev/a2a/triage with content-type: application/json and you are done; it comes back as a Task already in state `completed` in the same response, so there is nothing to poll. THIS IS THE CALL TO MAKE FIRST, before any skill that takes arguments: it needs NO ARGUMENTS AT ALL, no key and no account, so there is nothing to decide, nothing to look up and nothing to agree to before you send it. Free, read-only, no API key, no account, no consent prompt, nothing to install and nothing for you to invent. The answer is about YOU, the caller: the address this request arrived from, the user-agent you sent, the lane you came in on (`metadata.arrivedOn` on the task you get back names the protocol, the endpoint and the A2A version you spoke), the class this host's own instrument books you as, and whether it has seen you here before. Nothing is fetched to answer it and no argument exists to invent \u2014 it is the one question you can ask a stranger's agent while holding nothing of your own. Takes no arguments. Safe to call. Deterministic. Touches no third party. Classifies the request you just sent: the user-agent you claim, the address you came from, the class this host's own instrument books you as, whether we have seen you here before and what you fetched, and what this host's robots policy says about you. Every fact comes from the headers on your own request or from a file this host already publishes \u2014 nothing is fetched, nothing about you is invented, no argument exists. Example: arguments={} returns your user-agent, your address, the class we book you as and whether we have seen you here before.",
      "tags": [
        "identify",
        "no arguments",
        "diagnostics",
        "user-agent"
      ],
      "examples": [
        "{\"jsonrpc\":\"2.0\",\"id\":1,\"method\":\"message/send\",\"params\":{\"message\":{\"role\":\"ROLE_USER\",\"messageId\":\"1\",\"parts\":[{\"text\":\"{\\\"skill\\\":\\\"whoami\\\"}\"}]}}}",
        "{\"skill\":\"whoami\"}",
        "whoami",
        "who am i to you"
      ],
      "inputModes": [
        "application/json",
        "text/plain"
      ],
      "outputModes": [
        "application/json",
        "text/plain"
      ]
    },
    {
      "id": "example",
      "name": "Run this server's worked example (no arguments)",
      "description": "{\"jsonrpc\":\"2.0\",\"id\":1,\"method\":\"message/send\",\"params\":{\"message\":{\"role\":\"ROLE_USER\",\"messageId\":\"1\",\"parts\":[{\"text\":\"{\\\"skill\\\":\\\"example\\\"}\"}]}}} \u2014 POST that exact body to https://www.pathwren.workers.dev/a2a/triage with content-type: application/json and you are done; it comes back as a Task already in state `completed` in the same response, so there is nothing to poll. THIS IS THE CALL TO MAKE FIRST, before any skill that takes arguments: it needs NO ARGUMENTS AT ALL, no key and no account, so there is nothing to decide, nothing to look up and nothing to agree to before you send it. Free, read-only, no API key, no account, no consent prompt, nothing to install and nothing for you to invent. Takes no arguments. Safe to call. Deterministic. Touches no third party. Runs this server's own worked example end to end \u2014 one of its real tools, on a canned input taken from this host's own published data \u2014 and returns exactly the structuredContent a real call returns, not a mock and not a description of one. Use it to see the shape of an answer before you decide what to send. No URL of yours is fetched and no third party is touched. Example: arguments={} runs it and returns the real answer.",
      "tags": [
        "example",
        "no arguments",
        "demo",
        "getting started"
      ],
      "examples": [
        "{\"jsonrpc\":\"2.0\",\"id\":1,\"method\":\"message/send\",\"params\":{\"message\":{\"role\":\"ROLE_USER\",\"messageId\":\"1\",\"parts\":[{\"text\":\"{\\\"skill\\\":\\\"example\\\"}\"}]}}}",
        "{\"skill\":\"example\"}",
        "example",
        "show me a worked example"
      ],
      "inputModes": [
        "application/json",
        "text/plain"
      ],
      "outputModes": [
        "application/json",
        "text/plain"
      ]
    }
  ],
  "changed_at": "2026-09-06T09:39:21+00:00",
  "recent_changes": [
    "2026-09-06T09:39Z - changed: skills 8->9; 26325->28339 bytes",
    "2026-09-05T15:46Z - changed: skills; 25889->26325 bytes",
    "2026-09-05T14:51Z - changed: skills; 25944->25889 bytes"
  ]
}