{
 "when": "2026-10-16 22:48:03",
 "client": {
  "name": "Northline Industrial Supply",
  "legal": "Northline Industrial Supply, Inc.",
  "synthetic": true,
  "domain": "northline.example",
  "branches": [
   "Cleveland OH",
   "Green Bay WI",
   "Charlotte NC"
  ],
  "erp": "ERP export, nightly CSV, read-only",
  "price_source": "account price matrix exported from the ERP",
  "accounts": [
   {
    "id": "public",
    "label": "anonymous caller",
    "tier": "list",
    "multiplier": 1.0,
    "sees_stock": true
   },
   {
    "id": "acct-1042",
    "label": "Ridgeway Machine & Tool",
    "tier": "tier-2",
    "multiplier": 0.78,
    "sees_stock": true
   },
   {
    "id": "acct-2277",
    "label": "Bayline Fabrication",
    "tier": "tier-1",
    "multiplier": 0.71,
    "sees_stock": true
   },
   {
    "id": "acct-3305",
    "label": "Catawba Process Systems",
    "tier": "contract",
    "multiplier": 0.64,
    "sees_stock": true
   }
  ],
  "parts": 12
 },
 "before": {
  "domain": "dxpe.com",
  "company": "DXP Enterprises",
  "score": 5.1,
  "band": "partly readable",
  "scanned": "2026-10-16",
  "checks": [
   {
    "key": "machine_access",
    "name": "A non-browser client can read the site",
    "result": "pass",
    "detail": "HTTP 200 and readable content (441864 bytes) with no browser fingerprints",
    "weight": 3.0,
    "evidence": {
     "url": "https://dxpe.com/",
     "code": 200,
     "bytes": 441864
    }
   },
   {
    "key": "bot_rules",
    "name": "Rules for AI agents are published and permit them",
    "result": "warning",
    "detail": "robots.txt exists but never mentions an AI agent: 2 agents named, none of them AI",
    "weight": 2.0,
    "evidence": {
     "url": "https://dxpe.com/robots.txt",
     "code": 200,
     "bytes": 96
    }
   },
   {
    "key": "product_markup",
    "name": "Products are stated in machine terms",
    "result": "fail",
    "detail": "no Product markup on the 3 product pages we sampled from your sitemap: an agent reading your site cannot tell what you sell in machine terms",
    "weight": 2.0,
    "evidence": {}
   },
   {
    "key": "price_and_stock",
    "name": "Price and availability are machine-readable",
    "result": "fail",
    "detail": "neither price nor availability is machine-readable: a comparison agent has nothing to work with",
    "weight": 2.0,
    "evidence": {}
   },
   {
    "key": "catalogue_query",
    "name": "The catalogue can be queried, not only browsed",
    "result": "warning",
    "detail": "no public tool endpoint found (MCP or equivalent): the catalogue cannot be queried, only read as pages",
    "weight": 2.0,
    "evidence": {}
   },
   {
    "key": "discovery_map",
    "name": "There is a map of what you sell",
    "result": "pass",
    "detail": "/sitemap.xml lists 408 URLs, so product pages can be discovered",
    "weight": 1.0,
    "evidence": {}
   },
   {
    "key": "agent_description",
    "name": "A machine description of what may be requested",
    "result": "warning",
    "detail": "nothing at /agents.txt or /.well-known/ai.txt: a machine has no description of what it may ask for",
    "weight": 1.0,
    "evidence": {}
   },
   {
    "key": "llms_txt",
    "name": "llms.txt is present",
    "result": "warning",
    "detail": "llms.txt returns an HTML page, so it is a placeholder rather than a description",
    "weight": 0.5,
    "evidence": {
     "url": "https://dxpe.com/llms.txt",
     "code": 200,
     "bytes": 423079
    }
   },
   {
    "key": "agent_card",
    "name": "The site describes itself to other agents",
    "result": "warning",
    "detail": "no agent card: your site does not describe itself to another agent",
    "weight": 1.0,
    "evidence": {}
   },
   {
    "key": "api_surface",
    "name": "A callable API surface exists",
    "result": "warning",
    "detail": "/docs responds, but only with a human page, so an agent cannot call anything structured",
    "weight": 1.5,
    "evidence": {
     "url": "https://dxpe.com/docs",
     "code": 200,
     "bytes": 423079
    }
   },
   {
    "key": "authorisation",
    "name": "A way to authorise an agent is declared",
    "result": "pass",
    "detail": "/.well-known/oauth-authorization-server is present, so an agent has a defined way to be authorised",
    "weight": 0.5,
    "evidence": {
     "url": "https://dxpe.com/.well-known/oauth-authorization-server",
     "code": 200,
     "bytes": 539
    }
   },
   {
    "key": "machine_payment",
    "name": "Per-call payment is declared",
    "result": "warning",
    "detail": "no machine payment declaration (x402 or equivalent): an agent cannot pay per call",
    "weight": 0.5,
    "evidence": {}
   }
  ]
 },
 "after": {
  "address": "https://157-180-49-112.sslip.io:8099",
  "score": 10.0,
  "band": "agent-ready",
  "checks": [
   {
    "key": "machine_access",
    "name": "A non-browser client can read the site",
    "result": "pass",
    "detail": "HTTP 200 and readable content (3346 bytes) with no browser fingerprints",
    "weight": 3.0,
    "evidence": {
     "url": "https://157-180-49-112.sslip.io:8099/",
     "code": 200,
     "bytes": 3346
    }
   },
   {
    "key": "bot_rules",
    "name": "Rules for AI agents are published and permit them",
    "result": "pass",
    "detail": "robots.txt names AI agents and lets them in: Amazonbot, CCBot, ClaudeBot, GPTBot, Google-Extended, OAI-SearchBot",
    "weight": 2.0,
    "evidence": {
     "url": "https://157-180-49-112.sslip.io:8099/robots.txt",
     "code": 200,
     "bytes": 399
    }
   },
   {
    "key": "product_markup",
    "name": "Products are stated in machine terms",
    "result": "pass",
    "detail": "Product markup found on NL-ELC-CB-4MM, identifier present (NL-ELC-CB-4MM), price published (214.00)",
    "weight": 2.0,
    "evidence": {}
   },
   {
    "key": "price_and_stock",
    "name": "Price and availability are machine-readable",
    "result": "pass",
    "detail": "price and availability are both readable by a machine on the product page",
    "weight": 2.0,
    "evidence": {}
   },
   {
    "key": "catalogue_query",
    "name": "The catalogue can be queried, not only browsed",
    "result": "pass",
    "detail": "/.well-known/mcp.json publishes a tool interface a model can call",
    "weight": 2.0,
    "evidence": {
     "url": "https://157-180-49-112.sslip.io:8099/.well-known/mcp.json",
     "code": 200,
     "bytes": 1045
    }
   },
   {
    "key": "discovery_map",
    "name": "There is a map of what you sell",
    "result": "pass",
    "detail": "/sitemap.xml lists 15 URLs, so product pages can be discovered",
    "weight": 1.0,
    "evidence": {}
   },
   {
    "key": "agent_description",
    "name": "A machine description of what may be requested",
    "result": "pass",
    "detail": "/agents.txt describes the service to a machine (961 bytes)",
    "weight": 1.0,
    "evidence": {
     "url": "https://157-180-49-112.sslip.io:8099/agents.txt",
     "code": 200,
     "bytes": 961
    }
   },
   {
    "key": "llms_txt",
    "name": "llms.txt is present",
    "result": "pass",
    "detail": "llms.txt is present and contains real text (1146 bytes)",
    "weight": 0.5,
    "evidence": {
     "url": "https://157-180-49-112.sslip.io:8099/llms.txt",
     "code": 200,
     "bytes": 1146
    }
   },
   {
    "key": "agent_card",
    "name": "The site describes itself to other agents",
    "result": "pass",
    "detail": "/.well-known/agent-card.json declares the service to other agents",
    "weight": 1.0,
    "evidence": {
     "url": "https://157-180-49-112.sslip.io:8099/.well-known/agent-card.json",
     "code": 200,
     "bytes": 852
    }
   },
   {
    "key": "api_surface",
    "name": "A callable API surface exists",
    "result": "pass",
    "detail": "/openapi.json returns a machine-readable API description",
    "weight": 1.5,
    "evidence": {
     "url": "https://157-180-49-112.sslip.io:8099/openapi.json",
     "code": 200,
     "bytes": 1568
    }
   },
   {
    "key": "authorisation",
    "name": "A way to authorise an agent is declared",
    "result": "pass",
    "detail": "/.well-known/oauth-authorization-server is present, so an agent has a defined way to be authorised",
    "weight": 0.5,
    "evidence": {
     "url": "https://157-180-49-112.sslip.io:8099/.well-known/oauth-authorization-server",
     "code": 200,
     "bytes": 408
    }
   },
   {
    "key": "machine_payment",
    "name": "Per-call payment is declared",
    "result": "pass",
    "detail": "/.well-known/x402 declares machine payment support",
    "weight": 0.5,
    "evidence": {
     "url": "https://157-180-49-112.sslip.io:8099/.well-known/x402",
     "code": 200,
     "bytes": 385
    }
   }
  ]
 },
 "rows": [
  {
   "key": "machine_access",
   "name": "A non-browser client can read the site",
   "weight": 3.0,
   "result_after": "pass",
   "result_before": "pass",
   "before_detail": "HTTP 200 and readable content (441864 bytes) with no browser fingerprints",
   "after_detail": "HTTP 200 and readable content (3346 bytes) with no browser fingerprints",
   "evidence_after": {
    "url": "https://157-180-49-112.sslip.io:8099/",
    "code": 200,
    "bytes": 3346
   },
   "move": "held"
  },
  {
   "key": "bot_rules",
   "name": "Rules for AI agents are published and permit them",
   "weight": 2.0,
   "result_after": "pass",
   "result_before": "warning",
   "before_detail": "robots.txt exists but never mentions an AI agent: 2 agents named, none of them AI",
   "after_detail": "robots.txt names AI agents and lets them in: Amazonbot, CCBot, ClaudeBot, GPTBot, Google-Extended, OAI-SearchBot",
   "evidence_after": {
    "url": "https://157-180-49-112.sslip.io:8099/robots.txt",
    "code": 200,
    "bytes": 399
   },
   "move": "improved"
  },
  {
   "key": "product_markup",
   "name": "Products are stated in machine terms",
   "weight": 2.0,
   "result_after": "pass",
   "result_before": "fail",
   "before_detail": "no Product markup on the 3 product pages we sampled from your sitemap: an agent reading your site cannot tell what you sell in machine terms",
   "after_detail": "Product markup found on NL-ELC-CB-4MM, identifier present (NL-ELC-CB-4MM), price published (214.00)",
   "evidence_after": {},
   "move": "fixed"
  },
  {
   "key": "price_and_stock",
   "name": "Price and availability are machine-readable",
   "weight": 2.0,
   "result_after": "pass",
   "result_before": "fail",
   "before_detail": "neither price nor availability is machine-readable: a comparison agent has nothing to work with",
   "after_detail": "price and availability are both readable by a machine on the product page",
   "evidence_after": {},
   "move": "fixed"
  },
  {
   "key": "catalogue_query",
   "name": "The catalogue can be queried, not only browsed",
   "weight": 2.0,
   "result_after": "pass",
   "result_before": "warning",
   "before_detail": "no public tool endpoint found (MCP or equivalent): the catalogue cannot be queried, only read as pages",
   "after_detail": "/.well-known/mcp.json publishes a tool interface a model can call",
   "evidence_after": {
    "url": "https://157-180-49-112.sslip.io:8099/.well-known/mcp.json",
    "code": 200,
    "bytes": 1045
   },
   "move": "improved"
  },
  {
   "key": "discovery_map",
   "name": "There is a map of what you sell",
   "weight": 1.0,
   "result_after": "pass",
   "result_before": "pass",
   "before_detail": "/sitemap.xml lists 408 URLs, so product pages can be discovered",
   "after_detail": "/sitemap.xml lists 15 URLs, so product pages can be discovered",
   "evidence_after": {},
   "move": "held"
  },
  {
   "key": "agent_description",
   "name": "A machine description of what may be requested",
   "weight": 1.0,
   "result_after": "pass",
   "result_before": "warning",
   "before_detail": "nothing at /agents.txt or /.well-known/ai.txt: a machine has no description of what it may ask for",
   "after_detail": "/agents.txt describes the service to a machine (961 bytes)",
   "evidence_after": {
    "url": "https://157-180-49-112.sslip.io:8099/agents.txt",
    "code": 200,
    "bytes": 961
   },
   "move": "improved"
  },
  {
   "key": "llms_txt",
   "name": "llms.txt is present",
   "weight": 0.5,
   "result_after": "pass",
   "result_before": "warning",
   "before_detail": "llms.txt returns an HTML page, so it is a placeholder rather than a description",
   "after_detail": "llms.txt is present and contains real text (1146 bytes)",
   "evidence_after": {
    "url": "https://157-180-49-112.sslip.io:8099/llms.txt",
    "code": 200,
    "bytes": 1146
   },
   "move": "improved"
  },
  {
   "key": "agent_card",
   "name": "The site describes itself to other agents",
   "weight": 1.0,
   "result_after": "pass",
   "result_before": "warning",
   "before_detail": "no agent card: your site does not describe itself to another agent",
   "after_detail": "/.well-known/agent-card.json declares the service to other agents",
   "evidence_after": {
    "url": "https://157-180-49-112.sslip.io:8099/.well-known/agent-card.json",
    "code": 200,
    "bytes": 852
   },
   "move": "improved"
  },
  {
   "key": "api_surface",
   "name": "A callable API surface exists",
   "weight": 1.5,
   "result_after": "pass",
   "result_before": "warning",
   "before_detail": "/docs responds, but only with a human page, so an agent cannot call anything structured",
   "after_detail": "/openapi.json returns a machine-readable API description",
   "evidence_after": {
    "url": "https://157-180-49-112.sslip.io:8099/openapi.json",
    "code": 200,
    "bytes": 1568
   },
   "move": "improved"
  },
  {
   "key": "authorisation",
   "name": "A way to authorise an agent is declared",
   "weight": 0.5,
   "result_after": "pass",
   "result_before": "pass",
   "before_detail": "/.well-known/oauth-authorization-server is present, so an agent has a defined way to be authorised",
   "after_detail": "/.well-known/oauth-authorization-server is present, so an agent has a defined way to be authorised",
   "evidence_after": {
    "url": "https://157-180-49-112.sslip.io:8099/.well-known/oauth-authorization-server",
    "code": 200,
    "bytes": 408
   },
   "move": "held"
  },
  {
   "key": "machine_payment",
   "name": "Per-call payment is declared",
   "weight": 0.5,
   "result_after": "pass",
   "result_before": "warning",
   "before_detail": "no machine payment declaration (x402 or equivalent): an agent cannot pay per call",
   "after_detail": "/.well-known/x402 declares machine payment support",
   "evidence_after": {
    "url": "https://157-180-49-112.sslip.io:8099/.well-known/x402",
    "code": 200,
    "bytes": 385
   },
   "move": "improved"
  }
 ],
 "fixed": [
  "Products are stated in machine terms",
  "Price and availability are machine-readable"
 ],
 "improved": [
  "Rules for AI agents are published and permit them",
  "The catalogue can be queried, not only browsed",
  "A machine description of what may be requested",
  "llms.txt is present",
  "The site describes itself to other agents",
  "A callable API surface exists",
  "Per-call payment is declared"
 ],
 "counts": {
  "fixed": 2,
  "improved": 7,
  "before_score": 5.1,
  "after_score": 10.0
 },
 "agent_pass": [
  {
   "question": "Do you have the 6205-2RS bearing, and how many are on hand?",
   "request": "GET /api/catalog?q=6205",
   "status": 200,
   "answered": "1 match. First: Deep groove ball bearing 6205-2RS, 25mm bore, manufacturer number 6205-2RS, 580 on hand, list price 28.40 USD",
   "body": {
    "query": "6205",
    "count": 1,
    "results": [
     {
      "sku": "NL-BRG-6205-2RS",
      "mpn": "6205-2RS",
      "gtin13": "09506000134352",
      "brand": "Northline Bearings",
      "name": "Deep groove ball bearing 6205-2RS, 25mm bore",
      "category": "bearings",
      "description": "Sealed deep groove ball bearing, 25 mm bore, 52 mm outside diameter, 15 mm width. C3 clearance, nitrile seals, rated to 14,000 rpm. Interchangeable with the common 6205-2RS line.",
      "uom": "each",
      "list_price": 28.4,
      "currency": "USD",
      "available": true,
      "stock_total": 580,
      "lead_days": 1,
      "url": "/products/NL-BRG-6205-2RS"
     }
    ],
    "catalogue_size": 12
   }
  },
  {
   "question": "How many are at the Cleveland branch and what is the lead time?",
   "request": "GET /api/stock?sku=NL-BRG-6205-2RS",
   "status": 200,
   "answered": "Total 580 on hand across the branches: Cleveland OH 412, Green Bay WI 168, Charlotte NC 0. Lead time 1 working day. Availability InStock.",
   "body": {
    "sku": "NL-BRG-6205-2RS",
    "by_branch": {
     "Cleveland OH": 412,
     "Green Bay WI": 168,
     "Charlotte NC": 0
    },
    "total": 580,
    "availability": "https://schema.org/InStock",
    "lead_days": 1,
    "refreshed": "2026-10-16T02:00:00-05:00",
    "source": "ERP export, read-only"
   }
  },
  {
   "question": "What does the M12 hex bolt cost for account 2277?",
   "request": "GET /api/price?sku=NL-FST-HEX-M12&account=acct-2277",
   "status": 200,
   "answered": "68.16 USD per box of 100 on Bayline Fabrication (tier-1), against a public list price of 96.00.",
   "body": {
    "sku": "NL-FST-HEX-M12",
    "account": "acct-2277",
    "account_label": "Bayline Fabrication",
    "tier": "tier-1",
    "unit_price": 68.16,
    "currency": "USD",
    "list_price": 96.0,
    "note": "list price is public; an account price is contractual and expires with the agreement",
    "uom": "box of 100"
   }
  },
  {
   "question": "And on the contract account 3305?",
   "request": "GET /api/price?sku=NL-FST-HEX-M12&account=acct-3305",
   "status": 200,
   "answered": "61.44 USD per box of 100 on Catawba Process Systems (contract), against a public list price of 96.00.",
   "body": {
    "sku": "NL-FST-HEX-M12",
    "account": "acct-3305",
    "account_label": "Catawba Process Systems",
    "tier": "contract",
    "unit_price": 61.44,
    "currency": "USD",
    "list_price": 96.0,
    "note": "list price is public; an account price is contractual and expires with the agreement",
    "uom": "box of 100"
   }
  },
  {
   "question": "Send the batch certificate for GTIN 09506000134352, lot LOT-2026-09-A.",
   "request": "GET /api/batch/09506000134352/LOT-2026-09-A",
   "status": 200,
   "answered": "Batch LOT-2026-09-A of NL-BRG-6205-2RS, issued 2026-10-16, signature Ed25519:75240c8018bc274923... Verifiable against the issuer key. Claims: origin declared by the supplier, dimensional and material tests pass.",
   "body": {
    "gtin": "09506000134352",
    "lot": "LOT-2026-09-A",
    "sku": "NL-BRG-6205-2RS",
    "issuer": "Northline Industrial Supply",
    "issued": "2026-10-16",
    "signature": "Ed25519:75240c8018bc27492394f83da6082ea563d847f5472bcabdb14340add9dd78f2",
    "signature_note": "signed with the issuer key held by Northline, verifiable against the public key published at /.well-known/agent-card.json",
    "claims": {
     "part": "Deep groove ball bearing 6205-2RS, 25mm bore",
     "brand": "Northline Bearings",
     "produced": "2026-09-12",
     "origin": "declared by the supplier",
     "tests": {
      "dimensional": "pass",
      "material": "pass"
     }
    },
    "verify_at": "/.well-known/agent-card.json"
   }
  },
  {
   "question": "Can I place the order through this interface?",
   "request": "GET /agents.txt",
   "status": 200,
   "answered": "Refused by rule. No purchase orders through this interface. No redistribution of the price file. Repeated calls to a",
   "body": "# /agents.txt : Northline Industrial Supply\n\nService: industrial parts catalogue, machine readable.\nOperator: Northline Industrial Supply, Inc. (synthetic demonstration company)\nContact: sales@northline.example\nLanguage: en\nCurrency: USD\n\n## Open endpoints, no key required\n\nGET /api/catalog?q=          search the catalogue\nGET /api/price?sku=&account= price for an account number\nGET /api/stock?sku=          stock by branch and lead time\n\n## Endpoints that need an account\n\nAn account number, issued by Northline, unlocks contracted prices. The number is passed as a query\nparameter over TLS and i"
  }
 ],
 "needs": [
  {
   "stage": "Contact",
   "what_we_do": "Nothing. They arrive from the scan, or we open with a score we measured on their own domain.",
   "what_we_need": "The domain, the product line, and who owns the website.",
   "time": "1 day"
  },
  {
   "stage": "Intake call",
   "what_we_do": "Thirty minutes. They describe the catalogue and where the price lives.",
   "what_we_need": "Who the price depends on, which accounts exist, how many parts are live, which systems hold the truth.",
   "time": "1 day"
  },
  {
   "stage": "Diagnostic",
   "what_we_do": "We scan their public domain with the twelve checks and send the transcript.",
   "what_we_need": "Read-only access to nothing. The scan is public.",
   "time": "2 days"
  },
  {
   "stage": "Access",
   "what_we_do": "They open a read-only path to the catalogue and a staging copy of the site.",
   "what_we_need": "A catalogue export (CSV or API), the account price matrix, the stock source, and a staging hostname we may call.",
   "time": "3 to 5 days"
  },
  {
   "stage": "Gateway build",
   "what_we_do": "We stand the gateway in front of the staging catalogue and answer the six buyer questions.",
   "what_we_need": "One named engineer on their side who can answer questions about fields; a decision on what an anonymous caller may see.",
   "time": "10 working days"
  },
  {
   "stage": "Acceptance",
   "what_we_do": "The twelve checks are re-run against staging, and three real buyer questions must be answered correctly.",
   "what_we_need": "A person on their side who says yes to the result, in writing.",
   "time": "2 days"
  },
  {
   "stage": "Live",
   "what_we_do": "The gateway is published in front of production under their domain, with the log delivered to them.",
   "what_we_need": "A DNS change or a proxy rule, and a named owner for the log.",
   "time": "2 days"
  },
  {
   "stage": "First month",
   "what_we_do": "Weekly call, the log reviewed, the twelve checks re-run monthly.",
   "what_we_need": "The account list quarterly so the price tiers stay true.",
   "time": "30 days"
  }
 ],
 "price": [
  {
   "line": "Diagnostic",
   "usd": 2500,
   "note": "credited in full against the first month, so it is not an extra cost"
  },
  {
   "line": "Standard gateway, 50,000 calls a month",
   "usd": 1500,
   "note": "the tier a catalogue of this size starts on"
  },
  {
   "line": "Integration, one-time",
   "usd": 8000,
   "note": "their export, their staging, their rule set, their log"
  },
  {
   "line": "First month, all in",
   "usd": 9500,
   "note": "diagnostic credited: 2500 + 1500 + 8000 minus the 2500 credit"
  },
  {
   "line": "Year one",
   "usd": 27500,
   "note": "diagnostic and integration once, the gateway for twelve months"
  }
 ],
 "live_address": "https://157-180-49-112.sslip.io:8099",
 "raw": {
  "acceptance": "/root/pilot/loop-acceptance-2026-10-16.json",
  "agent_pass": "/root/pilot/loop-agent-pass-2026-10-16.json",
  "catalogue": "/root/pilot/demo_northline/catalogue.json"
 }
}