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.
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: nullparameters: {}(empty object — notype, noproperties)parameters: { "type": "object" }(declared as object but noproperties)- A
propertiesentry where the field is missing atype - A
propertiesentry where thetypevalue isn't one ofstring,number,integer,boolean,array,object,null - A
type: "array"field with noitemsdeclaration - A
type: "object"field with no nestedproperties(and noadditionalProperties: trueescape 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 input | JSON Schema type | Optional 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"> group | string | "enum": [...] |
<select> single | string | "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:
requiredHTML attr → field appears in JSON Schemarequiredarrayminlength/maxlength→minLength/maxLengthin JSON Schema (camelCase, mandatory)pattern="^[A-Z0-9]+$"→"pattern": "^[A-Z0-9]+$"(regex carries directly)min/maxon 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:
cat agents.json | jq .— confirms JSON is parseable.- Paste your file into json-schema-validator.herokuapp.com or any JSON Schema validator — confirms each parameter block is spec-compliant.
- Re-run Lighthouse Agentic Browsing — the
agents-json-actions-typedaudit 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
- Lighthouse Agentic Browsing FAQ — every common question, answered → — Long-tail Q&A coverage including this audit's most-searched questions.
- Lighthouse Agentic Browsing — every audit, every fix → — the canonical per-audit fix reference
- agents.json reference → — the file's structure, full action examples, and typing rules
- agents.json vs WebMCP vs llms.txt → — the three-layer mental model
- Add agents.json to WordPress in 5 minutes → — install path on WordPress
- The 2026 agent-ready Shopify checklist → — Shopify-specific application
- Run the free readiness audit → — check whether your file passes the typed-parameters audit