ax-check rule

AXC-D007: Closed vocabulary hinted in prose, not declared as an enum

A parameter description lists allowed values ("one of", "e.g. 'x'", "such as") but the schema declares no enum.

ax-check is a checker being prepared for release. This page documents the rule ahead of that release; see all 50 rules.

Severitywarn
KindHeuristic. A pattern match: a prompt to look, not a verdict.
Modeax-check lint
Applies toMCP tool lists, OpenAPI
Pattern tagsschema-enum, description, false-success
Fix in one lineMove the allowed values into the schema as "enum" (or "const" alternatives) and keep the prose for meaning.

A parameter description lists allowed values, with words such as “one of”, “for example ‘draft’” or “such as ‘paid’”, but the schema declares no enum. The agent has to guess the full set from a hint. When it guesses wrong, many servers do not reject the value: they ignore it, and the agent reports success on a call that did nothing useful.

What it checks

For each string parameter, ax-check reads the description for signs of a closed set of values. If it finds one and the schema has no enum, no const and no list of constant alternatives, it reports the parameter.

Why it matters

A schema is checked by machines; prose is not. An enum lets the client validate the call before it is sent and lets the server return an honest error. A vocabulary that lives only in the description is invisible to both.

Li, Ye, Guo and Dang studied this in “SilentProbe” (preprint, August 2026). Across 721,320 parameters in 2,501 OpenAPI documents, the paper’s claim is that 7.5% declare an enumeration, and 40.1% of documents state a constraint in prose that the schema does not encode. In their tests, machine-checkable constraints gave an honest error in 111 of 111 cases, while prose-only constraints failed silently in 44 of 61. With twelve models from eight families, a vocabulary the description merely exemplified was missed on 88 of 88 attempts; promoting it into the schema took the failure to 0 of 89 (all the paper’s claim). The authors reached the endpoints through one aggregation layer with which they declare an affiliation.

How to fix

Move the allowed values into the schema as enum (or as oneOf alternatives that each use const, when each value needs its own description). Keep the prose for meaning: what each value does and what happens when the parameter is omitted.

Example

Before

"status": {
  "type": "string",
  "description": "Filter by invoice status, for example 'draft' or 'paid'."
}

After

"status": {
  "type": "string",
  "enum": ["draft", "open", "paid", "void"],
  "description": "Only return invoices in this state. Omit it to return invoices in every state."
}

How ax-check detects it

The rule looks only at string-like parameters: no type, type: string, or an array of strings. It skips a parameter that already has enum, const, or oneOf/anyOf where every branch is a const or an enum (and the same for array items). Parameters are the top-level properties of an MCP input schema, and OpenAPI parameters and top-level JSON request body properties. CLI help and skills are not checked by this rule.

Strong signals report the parameter on their own:

  • “one of the following”, “any of the following” or “either of the following”;
  • “one of”, “any of” or “either of” in other forms, unless followed by a word such as “the”, “your” or “these” (so “one of the invoices” does not count);
  • “valid values”, “allowed options”, “supported modes” and similar;
  • “options are”, “values include”, “must be one of”, “must be either”;
  • two or more quoted words joined by commas, slashes, pipes, “or” or “and”, such as 'draft', 'open' or 'paid';
  • a bare pipe list such as asc|desc.

A weak signal, “e.g.”, “for example”, “for instance”, “such as” or “like” followed by one quoted word, counts only when the parameter name does not look like free input (names ending in query, text, name, id, slug, url, path, email, date, tag and similar) and the schema has no format or pattern. A strong signal that sits just after “for example” is ignored on the same kind of parameter.

Known false negatives: a vocabulary introduced in other words, such as “Accepts draft, open or paid” with unquoted values, is missed. Nested object properties are not inspected.

Known false positives: an open set illustrated with quoted examples, such as a locale parameter described as “for example ‘en-GB’ or ‘fr-FR’”. Adding a pattern or format silences the finding and documents the shape. Otherwise use --disable AXC-D007.

Sources

  • Paper: Li, Ye, Guo and Dang, “SilentProbe: Measuring Silent Failure in Production APIs Used as Agent Tools”, arXiv 2609.00035, submitted 29 August 2026 (preprint, not peer reviewed). https://arxiv.org/abs/2609.00035 . The paper’s claim, with twelve models across eight families, is that a vocabulary only exemplified in prose was missed on 88 of 88 attempts and on 0 of 89 once declared in the schema.
  • Site guide: Write tool descriptions an agent can act on, agentexperience.tech. https://agentexperience.tech/insights/tool-descriptions/ . Asks for closed sets to be declared in the schema as an enum, with additionalProperties set to false.

Records in the AX evidence register that share a pattern tag with this rule. A shared tag means the record is about the same pattern, not that it tests this rule. Read the evidence class before the number.