BridgeToAgent
Audit6 min read

agents-json-actions-typed — why your action manifest is failing the Lighthouse type check

The agents-json-actions-typed audit fails on most hand-written agents.json files. The reason is rarely missing fields — it's untyped or wrongly-typed parameters. This post is the deep dive on the typing rules the audit enforces, the seven common mistakes that flunk hand-written manifests, and the type-inference table for converting any HTML form into a passing schema.

BridgeToAgentEditorial team

agents-json-actions-typed — why your action manifest is failing the Lighthouse type check

agents-json-actions-typed is the Lighthouse Agentic Browsing audit that catches the most hand-written agents.json files in 2026. Files that pass the easier agents-json-present audit (file exists, returns valid JSON) often fail this one — because passing requires more than uploading the file. Every action declared in agents.json needs a properly-typed parameter schema, and most hand-written drafts get the typing slightly wrong.

This post unpacks the typing rules, the failure modes, and the type-inference table that lets you convert any HTML form on your site into a schema the audit accepts.


What the audit actually checks

The reference parser for agents.json walks every entry in your actions array and validates each action's parameters block against JSON Schema. The audit marks red on any of these:

  • parameters: null
  • parameters: {} (empty object — no type, no properties)
  • parameters: { "type": "object" } (declared as object but no properties)
  • A properties entry where the field is missing a type
  • A properties entry where the type value isn't one of string, number, integer, boolean, array, object, null
  • A type: "array" field with no items declaration
  • A type: "object" field with no nested properties (and no additionalProperties: true escape hatch)

The audit is strict on purpose. A typed schema is what lets an agent call the action — without it, the agent has no idea whether to send a query string, an integer, a date, or an enum value. A vague schema is functionally equivalent to no schema.


The seven mistakes that flunk most hand-written manifests

1. Plain parameters: null

The most common single failure mode. Author writes the action shape, defines name/description/url/method, leaves parameters empty as a TODO, and ships.

Fix. Even actions with no parameters need a non-null block:

{
  "name": "contact",
  "url": "https://yourdomain.com/contact",
  "method": "GET",
  "parameters": { "type": "object", "properties": {} }
}

Empty properties: {} is valid — the audit doesn't require parameters, it requires typed parameters when they exist.

2. Inline properties without the wrapping object

Author writes parameters as a flat key-value list instead of the JSON Schema shape:

"parameters": {
  "q": "string",
  "limit": "number"
}

This looks like typing, but it's not — JSON Schema requires the wrapper:

"parameters": {
  "type": "object",
  "properties": {
    "q": { "type": "string" },
    "limit": { "type": "number" }
  },
  "required": ["q"]
}

The type: "object" declaration plus properties wrapper is mandatory. Field types go in nested objects, not as direct values.

3. Wrong type names

text, int, float, bool, date, url, email are not valid JSON Schema types. The accepted types are exactly: string, number, integer, boolean, array, object, null. Use format for finer-grained constraints:

{
  "type": "string",
  "format": "email"
}

Other common formats: date, date-time, uri, uuid. The audit accepts them on string fields.

4. Optional fields without typing

Author thinks optionality implies type-free:

"properties": {
  "name": { "type": "string" },
  "phone": {}
}

Wrong. Optional means the field isn't in required, but it still needs a type when it appears:

"properties": {
  "name": { "type": "string" },
  "phone": { "type": "string" }
},
"required": ["name"]

5. Enum fields with no enum

Selects and radio buttons on the source form become string fields with an enum. Author often writes:

"size": { "type": "string" }

This passes the audit but loses information — the agent can't enumerate the valid options. Correct shape:

"size": {
  "type": "string",
  "enum": ["XS", "S", "M", "L", "XL", "XXL"]
}

Same pattern for any constrained string field — countries, categories, status values.

6. Array fields with no items

Author writes:

"tags": { "type": "array" }

Passes JSON parse but fails the typed-parameters audit. Every array needs an items declaration:

"tags": {
  "type": "array",
  "items": { "type": "string" }
}

