Tool Schemas Are the New Prompt Engineering
An agent's output quality is bounded by how well its tools are described, not by how carefully you phrase the request. Our own definitions as the example.
The usual advice for getting better results from an AI agent is to write a better prompt — be specific, give examples, state constraints up front. That advice tops out fast, because a chat agent isn't answering from raw knowledge. It's choosing between a fixed set of tools, and the ceiling on what it can get right is set by how well those tools are described, not by how carefully you phrased the request. Ask an agent to "generate a product image" and its next move depends entirely on whether the tool behind that request was written to ask a clarifying question, silently guess an aspect ratio, or fail outright on a model that actually needed a reference image and didn't get one. None of that is visible in your prompt. All of it is decided by a schema you never see.
The description is the interface, not the documentation
In a traditional API, the docs are separate from the contract — you can call an endpoint correctly without ever reading a word of prose about it, because the types and required fields do the enforcing. A tool description handed to a language-model agent doesn't work that way. The natural-language description is the contract. The model reads it once, at the moment it's deciding what to call and with what arguments, and everything it does next is downstream of how well that paragraph anticipated the situation it's actually in.
That reframes what "prompt engineering" even means for anyone building on top of an agent rather than just chatting with one. Getting the user to phrase things well is a losing strategy at scale — users won't, reliably. Getting the tool description to handle the range of ways a request actually shows up is the lever that's actually in your control, and it's the one most teams underinvest in relative to how much they tune the system prompt around it.
What a well-written tool description is actually doing
Versely's own agent surface makes a useful worked example, because the difference between a thin description and a load-bearing one shows up directly in how the tool behaves. Take generate_images, one of the most heavily used tools in the catalog. Its description doesn't just say what the tool does — it does three jobs a thin one-liner couldn't:
It tells the model when to stop and ask. The description opens with an explicit instruction: ask the user about style, aspect ratio, and number of images before generating, and mention credit costs when suggesting models. That single sentence is the entire difference between an agent that fires off a generation on a vague request and one that gathers the missing specifics first — and it lives in the tool schema, not in anything the user typed.
It encodes a constraint the model would otherwise get wrong silently. A meaningful subset of image models in the catalog are edit models that require at least one reference image to function at all. Rather than trusting the agent to somehow know this per model, the description enumerates the specific models that need it by name, and states plainly that omitting image_urls for one of them gets the generation rejected. That's not documentation for a human reading it later — it's the fact that prevents a wrong tool call from happening in the first place, written directly into the field the model actually consults.
It disambiguates near-duplicate tools. The catalog also has a dedicated generate_image_from_image tool, and the description is explicit that generate_images with image_urls covers the same ground for the models that need it — closing off a routing decision the model would otherwise have to guess at.
None of that is prompt engineering in the traditional sense. It's schema engineering, and it happens once, upstream of every single user request the tool will ever handle.
A second tool, built specifically to prevent guessing
The clearest evidence that this matters is that Versely built a tool whose entire job is looking up another tool's schema before calling it. get_model_input_schema exists because generation models don't share one input shape — required fields, allowed enum values, and provider-specific constraints vary model to model, and guessing wrong produces exactly the failures a good schema should prevent: a wrong field name, an invalid enum value, a missing required parameter. The tool's own description is direct about the tradeoff: it's "cheap and fast — call it whenever you're unsure," which is a schema explicitly telling the model that uncertainty should trigger a lookup rather than a guess.
That's worth sitting with for a second. The fix for "the model doesn't reliably know a model's exact input shape" wasn't a longer prompt reminding it to be careful. It was a second, narrow tool whose only job is answering that one question precisely, on demand — because a targeted lookup is more reliable than an instruction trusting memory to hold across every one of dozens of model variants.
The scale where this actually starts to matter
Versely's agent surface currently runs to 139 distinct tools spanning generation, editing, publishing, and analysis. At that scale, "write a good system prompt" stops being a viable strategy for correctness on its own — no system prompt reasonably holds 139 tools' worth of edge cases in working context on every turn. The schema is where that knowledge actually has to live, attached to the specific tool it governs, surfaced only when that tool is actually in play.
This is also where the traditional "just be more specific in your prompt" advice runs out of road for anyone building rather than just chatting. A user who writes "make me a product photo" is never going to specify which of the catalog's dozens of image models need a reference image, or under what conditions a caption tool actually transcribes audio versus burning in text you supply yourself. That knowledge has to be encoded once, in the tool, or it has to be re-derived — imperfectly — by every user, every time, in every prompt.
The pattern shows up again in how automating a multi-step content task is scoped. spawn_background_task doesn't just describe what it runs — its schema bakes in a behavior nobody has to remember to ask for: every task it runs also saves itself as a reusable workflow automatically. That's a stateful side effect encoded directly into the tool's contract rather than left as a follow-up step a user would otherwise have to request explicitly, and it only works because the description says so plainly enough for the model to treat it as non-optional.
Writing a schema like this yourself
The pattern generalizes past Versely's own tools, and it's worth stating as a checklist for anyone building an agent surface:
- State the "ask first" conditions explicitly, not implicitly. If a tool needs style, size, or count before it can do a good job, say so in the description — don't rely on the model inferring that a request was underspecified.
- Enumerate hard constraints by name where they're not universal. "Some models need X" is worse than useless to a model deciding what to call; a named list of exactly which ones is the difference between a schema that prevents an error and one that just documents it after the fact.
- Disambiguate near-duplicate tools inside each tool's own description, not just in a separate routing guide the model may never consult at decision time.
- Add a narrow lookup tool for anything with too much per-case variation to state inline. If the full space of constraints doesn't fit cleanly in one description, that's a signal for a dedicated schema-lookup tool rather than an ever-longer paragraph.
A Versely walkthrough: watching the schema do the work
The practical version of this is noticing where the schema — not your phrasing — determined what happened next.
Ask "Generate a product shot using Nano Banana Edit" with no reference image attached, and the request should get stopped or redirected before it dispatches, because generate_images's own description names that model as one of the ones requiring image_urls. The correction isn't coming from anything clever in how the request was phrased — it's coming from a constraint written into the tool.
Ask "Generate a video with a duration and resolution I'm not sure this model supports" and a well-built agent should reach for get_model_input_schema before dispatching, precisely because its own description tells it to when unsure — returning the exact allowed values back rather than letting a malformed request fail at the provider. Compare that to a vaguer request handled by a thinly-described tool, and the difference in outcome traces back to the schema, not to how the request was worded. Browse Versely's full tool surface and prompting guidance for more of what a well-scoped agent request looks like in practice.
FAQ
Isn't this just prompt engineering with extra steps?
The target is different. Prompt engineering optimizes what a user types. Schema engineering optimizes what the model reads about a tool before deciding whether and how to call it — a layer the user never sees or controls, and one that governs every request to that tool, not just one well-phrased one.
Why not just put all of this in the system prompt instead?
It doesn't scale past a handful of tools. A system prompt trying to hold every constraint for 139 tools in working context on every turn is exactly the failure mode a scoped schema avoids — the relevant detail should live on the tool it governs and surface only when that tool is actually being considered.
Does a better tool description reduce the need for a good prompt?
It reduces how much a good prompt matters, which is the point — a well-built tool asks the clarifying question or enforces the constraint regardless of how the request was phrased, rather than requiring the user to have already anticipated the tool's own requirements.
How do I know if a tool's description is too thin?
If the model has to guess at required fields, silently pick a default the user didn't ask for, or call the wrong one of two similar tools, that's usually traceable to a description that states what the tool does but not when to ask, what it requires, or how it differs from its nearest neighbor.
The next time an agent gets something wrong on a clearly-phrased request, check the tool's description before you rewrite the prompt. More often than not, that's where the actual fix lives.