Defining Tool Schemas
Describe each tool's name, purpose, and parameters so the model can use it.
To offer a tool, you give the model a schema: the tool's name, a clear description, and the parameters it accepts (usually as JSON Schema). The description is effectively a prompt — write it well.
A good tool definition has
- A precise name.
- A description that says exactly when to use it.
- Typed parameters with descriptions and which are required.
The model reads these definitions and decides which tool (if any) fits the user's request, then produces the arguments.
Example
{
"name": "get_weather",
"description": "Get the current weather for a city. Use when the user asks about current conditions.",
"parameters": {
"type": "object",
"properties": {
"city": {"type": "string", "description": "City name, e.g. 'Tokyo'"},
"unit": {"type": "string", "enum": ["celsius", "fahrenheit"]}
},
"required": ["city"]
}
}When to use it
- An API team writes precise JSON Schema tool definitions so the model always passes correctly typed arguments and never sends a string where an integer is needed.
- A data tool marks 'table_name' as required in its schema so the model cannot call the query function without specifying which table to read.
- A developer adds 'enum' constraints to a tool parameter so the model can only pass one of the valid sort-order values the API accepts.
More examples
Well-formed tool schema definition
Shows a complete tool schema with a required string, optional number, and an enum-constrained sort parameter.
{
"type": "function",
"function": {
"name": "search_products",
"description": "Search the product catalogue by keyword and optional filters.",
"parameters": {
"type": "object",
"properties": {
"query": {
"type": "string",
"description": "Search keyword, e.g. \"blue running shoes\""
},
"max_price": {
"type": "number",
"description": "Maximum price in USD. Omit to return all prices."
},
"sort": {
"type": "string",
"enum": ["price_asc", "price_desc", "relevance"],
"description": "Sort order for results."
}
},
"required": ["query"]
}
}
}Schema with array and nested object
Demonstrates an array parameter and a nested object parameter, both marked as required.
{
"type": "function",
"function": {
"name": "send_emails",
"description": "Send an email to one or more recipients.",
"parameters": {
"type": "object",
"properties": {
"recipients": {
"type": "array",
"items": {"type": "string", "format": "email"},
"description": "List of recipient email addresses."
},
"message": {
"type": "object",
"properties": {
"subject": {"type": "string"},
"body": {"type": "string"}
},
"required": ["subject", "body"]
}
},
"required": ["recipients", "message"]
}
}
}Validate model's arguments against schema
Uses the jsonschema library to validate that the model's generated arguments conform to the tool's parameter schema.
import json
import jsonschema
from openai import OpenAI
client = OpenAI()
param_schema = {
'type': 'object',
'properties': {
'city': {'type': 'string'},
'units': {'type': 'string', 'enum': ['celsius', 'fahrenheit']}
},
'required': ['city']
}
tools = [{'type':'function','function':{'name':'get_weather','description':'Weather.','parameters':param_schema}}]
r = client.chat.completions.create(
model='gpt-4o-mini',
messages=[{'role':'user','content':'Weather in Berlin in celsius?'}],
tools=tools
)
args = json.loads(r.choices[0].message.tool_calls[0].function.arguments)
jsonschema.validate(instance=args, schema=param_schema)
print('Valid args:', args)
Discussion