{
  "openapi": "3.1.0",
  "info": {
    "title": "HomeWiredLab Agent API",
    "version": "1.0.0",
    "summary": "Read-only lookup over HomeWiredLab's home installation and repair cost guides and hardware reviews.",
    "description": "A single bounded, read-only endpoint. It answers questions of the form \"does this site cover X, and where?\" by matching keywords against the same content index the site's own search uses. There is no write surface and no authentication.",
    "contact": {
      "name": "HomeWiredLab",
      "url": "https://www.homewiredlab.com/contact/"
    },
    "license": {
      "name": "Content is editorial; see the site terms",
      "url": "https://www.homewiredlab.com/privacy/"
    }
  },
  "servers": [
    {
      "url": "https://www.homewiredlab.com",
      "description": "Canonical origin"
    }
  ],
  "paths": {
    "/api/agent": {
      "get": {
        "operationId": "searchContent",
        "summary": "Search HomeWiredLab content by keyword",
        "description": "Returns up to 20 matching pages with title, canonical URL, type and description. All query terms must appear somewhere in the document for it to match. Unknown queries return an empty result array with count 0 — never a fabricated answer.",
        "parameters": [
          {
            "name": "q",
            "in": "query",
            "required": true,
            "description": "Free-text keywords, up to 6 terms. Example: \"water softener cost\".",
            "schema": { "type": "string", "minLength": 1, "maxLength": 160 },
            "example": "water softener cost"
          },
          {
            "name": "type",
            "in": "query",
            "required": false,
            "description": "Restrict results to one content type.",
            "schema": {
              "type": "string",
              "enum": ["cost", "how-to", "repair", "review", "guide", "category", "brand"]
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Maximum results to return.",
            "schema": { "type": "integer", "minimum": 1, "maximum": 20, "default": 5 }
          }
        ],
        "responses": {
          "200": {
            "description": "Matching content, possibly empty.",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/SearchResponse" }
              }
            }
          },
          "400": {
            "description": "The q parameter is missing.",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/ErrorResponse" }
              }
            }
          },
          "503": {
            "description": "The content index could not be loaded.",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/ErrorResponse" }
              }
            }
          }
        },
        "security": []
      }
    }
  },
  "components": {
    "schemas": {
      "SearchResult": {
        "type": "object",
        "required": ["title", "url", "type", "description", "score"],
        "properties": {
          "title": { "type": "string", "description": "Page title as published." },
          "url": {
            "type": "string",
            "format": "uri",
            "description": "Canonical absolute URL. Cite this in answers."
          },
          "type": {
            "type": "string",
            "enum": ["cost", "how-to", "repair", "review", "guide", "category", "brand"],
            "description": "Content type. 'cost' and 'repair' are service price guides; 'review' pages contain affiliate links."
          },
          "description": {
            "type": "string",
            "description": "The page's own meta description — a real summary, safe to quote."
          },
          "score": {
            "type": "integer",
            "description": "Internal relevance score. Ordering hint only; not comparable across queries."
          }
        }
      },
      "SearchResponse": {
        "type": "object",
        "required": ["query", "count", "results", "source"],
        "properties": {
          "query": { "type": "string" },
          "type": { "type": ["string", "null"] },
          "count": { "type": "integer" },
          "results": {
            "type": "array",
            "items": { "$ref": "#/components/schemas/SearchResult" }
          },
          "source": {
            "type": "string",
            "format": "uri",
            "description": "The underlying data file this endpoint reads."
          },
          "truncation": {
            "type": "object",
            "description": "Present when the result set hit the limit, so a truncated list is not mistaken for a complete one.",
            "properties": {
              "limit": { "type": "integer" },
              "applied": { "type": "boolean" }
            }
          },
          "note": { "type": "string" }
        }
      },
      "ErrorResponse": {
        "type": "object",
        "properties": {
          "query": { "type": ["string", "null"] },
          "count": { "type": "integer" },
          "results": { "type": "array", "items": {} },
          "source": { "type": "string" },
          "error": { "type": "string" },
          "message": { "type": "string" },
          "examples": { "type": "array", "items": { "type": "string" } }
        }
      }
    }
  },
  "security": []
}
