{
 "schema_version": "gaip.watched-agents.v1",
 "title": "Public agents GAIP watches",
 "notice": "The public MCP servers and A2A agents GAIP's Agent Observatory watches, with their names and identifiers exactly as the public registries list them: facts as listed by those registries, not an assessment, result, score or ranking of any party, and no observation of any of them.",
 "licence": "Not covered by CC BY 4.0 (which covers GAIP's aggregate figures only): the names and identifiers are as listed by public registries; GAIP's terms of use apply (https://www.gaipagents.com/terms).",
 "opt_out": "An operator can opt out through https://www.gaipagents.com/corrections (machine route: POST https://www.gaipagents.com/v1/free/observatory/corrections); an opted-out or excluded agent is left out of the list from its next build, at the latest the next day.",
 "left_out": "Left out: agents on GAIP's exclusion list or on a host paused by an opt-out, agents retired from their registry, agents that did not come from a public registry (hosts callers asked about, cards a caller published or captured) and GAIP's own agents.",
 "privacy": "A registry name can contain a person's name or handle (for example a GitHub username in an MCP server name); see https://www.gaipagents.com/privacy#watched-agents.",
 "built_at_utc": "2026-10-04T00:11:26Z",
 "rebuilt": "Daily (UTC) at the Observatory tick, and after any opt-out.",
 "fields": [
  {
   "name": "target_id",
   "type": "string",
   "description": "GAIP's id of the watched agent (obs_ + 24 hex characters)."
  },
  {
   "name": "source_registry",
   "type": "string",
   "description": "The public registry that lists it: official-mcp-registry or a2aregistry-org."
  },
  {
   "name": "registry_name",
   "type": "string",
   "description": "The name as that registry lists it (the Official MCP Registry's title; empty when the registry gives none, and for the A2A Registry, from which GAIP keeps no name)."
  },
  {
   "name": "registry_identifier",
   "type": "string",
   "description": "The identifier as that registry lists it: the Official MCP Registry's server name (e.g. io.github.owner/server) or, for the A2A Registry, the URL of the agent card it lists (wellKnownURI)."
  },
  {
   "name": "kind",
   "type": "string",
   "description": "MCP_REMOTE (a remote MCP server) or A2A_CARD (an A2A agent card)."
  },
  {
   "name": "cohorts",
   "type": "array",
   "description": "Cohort memberships: AGENTS-COHORT-2026-10 (the reference panel), AGENTS-COHORT-YYYYQn (first watched in that quarter) and AGENTS-SAMPLE-YYYYQn (that quarter's random sample). JSON text in the CSV."
  },
  {
   "name": "first_watched_date",
   "type": "string",
   "description": "The date (UTC, YYYY-MM-DD) GAIP first watched it."
  }
 ],
 "registries": {
  "official-mcp-registry": "Official MCP Registry (registry.modelcontextprotocol.io)",
  "a2aregistry-org": "A2A Registry (a2aregistry.org)",
  "global-a2a-registry": "Global A2A Registry (a2a-registry.org)"
 },
 "agents_listed": 12525,
 "agents_left_out": 55,
 "left_out_by_reason": {
  "not_from_a_public_registry": 36,
  "retired_from_registry": 19
 },
 "files": {
  "watched-agents.csv": {
   "url": "https://www.gaipagents.com/data/watched-agents.csv",
   "sha256": "e273a9060aa800143d8222d5c6bacfe49f1b55ed264d675d81de2a2e4023783f",
   "bytes": 1853401,
   "rows": 12525
  },
  "watched-agents.jsonl": {
   "url": "https://www.gaipagents.com/data/watched-agents.jsonl",
   "sha256": "aef79b270d44d5d4c0e746b70eda0abc7c10edc897c613a67a5e33d0139f088d",
   "bytes": 3313163,
   "rows": 12525
  }
 },
 "verification": {
  "panel": {
   "id": "AGENTS-COHORT-2026-10",
   "registered_membership_sha256": "2233a448bbd86b8bad7ba29f7cf1532f7dca5bfbe5e851e72d976e4ef7dcb5b5",
   "registered_size": 4157,
   "listed_members": 4105,
   "withheld_members": 52,
   "withheld_by_reason": {
    "not_from_a_public_registry": 34,
    "retired_from_registry": 18
   },
   "listed_members_sha256": "f700a97b359a739a2cf978f183bc74652048ad866a0a716d14c94b6b26a92e92",
   "rule": "SHA-256 of the panel's target ids, sorted and joined by newlines (no trailing newline).",
   "recomputes_from_list": false,
   "why_not": "52 panel member(s) are left out of the list (opted out or excluded, retired from their registry, not from a public registry, or GAIP's own), so the registered hash cannot be recomputed from the published list alone. The panel never changes: the listed members plus the withheld ones make up the registered size, and listed_members_sha256 is the hash of the listed members."
  },
  "quarterly_samples": [
   {
    "id": "AGENTS-SAMPLE-2026Q4",
    "quarter": "2026-Q4",
    "seed_sha256": "1dedbd9feb2294ab0830be9fcd257b2655b6558cf1b6481947079cb7ead6f315",
    "seed_rule": "SHA-256 of the quarter label",
    "drawn_at_utc": "2026-10-01T16:41:20Z",
    "size": 200,
    "members_sha256": "caa959a42f6e90ad835db22203a4974157588488b159105ece83cd9cb176c1c6",
    "population_at_draw": 3627,
    "population_sha256": "699cc43f12de8a71a4b35f200e4740545fe9e4e36207d412ef9931fcafa70265",
    "listed_members": 200,
    "withheld_members": 0,
    "listed_members_sha256": "caa959a42f6e90ad835db22203a4974157588488b159105ece83cd9cb176c1c6",
    "recomputes_from_list": true,
    "listed_population_first_watched_by_draw_date": 5902,
    "listed_non_members_ranked_inside_the_sample": 91,
    "rule": "Rank each target id by SHA-256(seed + ':' + target_id) (hex) and take the lowest `size` of the population (Official MCP Registry MCP servers, active and not withdrawn, at the draw). A listed non-member first watched by the draw date and ranked below the highest-ranked member was not in the population at the draw (for example not active in the registry then)."
   }
  ],
  "how": "import csv, hashlib, json\nwith open(\"watched-agents.csv\", encoding=\"utf-8\", newline=\"\") as handle:\n    rows = list(csv.DictReader(handle))\ndef membership_sha256(ids):           # sorted target ids joined by newlines\n    return hashlib.sha256(\"\\n\".join(sorted(ids)).encode(\"utf-8\")).hexdigest()\npanel = [r[\"target_id\"] for r in rows if \"AGENTS-COHORT-2026-10\" in json.loads(r[\"cohorts\"])]\nprint(len(panel), membership_sha256(panel))   # compare with /v1/free/data/releases (and withheld_members)\nquarter = \"2026-Q4\"; seed = hashlib.sha256(quarter.encode(\"utf-8\")).hexdigest()\nrank = lambda i: hashlib.sha256(f\"{seed}:{i}\".encode(\"utf-8\")).hexdigest()\nsample = sorted(r[\"target_id\"] for r in rows if \"AGENTS-SAMPLE-2026Q4\" in json.loads(r[\"cohorts\"]))\nprint(membership_sha256(sample), max(map(rank, sample)) if sample else None)\n",
  "method": "https://www.gaipagents.com/methodology#watched-agents"
 },
 "decision": "Founder decision #23 (2 Oct 2026); legal risk register row 13.",
 "data_page": "https://www.gaipagents.com/data#watched-agents",
 "price_gbp": 0
}