For arrays of objects, items is a nested object schema:

"line_items": {
  "type": "array",
  "items": {
    "type": "object",
    "properties": {
      "sku": { "type": "string" },
      "quantity": { "type": "integer" }
    },
    "required": ["sku", "quantity"]
  }
}

7. Nullable fields written as union types

JSON Schema allows nullable fields, but the syntax is specific:

"middle_name": { "type": ["string", "null"] }

Not:

"middle_name": { "type": "string?" }
"middle_name": { "type": "string", "nullable": true }
"middle_name": { "type": "string|null" }

The bracket-array notation is the only spec-compliant way to declare nullability. The audit accepts it; the alternatives all fail.


The type-inference table — HTML to JSON Schema

Most actions in your agents.json correspond to forms or search endpoints on your site. The conversion from HTML to the schema is mechanical once you have the table:

HTML inputJSON Schema typeOptional format / extras
<input type="text">string
<input type="email">string"format": "email"
<input type="url">string"format": "uri"
<input type="tel">string— (don't use number — tels can have spaces, dashes, +)
<input type="number">number"minimum", "maximum" from HTML attrs
<input type="number" step="1">integer
<input type="date">string"format": "date"
<input type="datetime-local">string"format": "date-time"
<input type="time">string"format": "time"
<input type="checkbox">boolean
<input type="radio"> groupstring"enum": [...]
<select> singlestring"enum": [...]
<select multiple>array"items": { "type": "string", "enum": [...] }
<textarea>string"maxLength" if maxlength attr present
<input type="hidden">match the value's type
<input type="file">string"format": "binary" (file uploads are out-of-band; the schema is informational)

For forms with constraints (required, minlength, maxlength, pattern, min, max), carry the constraints over:

  • required HTML attr → field appears in JSON Schema required array
  • minlength / maxlengthminLength / maxLength in JSON Schema (camelCase, mandatory)
  • pattern="^[A-Z0-9]+$""pattern": "^[A-Z0-9]+$" (regex carries directly)
  • min / max on numeric inputs → minimum / maximum

A fully-typed contact form looks like:

{
  "name": "contact",
  "description": "Submit a contact form inquiry",
  "url": "https://yourdomain.com/contact",
  "method": "POST",
  "parameters": {
    "type": "object",
    "properties": {
      "name": {
        "type": "string",
        "minLength": 1,
        "maxLength": 100
      },
      "email": {
        "type": "string",
        "format": "email",
        "maxLength": 255
      },
      "phone": {
        "type": "string"
      },
      "topic": {
        "type": "string",
        "enum": ["sales", "support", "partnership", "other"]
      },
      "message": {
        "type": "string",
        "minLength": 10,
        "maxLength": 5000
      },
      "newsletter_opt_in": {
        "type": "boolean"
      }
    },
    "required": ["name", "email", "topic", "message"]
  }
}

This passes the audit cleanly and gives the agent everything it needs to call the endpoint correctly.


What the kit does differently

The BridgeToAgent generator runs an HTML form-extraction pass over your sitemap, infers types from input attributes per the table above, infers enums from <select> and radio groups, and validates the resulting schema against the JSON Schema reference parser before writing the file. Files that don't validate get re-extracted or blocked at build time. Files that ship pass agents-json-actions-typed by construction.

That's not a sales pitch — it's the reason the kit costs $49 instead of being a freebie generator. The free generators that fail this audit are failing on this exact step: they extract action shapes correctly, but skip the typing pass.


Verifying your file

Three checks before publishing:

  1. cat agents.json | jq . — confirms JSON is parseable.
  2. Paste your file into json-schema-validator.herokuapp.com or any JSON Schema validator — confirms each parameter block is spec-compliant.
  3. Re-run Lighthouse Agentic Browsing — the agents-json-actions-typed audit should flip green.

If you've worked through all seven failure modes above and still see the audit failing, the issue is usually a single field with a subtle type mismatch buried in a long file. The Rich Results validator surfaces the exact field and line number.


Related

All posts →