skip to content

When should a tool parameter be required versus optional in its JSON Schema?

level: middleimportance: should knowfreq 54%

answer

  1. required means the model must ask first
  2. optional fields invite invented values
  3. enum closes the value space
  4. handler defaults beat schema optionals
  5. nesting: real structure, not your domain model

basics

~20 s

Mark a parameter required when the tool cannot do anything useful without it and the value must come from the conversation. Every optional field is an invitation for the model to invent a plausible value, so keep optionals few, describe them tightly, and default the rest in your handler.

solid answer

~50 s

`required` is not bookkeeping — it changes model behaviour. A required field tells the model it must gather that value before calling, so a missing policy number becomes a question to the user rather than a guess. An optional field says "fill this if you can", and a cooperative model frequently can, by fabricating something plausible: free-text notes that paraphrase nothing the caller said, a date it inferred from context. So the rule I use is: required for anything the tool genuinely cannot execute without, optional only where absence is meaningful and the field's own description says when to omit it, and everything else moved out of the schema entirely into handler-side defaults. Enums do related work on the value axis — pinning a claim type to six known values removes a whole class of invented strings that free text would allow.

code

json · 37 lines
json
{
  "name": "file_claim",
  "parameters": {
    "type": "object",
    "properties": {
      "policy_number": {
        "type": "string",
        "description": "Policy number exactly as stated by the caller. Ask for it if missing; never infer it."
      },
      "claim_type": {
        "type": "string",
        "enum": ["auto_collision", "auto_theft", "property_fire", "property_water", "property_theft", "liability"]
      },
      "incident": {
        "type": "object",
        "properties": {
          "occurred_at": {"type": "string", "description": "ISO-8601 date or datetime of the incident."},
          "location": {
            "type": "object",
            "properties": {
              "city": {"type": "string"},
              "region": {"type": "string"},
              "country": {"type": "string"}
            },
            "required": ["city", "country"]
          }
        },
        "required": ["occurred_at", "location"]
      },
      "adjuster_notes": {
        "type": "string",
        "description": "Free text stated by the caller. Omit entirely if none was volunteered; never summarise or infer."
      }
    },
    "required": ["policy_number", "claim_type", "incident"]
  }
}

go deeper

for a junior

Know that required lists the fields that must be present, and that enum pins a parameter to a fixed set of allowed values. Be able to write a small schema with both.

for a middle

Explain the behavioural effect: required pushes the model to ask the user for a missing value, while an optional field gives it permission to invent one. Cover enums and nested required arrays.

for a senior

Demonstrate the judgment of keeping schemas minimal — moving handler concerns out of the model's interface, guarding the optionals that remain with omission conditions, and validating everything server-side regardless.

for a principal

Own the interface standard across teams: which fields agents are ever allowed to supply, where the model-facing schema deliberately diverges from the internal API, and how enums stay in sync with a domain vocabulary that changes.

## What `required` actually does In JSON Schema, `required` is an array of property names on the object that must be present. In a tool definition it does double duty. Mechanically it is a validation rule, and under strict decoding modes it is enforced. Behaviourally — and this is the part interviews are testing — it is an instruction to the model about what it must have in hand before it is allowed to call. That behavioural half is the useful one. When a field is required and the conversation has not supplied it, a well-prompted model asks the user. When the same field is optional, the model has permission to proceed without it, and will. Requiredness is therefore one of your few levers for making an agent gather information rather than assume it. ## The optionality trap Every optional field is a small invitation to hallucinate. Consider an insurance first-notice-of-loss tool with an `adjuster_notes` string marked optional. Nothing in the schema says the notes must originate from the caller. A helpful model, having been told the field exists, will often fill it with a fluent summary that reads like it came from the conversation but contains details nobody stated. The output validates perfectly. It is still wrong, and because it validates, no runtime check catches it. Three defences, in order of effectiveness: 1. **Delete the field.** If your handler can compute or default it, it does not belong in the model's schema at all. Most fields that end up optional are actually handler concerns that leaked into the interface. 2. **Describe the omission condition.** If the field must stay, its description should say when to leave it out and where legitimate values come from: "optional free-text notes stated by the caller; omit entirely if the caller did not volunteer them; never summarise or infer". 3. **Constrain the value space.** Where the field is categorical, an `enum` replaces open text with a closed set and removes the fabrication surface. ## Enums and the value axis `required` governs presence; `enum` governs value. A claims tool with `claim_type` as a free string will receive `"auto accident"`, `"car crash"`, `"collision"` and `"AUTO_COLLISION"` from the same model on different days, and your handler has to normalise all of them. The same field declared as an enum of six values — `auto_collision`, `auto_theft`, `property_fire`, `property_water`, `property_theft`, `liability` — makes the mapping the model's job at generation time, which is exactly where it belongs, and under strict decoding makes an out-of-set value impossible rather than merely unlikely. Enums also teach. Seeing the six categories tells the model what the domain looks like, which improves the choice, not just its formatting. The limit is cardinality: a fifty-value enum is a taxonomy the model must scan on every turn, and at that size a lookup tool or a two-step flow usually reads better than a wall of literals. ## Nested objects Nesting is how you express structure that genuinely belongs together — an `incident` object holding `occurred_at` and a `location` object with `city`, `region` and `country`. Nested objects carry their own `required` arrays, so you can say that a location must have a city and a country while region is optional. Use nesting when the grouping is real and reused, not to mirror your internal domain model. Deep nesting hurts twice: it costs tokens on every turn, and each additional level is another place for the model to produce a structurally valid but semantically empty object — an `incident` present, correctly shaped, and containing invented values. Two levels is comfortable; beyond three, flatten or split the tool. ## A worked shape For the claims tool: `policy_number` required, because filing without one is meaningless and the value can only come from the caller. `claim_type` required and enumerated, because routing depends on it and the model can classify from the narrative. `incident` required, with `occurred_at` and `location` required inside it. `adjuster_notes` optional, with a description that says to omit it unless the caller volunteered the text. Nothing else — timestamps, channel, agent id, correlation ids all belong to the handler and never appear in the schema. ## What stays on the server A final discipline: `required` is guidance to the model, and under strict modes a shape guarantee, but never a trust boundary. The handler validates regardless — presence, ranges, referential existence, authorisation. A schema makes the right call likely and the wrong shape impossible; it does not make the value true. `policy_number` may be perfectly formatted, present, and belong to a different customer.

  • An optional field is being filled with invented values. What do you change first?
    Try to remove the field: if the handler can default or derive it, it should never have been in the model's schema. If it must stay, rewrite its description to state the omission condition explicitly and where legitimate values come from, and constrain the type if the field is categorical. Adding the field to required is the wrong fix — it forces a value where absence was the honest answer.
  • When is an enum the wrong choice for a categorical parameter?
    When the value set is large, volatile, or caller-specific. A fifty-value enum is a taxonomy the model must read on every turn, and any set that changes without a redeploy will drift out of date in the schema. Above roughly a dozen stable values, prefer a lookup tool that returns valid options, or a free string the handler resolves and rejects clearly on no match.
  • Does marking a field required guarantee the model supplies a real value?
    No. It guarantees the field is present, and under strict decoding that it has the declared type. The model can satisfy a required string with a fabricated one just as easily as an optional one — requiredness raises the chance it asks the user first, but the truth of the value is never a schema property. Server-side validation and authorisation checks remain mandatory.

saying these in an interview costs you the question

  • Marks everything optional to avoid call failures
  • Thinks required guarantees the value is correct
  • Uses free-text strings where a fixed value set exists
  • Mirrors internal domain objects as deep nested schemas
  • Puts handler-side defaults into the model's schema

context