Tool schemas and structured output

A model knows exactly as much about a tool as its schema tells it. Read a real definition field by field, see why a precise description beats a clever name, and learn what a null in a tool result does and does not mean.

When an agent misuses a tool, the instinct is to blame the model. Look at the tool definition first. The model chose that tool, built those arguments and interpreted that result using nothing but the name, the descriptions and the schemas it was given. If the definition is ambiguous, the behaviour will be too, and no amount of system-prompt pleading fixes a schema that says the wrong thing.

This lesson reads a real APIVerve tool definition the way a model does, then looks at the other half of the contract: what comes back, how structuredContent differs from the text block, and why a null is information rather than an absence of it.

A tool definition, field by field

Here is the complete definition the APIVerve server returns for Number to Words, as tools/list sends it. The output schema is trimmed to a few fields; the rest follow the same pattern.

tools/list entry
{
  "name": "NumbertoWords",
  "title": "Number to Words",
  "description": "Number to Words: Number to Words is a number to words API that converts numeric values into written cardinal words and counts whole and fractional digits. Pass any integer or float to get the spelled-out text along with digit counts and locale information. (Cost: 1 credit)",
  "inputSchema": {
    "type": "object",
    "properties": {
      "number": {
        "type": "number",
        "description": "The number to convert to words",
        "examples": [975.07]
      }
    },
    "required": ["number"]
  },
  "outputSchema": {
    "type": "object",
    "properties": {
      "status": { "type": "string", "description": "\"ok\" on success" },
      "error": { "type": ["string", "null"], "description": "Error message, null on success" },
      "data": {
        "type": "object",
        "properties": {
          "words": { "type": ["string", "null"], "description": "The cardinal word representation of the number" },
          "ordinal": { "type": ["string", "null"], "description": "The ordinal word representation of the number (premium)" },
          "afterDecimal": {
            "type": "object",
            "description": "Breakdown of the digits after the decimal point, or null when the number has no fractional part"
          }
        }
      }
    }
  },
  "annotations": { "readOnlyHint": true, "openWorldHint": true }
}

Each part has a job.

name is the identifier the model emits when it wants the tool. APIVerve derives it from the endpoint title stripped to letters, digits, underscores and hyphens, so Number to Words becomes NumbertoWords. Names must be stable: a client may cache them, and a user may have approved a tool by name.

title is for humans. Clients that render a tool picker show it; the model mostly ignores it.

description is the single most important string in the definition, because it is what the model reads to decide whether this tool answers the question in front of it. Note the cost appended at the end. An agent choosing between a 1-credit and a 20-credit way to answer has what it needs to pick the cheap one.

inputSchema is a JSON Schema for the arguments object. type: "number" means the model should send 975.07, not "975.07" or "nine hundred". required tells it which arguments it cannot leave out. examples shows a valid value, which helps more than people expect: a model that has seen one correctly formatted example rarely invents a different format.

outputSchema describes what a successful result contains. It arrived in protocol version 2025-06-18, so a client negotiating an older version will not see it. Look at the types: almost every field is ["string", "null"] or ["number", "null"]. That is deliberate, and it is the subject of the last section.

annotations are hints about behaviour. readOnlyHint: true says calling the tool changes nothing on your side, which is true of every APIVerve tool: they look things up, compute or generate. openWorldHint: true says the tool reaches outside a closed system. Clients may use these to decide when to ask for confirmation. The specification is clear that annotations are hints, and a client should not trust them from a server it does not trust. They are a courtesy, not a security boundary.

Check yourself

Which part of a tool definition does the model rely on most to decide whether to call that tool for a given question?

Answer the check above to continue.

Run every example on your own key. Free plan, no card.

Scaling up?

Volume pricing, custom SLAs, and dedicated support for high-traffic teams.

Contact sales