My agent calls a tool with invalid or made-up arguments
Any AI coding tool Last checked 2026-10-14
The model is filling in a schema it does not fully understand, so it invents plausible values. Fix it at the schema, not the prompt: make every parameter strictly typed with enums and required fields, describe each one in the schema itself, and return a specific, correctable error instead of a generic failure.
What you saw
A tool call arrives with a parameter that does not exist, a string where you expect a number, an ID the agent invented, or a date in a format you never specified.
Or the call is structurally valid but semantically wrong — a plausible-looking customer_id that is not in your database.
What it actually means
Tool calling is generation. The model produces arguments the same way it produces prose: by predicting what fits. Where your schema is vague, it fills the gap with something that looks right.
What reliably causes it:
- Loose types. A parameter typed as
string with no description or enum is an invitation to invent. Free-text IDs are the worst offender. - Descriptions in the prompt instead of the schema. Models weight the tool schema heavily; a rule stated only in the system prompt is easy to lose in a long conversation.
- Too many tools. Accuracy degrades as the tool list grows, and near-duplicate tools get confused with each other.
- No way to look values up. If the agent needs an ID and has no search tool, inventing one is its only option.
- Unhelpful errors.
400 Bad Request tells the model nothing, so it retries with another guess — the usual start of a retry loop.
The fix
Constrain the schema. Enums eliminate a whole class of invention outright:
{
"status": { "type": "string", "enum": ["open", "closed", "pending"] },
"limit": { "type": "integer", "minimum": 1, "maximum": 100 },
"required": ["status"],
"additionalProperties": false
}
Put the guidance in the parameter description, where the model will actually see it: what the value means, its exact format, and where to obtain it.
Give it a lookup tool. If an argument must come from your system, provide search_customers so it never has to guess a customer_id.
Return errors the model can act on. Say what was wrong and what to do next:
{"error": "invalid_argument", "field": "status",
"got": "in_progress",
"expected_one_of": ["open", "closed", "pending"]}
Validate before executing, and never let a malformed call reach your database or an API that charges money.
Cap retries per tool call. Three attempts, then stop and surface the failure to a human — do not let it spin.
How to stop it happening again
Keep the tool list short and the tools clearly distinct. Merge near-duplicates; a single tool with an enum parameter beats four similar tools.
Use structured-output or strict-schema modes where your provider offers them — they enforce the schema at generation time rather than catching it afterwards.
Generate the schema from the same types your handler uses, so the two cannot drift apart.
Log every rejected tool call with the arguments the model produced. The pattern in those logs tells you precisely which description is ambiguous.
Make destructive tools require confirmation. An invented argument on a read is a nuisance; on a delete it is an incident.
Related questions
Would a better model fix this?
It reduces the rate, it does not remove it. Any model asked for a value it cannot know will produce something plausible. The schema and the lookup tool are what remove the possibility.
Should I retry automatically on an invalid call?
Yes, but only with a specific error in the retry, and with a hard cap of two or three attempts. Blind retries against a generic error are how a retry loop starts.
How many tools is too many?
There is no fixed number, but accuracy falls as the list grows and as tools become similar. If an agent is mixing up two tools, that is the signal to merge or rename them.