Tool-Calling Schema Design for LLM Agents
Schema design is the actual lever for fixing flaky agents, not prompts.

Tool-calling schema design decides whether an LLM agent picks the right function and fills it out correctly. It's the one lever developers actually control once the model itself is fixed, and it's the difference between an agent that works and one that quietly breaks in production. Most teams debugging a flaky agent start with the prompt. That's the wrong place to look, and it wastes hours that should go somewhere else entirely.
Tool calling, defined precisely, is the mechanism by which a model decides whether to invoke an external function, when to invoke it, and how to fill in its arguments, all within a single turn of a conversation. The model doesn't see code. It sees a set of tool descriptions laid out as text, and it generates a structured call based entirely on what those descriptions say.
Developers can't touch the model weights. Prompt injection only goes so far before it stops helping and starts confusing things. But the schema, meaning the tool's name, its description, and the shape of its parameters, sits entirely in the developer's hands. Even the best models available today still misfire on tool calls often enough to matter, and that gap between what a model can theoretically do and what it reliably does is a systems problem. It's a schema problem, full stop.
How the model reads a schema at inference time
Every tool definition boils down to three parts. It has a name, a description, and a parameter object with typed fields, some required, some not. At inference time, the model reads all of it and fills those fields in based on what it understands about the user's request.
Tool selection works like pattern matching, nothing fancier. The model compares the intent behind a query against the language in each tool's name and description, then routes to whichever one seems closest. When two tools have descriptions that overlap, or names that don't clearly separate their purposes, the model has no strong signal to pick correctly. It's guessing with extra steps, and it guesses confidently, which is worse than guessing badly. A confident wrong answer doesn't look like a wrong answer until something downstream breaks.
Field order matters more than most developers assume, too. LLMs generate left to right, so the order fields appear in a schema is effectively the order the model reasons through them. Put the wrong field first, and the model may commit to a value before it's worked out what the call actually needs.
All of this happens inside a single forward pass, and that pass is already busy. The model has to understand the query, choose the right tool, follow formatting rules, and produce a coherent response, all at once. Research on task interference has found that this kind of cognitive overload alone can cut accuracy by more than 20 percentage points. Every word in a tool description, every field in a parameter list, functions as part of the interface the model relies on. That's a cognitive load decision, whether the developer treats it that way or not.
What bad schema design looks like in practice
Failures break into three distinct buckets, and they don't share a fix.
The first is wrong tool selection. The model calls something that sounds close enough but isn't right, usually because two tools have descriptions that blur together or names too generic to differentiate. A tool called get_data sitting next to one called fetch_info gives the model nothing to go on. Semantically, they're twins, and the model treats them like a coin flip.
The second is correct tool, bad arguments. The model picks the right function but fills it out wrong, often because field names don't clearly signal what kind of value belongs there, or because there's no example anchoring the format. A sneakier version of this: marking a field as required when the underlying data might not actually contain it. Faced with a mandatory field and no real value, the model doesn't fail gracefully. It fabricates something plausible-sounding and moves on. That's worse than an outright error, because it looks like success right up until someone checks the output against reality.
The third is structural failure, and it's the ugliest one. Malformed JSON breaks the agent loop outright. The tool never runs, and no downstream logic saves a call that never executed.
Schema bloat deserves its own callout. Cramming too many fields into a single schema fragments the model's attention across all of them, and accuracy drops as a result. The fix is blunt: split the job into multiple, narrower extraction calls instead of one sprawling one. Anyone tempted to build the "one schema to rule them all" version should stop and split it now, not after it starts failing in production.
There's also a quieter risk that catches teams off guard. Adding a new tool to an existing set isn't an isolated change. It can silently degrade routing accuracy for every other tool in that set, simply by introducing another option the model has to disambiguate against. That's why schema evaluation can't be a one-time event. Performance drifts whenever tool descriptions change, new tools get added, prompts get rewritten, routing logic shifts, or the model underneath gets upgraded. None of those look like schema changes on the surface, but all of them touch schema behavior underneath.
Naming and description decisions that drive correct tool selection
The name is the first and strongest signal a model uses when choosing between tools, so it has to encode purpose without ambiguity. A name should describe the action and the domain it operates in, not function as a generic label that could apply to five different things. If a name needs a paragraph of context to make sense, the name has already failed, and no amount of description underneath will fully fix that.
Descriptions carry a heavier job than most developers give them credit for. When two tools do related things, the description's real purpose is to spell out the exact condition under which this one, specifically, is the right call. Restating the name in sentence form doesn't accomplish that. Neither does listing generic capabilities nobody asked about.
Negative specification helps more than people expect. Telling the model what a tool does not handle resolves ambiguity faster than three extra sentences describing what it does. One instructive example: a tool called check_talk_to_a_human describes both the trigger ("user requests to speak with a human representative, agent, or support person") and the resulting behavior ("checks whether escalation is possible and initiates the handoff process"). Both halves are stated explicitly. Neither is left for the model to infer.
There's a simple test for whether a description is doing its job. If a developer reading two similar tool descriptions side by side can't tell which one applies to a given scenario, the model can't either. That's not a minor gap. That's the schema failing at the one job it has.
Parameter design: types, constraints, and field order
Typed fields aren't labels for a spec sheet, they're instructions. Telling the model a field expects a string versus an enum versus an integer narrows what it's allowed to generate before it generates anything at all.
Marking a field required is a semantic claim, not a formality. It tells the model this data will always be available. When it isn't, and the field is still required, the model fills the gap with a fabricated value rather than admit it doesn't know. Making a field optional when the source data might not have an answer is the simpler, more honest fix, and it's the one most developers skip because it feels like giving something up. It is a systems problem. It's giving the model permission to tell the truth.
Constraints work the same way grammar-based decoding does, just at the design layer instead of the inference layer. Enums, min and max bounds, and pattern constraints shrink the space of valid outputs down to values that actually make sense.
Pydantic has become the practical standard for this in production Python systems, and for good reason. Typed classes generate precise JSON schemas automatically, keep the schema in sync with the underlying code, and enforce constraints declaratively instead of by convention. The schema stops being a static document somebody wrote once and forgot about. It becomes something the code maintains on its own.
The same principle from earlier applies here too: one schema per task. A complex extraction split into several focused calls tends to outperform a single, monolithic one, both on accuracy and on how easy the thing is to maintain six months later.
How structured output enforcement changes the reliability guarantee
Malformed JSON is a hard stop. If the model's output isn't structurally valid, the tool never runs, and no retry logic fixes a schema the model can't reliably produce in the first place.
Grammar-based enforcement solves this at the token level. The JSON Schema gets compiled into a finite state machine, and at each generation step, only tokens that keep the output on a valid path through that machine are allowed. Invalid tokens get a probability of zero. That's a hard guarantee, not a statistical likelihood, and the distinction matters a lot once real users are on the other end of the call.
As of early 2026, native structured output support is fairly widespread. OpenAI has offered it since August 2024. Google's Gemini added it in 2024 and expanded the feature in 2026. Anthropic ran it in beta starting November 2025 before general availability early this year. Cohere and xAI's Grok support it natively too. For locally run models, Ollama, vLLM, and SGLang get there through grammar-based constrained decoding instead.
On the tooling side, Instructor offers a unified API across more than 15 LLM providers, built on top of Pydantic. Pydantic AI, Outlines, and BAML (a cross-language structured output tool) round out the ecosystem, and grammar-based constrained decoding handles the same requirement for open-source setups.
Keep structured output and function calling straight in your head, because they solve different problems. Structured output suits extraction and classification tasks. Function calling suits agent orchestration, where a model needs to decide which action to take next. Plenty of production systems use both, in the same pipeline, for different jobs.
None of this fixes a badly designed schema, though. A JSON object can be perfectly valid and still populate the wrong fields, or hallucinate a value in a spot where the source data was empty. Enforcement guarantees structure. It says nothing about correctness. Treat the two as complementary, never as substitutes for each other.
The task interference problem and what it reveals about schema scope
Forcing JSON output isn't a neutral formatting choice. Tam et al. (2024) found that requiring JSON output cut response accuracy on GSM8K by 27.3 percentage points compared to natural language output on the same task. The format itself competed with the reasoning, and the format won.
A framework called Natural Language Tools (Johnson et al., arXiv:2510.14453, October 2025) tested a different structure entirely. Decouple tool selection into its own dedicated step, and instead of asking the model to emit JSON, ask it a plain yes-or-no question per tool. Across 6,400 trials and 10 models, that approach lifted tool-calling accuracy from 69.1% to 87.5%, an 18.4 percentage point gain. Open-weight models saw the largest jump, up 26.1 points, while closed flagship models still gained 10.6 points. Output variance dropped by 70% under the same approach, so the gain wasn't just accuracy. It was consistency, and consistency matters more in production than any single benchmark number ever will.
None of this argues against schemas. It argues against asking a model to reason, select, and format all in the same breath, and the two are not the same claim even though they sound related. Schemas scoped to a single decision hold up better than schemas that try to bundle multiple demands into one call. Whether that separation comes from NLT, from a dedicated router model, or from a simple two-step chain, the underlying mechanism stays the same: less packed into a single generation step means fewer ways for that step to go wrong. That's consistent with what schema decomposition already accomplishes at the parameter level, just applied one layer up.
How multi-tool orchestration changes schema design requirements
Early tool-use research mostly asked a narrow question: can a model pick one correct tool and execute it. The problem being worked on now is different and harder. Xu et al. (arXiv:2603.22862, April 2026) frame the current challenge as orchestration across long trajectories, with intermediate state, execution feedback, and environments that keep shifting underneath the agent as it works.
That shift surfaces failure modes single-tool schema design never has to face: choosing the right subset of tools dynamically, modeling dependencies between tools, scheduling calls in sequence or in parallel, recovering when something fails partway through, and re-planning on the fly.
Tool sets sharing overlapping domains need descriptions written relationally, not in isolation, so each tool's description implicitly signals when one of the others is the better choice instead. And tools that mutate state, meaning anything that writes or changes something external, need schemas that make the scope and irreversibility of that action legible to the model before it commits. A tool that deletes a record shouldn't look, on paper, indistinguishable from one that reads it. That distinction has to live in the schema, not in a hope that the model infers caution on its own.
Google's Agent-to-Agent protocol, introduced in 2025, extends this same discipline to communication between agents across trust boundaries. Agent Cards publish machine-readable descriptions of what an agent can do, functioning much like a tool schema but for an entire agent rather than a single function. In a multi-agent pipeline, a poorly written schema doesn't just cause one agent to misfire. It propagates. Every downstream agent depending on that tool's output inherits the failure.
Why diffusion models expose JSON schema brittleness as a structural risk
Diffusion-based language models surface a version of this problem that autoregressive models mostly avoid. Lu et al. (arXiv:2601.12979, April 2026) found that current diffusion LLMs, including LLaDA and Dream, systematically violate strict JSON schemas and produce imprecise, unstable tool invocations. The paper traces this to noise inherent in the diffusion generation process itself.
A related framework, DiffuAgent, found that diffusion models aren't useless for agent work, just mismatched to certain roles. They perform well in non-causal tasks: summarizing memory, verifying redundant trajectories, deciding early to exit a reasoning path, selecting which tool to use. Actually calling that tool, generating precise structured arguments, needs the kind of causal, step-by-step precision that diffusion generation doesn't naturally provide.
That gap is a broader pattern that extends beyond one model family. It's the clearest evidence available that JSON schema enforcement assumes a left-to-right, token-by-token generation process, and any architecture that doesn't generate that way will keep breaking it in ways constrained decoding can't patch over. Build schemas for the failure case, not just the case where everything goes right: optional fields where data might be missing, narrow enums instead of open-ended strings wherever the range of valid values is predictable, explicit handling of null values rather than letting a field silently get skipped.
Schema as a tool interface for live web data extraction in agent pipelines
Web pages don't come pre-structured. Getting a specific set of fields, reliably, out of an unstructured page and into an agent pipeline requires a developer-defined JSON schema that tells the extraction layer exactly what to pull and in what shape to hand it over. Different problem, same discipline underneath.
A framework called Schema as Parameterized Tools (Liang et al., arXiv:2506.01276, from Huawei's Noah's Ark Lab) treats predefined extraction schemas as tools in their own right, letting a model retrieve one from a pool, fill it in slot by slot, or generate a new one for a case that doesn't fit anything on hand. It's a fairly direct demonstration that schema thinking isn't confined to function calling. It extends into extraction work just as naturally.
On the open-source side, one such tool handles model-based extraction using schema definitions, alongside deep and adaptive crawling strategies and Docker deployment. Another library, openly licensed with roughly 98,000 stars on a code-hosting platform as of June 2026 and currently at version 0.13.1, takes a different approach: a model drives an actual browser session toward a goal stated in plain language, and the extraction schema defines exactly what gets pulled out of that session once it's done.
There's a maintenance argument underneath all of this, and it's the one that should worry anyone running scrapers at scale. Kadoa's 2026 research found that in the traditional scraping model, most of the time spent doesn't go to building extractors. It goes to maintaining the ones that already exist, patching them every time a site's layout shifts. Schema-driven extraction pushes that maintenance burden down into the tooling layer, leaving the developer's schema as close to the only thing that still needs upkeep. Same principle running through every section here, just applied to a different surface. Get the schema right, and reliability stops being a matter of luck.
Sources
- Natural Language Tools: A Natural Language Approach to Tool Calling In Large Language Agents
- The Bitter Lesson of Diffusion Language Models for Agentic Workflows: A Comprehensive Reality Check
- The Evolution of Tool Use in LLM Agents: From Single-Tool Call to Multi-Tool Orchestration
- Schema as Parameterized Tools for Universal Information Extraction

