The Param the Model Keeps Skipping: Required vs Optional Tool Parameters
▶ Watch on YouTube & subscribe to The Stack Underflow
A finance tool takes amount and an optional currency. Ninety percent of the time the model omits currency entirely, the tool quietly assumes USD, and three weeks later someone in the EU office is staring at a total that’s off by 8% because the underlying charge was in euros. Nobody wrote a bug. The schema just told the model it was fine to skip a field that was never actually optional in practice — it just felt optional to whoever wrote the tool.
This is a JSON Schema question dressed up as a prompting problem, and it’s exactly the kind of scenario Domain 2 of the Claude Certified Architect exam — Tool Design & MCP Integration, roughly 18% of the exam per Anthropic’s public blueprint — tests directly.
The one-sentence version: If a parameter must be there for the tool to behave correctly,
requiredis not a suggestion you skip to save tokens — it’s the contract that stops the model from guessing.
The question
A tool has an optional currency param the model keeps omitting, producing wrong totals. What’s the fix?
- A) Hope it remembers
- B) Make it required in the schema and describe when it matters
- C) Default it silently to USD
- D) Remove the param
Pause here and pick an answer before you keep scrolling.
The answer
B — make currency required in the schema, and describe when it matters.
The mechanism is simpler than it looks, and it’s the same mechanism behind every “the model keeps forgetting X” complaint in tool design: the model doesn’t read your intentions, it reads your JSON Schema. If a field sits outside the required array, the model has been handed explicit permission to skip it — and it will, especially on the common path where the answer isn’t obviously needed. The description field, when a param is optional, gets treated as flavor text rather than a hard constraint.
Here’s the before/after schema diff that’s the actual fix:
BEFORE — currency is optional, gets skipped
{
"type": "object",
"properties": {
"amount": { "type": "number" },
"currency": {
"type": "string",
"enum": ["USD", "EUR", "INR"],
"description": "The currency of the amount"
}
},
"required": ["amount"] <-- currency NOT here
}
model reads schema
│
▼
"currency isn't required —
I can just call the tool
with amount alone"
│
▼
charge_total(amount: 500) <-- wrong total, silently
────────────────────────────────────────────────────────
AFTER — currency is required, with a sharper description
{
"type": "object",
"properties": {
"amount": { "type": "number" },
"currency": {
"type": "string",
"enum": ["USD", "EUR", "INR"],
"description": "Always set for cross-border totals — never assume the caller's home currency"
}
},
"required": ["amount", "currency"] <-- now enforced
model reads schema
│
▼
"currency IS required —
I must supply it or the
call is invalid"
│
▼
charge_total(amount: 500, currency: "EUR") <-- correct
Two things move in that diff, and both matter:
requiredgained an entry. This is the part that actually changes behavior. Most tool-calling implementations (Claude included) validate the arguments against the schema before or immediately after generation — a call missing a required field is either rejected or triggers the model to self-correct and re-emit the call with the field filled in. An optional field has no such backstop; a skipped optional field is just… skipped, and the tool runs anyway.- The description got sharper.
"always set for cross-border totals"tells the model when the field matters, which helps in the rarer case where a genuinely optional field should be supplied conditionally. But description text alone, on an optional field, is advisory — it’s a strong suggestion, not a gate. That’s why option B pairs both moves: required and a clearer description. Required does the enforcement; the description does the judgment call for edge cases the schema alone can’t express (like “required except when X”).
The general rule from the source material: schemas beat reminders. A system-prompt note asking the model to “please remember to always include currency” degrades under load — long conversations, competing instructions, context pressure. A required array entry doesn’t degrade. It’s checked mechanically, every single call.
Why the other options fail
- A) Hope it remembers. This isn’t a fix, it’s the status quo — it’s the exact behavior that produced the bug report in the first place. “The model usually gets it right” is not a design; it’s an incident waiting for a retry.
- C) Default it silently to USD. This is the most dangerous wrong answer because it looks like a fix — the tool stops erroring and totals stop looking obviously broken. But it converts a loud, catchable failure (model omits currency, tool call fails validation, model retries with the field) into a silent, uncatchable one: every European or Indian transaction now gets mislabeled as USD with no error, no log line, no signal. Silent defaults on financially significant fields are how “off by 8%” becomes a quarter-long reconciliation project instead of a one-line schema fix caught in code review.
- D) Remove the param. This solves the omission problem by making the tool incapable of doing its job correctly for any currency other than whatever gets hardcoded. It doesn’t fix the design flaw, it just deletes the flexibility the tool needed in the first place — now every non-USD transaction is unrepresentable, not just occasionally mislabeled.
The concept behind it
Zoom out from this one param, and the general principle is: required is where you encode “the tool cannot behave correctly without this,” and description is where you encode “here’s how to decide.” They do different jobs, and conflating them is the most common tool-schema mistake.
| Signal | What it tells the model | Enforcement | Use it for |
|---|---|---|---|
required array | This field must be present or the call is invalid | Mechanical — validated against the schema, not left to judgment | Fields the tool genuinely cannot run without (currency on a money tool, an ID on a lookup, a destination on a transfer) |
type / format / enum | The field must look like this, not free text | Mechanical — a malformed value is rejected before it reaches your code | Dates, currency codes, IDs — anything with a canonical machine-readable shape |
description on the field | When and why to set this, especially for judgment calls | Advisory — the model reads it, but nothing blocks a call that ignores it | Conditional logic the type system can’t express: “only needed for international transfers,” “omit unless the user specifies a region” |
| System-prompt reminder | A general nudge, not tied to any one call | Advisory, and the weakest of the four — competes with everything else in context | Broad behavioral guidance, not per-field data contracts |
A useful test when you’re deciding whether a param should be required: if the tool produces a wrong or misleading result when the field is absent, it belongs in required — even if there’s a “reasonable” default you could fall back to. A default that’s silently wrong for a meaningful slice of your users (every non-USD customer, every non-UTC timezone, every non-default region) is worse than an explicit failure, because explicit failures get noticed and fixed. Silent wrong answers get shipped.
This connects directly to two other tool-design failure modes worth knowing cold for the exam. Loosely typed inputs — a date field with no format, letting the model send "next Tuesday" — fail the same way for the same underlying reason: the schema didn’t constrain what it should have. And vague descriptions on the tool itself, not just its params, cause the model to pick the wrong tool entirely, because tool selection and parameter selection are both reading from the same source of truth: what you wrote in the schema, not what you meant.
FAQ
Does making a field required mean the model will always have a value to put there?
No — and this is the sharp edge of the fix. If you make currency required but the upstream conversation genuinely never mentions a currency, the model either has to ask the user or infer one, and a badly designed required field just forces a bad guess instead of a bad omission. The fix works because currency is usually inferable from context (the user’s account region, an explicit mention, an enum default surfaced in the tool description) — required parameters need to be things the model can reasonably obtain, not things you’re hoping appear out of nowhere.
What if a param really is optional — is there a lighter-weight fix than required?
Yes. If a field is genuinely sometimes-needed and sometimes-not, keep it optional but write the description as a decision rule rather than a definition: not "the currency" but "set this whenever the transaction is not in the user's home currency; omit only for same-currency transfers." That gives the model a judgment call to make instead of a fact to remember — a real difference in how reliably it gets applied.
Is this a JSON Schema concept or something Anthropic-specific to Claude’s tool use?
It’s plain JSON Schema — required, type, format, enum are all standard keywords, not an Anthropic extension. What’s worth knowing for the exam is how Claude’s tool-use implementation uses that schema: arguments are validated against it, and a missing required field is a strong, mechanical signal back to the model, versus an optional field’s absence being invisible.
Does this same logic apply to MCP tool schemas, or only to inline tool definitions?
Same logic, same JSON Schema underneath. MCP tools declare their inputSchema the same way inline tools declare their parameter schema — the required array does the identical enforcement job whether the tool is defined inline in your agent code or exposed by an MCP server. For the deeper picture of how MCP tool definitions travel from server to model, see the MCP explainer linked below.
Where this fits in the CCA series
This is question 9 of a 10-question Domain 2 practice set on Tool Design & MCP Integration. If schema design like this is new territory, start with the keystone — Claude Certified Architect (CCA) Exam Guide: All Five Domains on One Diagram — and, if MCP itself is still fuzzy, MCP Explained on One Diagram: The USB-C Port for AI Tools.
Two sibling questions in the same set worth the five minutes: The Model Sends ‘Next Tuesday,’ Not a Date: Typing Tool Parameters covers the same “constrain it in the schema, don’t hope” principle for date fields, and ‘Gets Data’ Is Too Vague: How to Write Tool Descriptions That Work covers the description-writing half of the contract this page only touched on. If tool selection itself is the problem rather than a skipped param, Why Does Claude Pick the Wrong Tool? Fixing Tool Selection is the closest relative.
Not affiliated with, authorized, or endorsed by Anthropic. “Claude” and “Claude Certified Architect” are trademarks of Anthropic. These are original practice questions for study, not real exam content — verify current exam details (as of mid-2026: Pearson VUE, $125, retakes available, 60 questions / 120 minutes, pass score 720/1000, five domains) on Anthropic’s official pages.
Browse all tutorials for the rest of the CCA prep series and beyond.
Found this useful? The deep version lives on YouTube — new breakdowns of how AI dev tools actually work, weekly.
Subscribe on YouTube →