Vibe Engines is free, interactive AI engineering & system design — runs in your browser. Pick a learning path
Tool-Schema Designer
Compose a tool/function definition field by field — name, description, parameters, required flags — and export valid tool-use JSON for the Claude and OpenAI formats, with the JSON Schema generated for you. Stop hand-writing function-calling schemas and fighting silent validation errors.
{
"name": "get_weather",
"description": "Get the current weather for a given location.",
"input_schema": {
"type": "object",
"properties": {
"location": {
"type": "string",
"description": "City and region, e.g. \"Austin, TX\"."
},
"unit": {
"type": "string",
"description": "Temperature unit: \"celsius\" or \"fahrenheit\"."
}
},
"required": [
"location"
]
}
}Function calling lets a model ask your code to run something, and the tool definition is the whole contract: a name, a description and a JSON Schema for the arguments. This designer builds that definition field by field and prints it in the Claude or the OpenAI format, so the JSON is valid before you paste it into a request.
What it computes
The inputs are a tool name, a description, and a list of parameters, each with a name, a type (string, number, boolean, array or object), a description and a required toggle. The output is assembled the same way every time:
properties[name] = { "type": type, "description": desc }
required = names of parameters toggled req
schema = { "type": "object", properties, required }
Claude { "name", "description", "input_schema": schema }
OpenAI { "type": "function",
"function": { "name", "description", "parameters": schema } }
Names and descriptions are trimmed, a parameter with a blank name is left out, a parameter whose name repeats an earlier one is left out and flagged, and the JSON is printed with two-space indentation, exactly the text the Copy button puts on the clipboard. A warning appears if the tool name contains anything but letters, digits, underscores and hyphens.
A worked example
The defaults describe a weather lookup: the tool get_weather, a required string location and an optional string unit. In the Claude format, selected by default, the designer prints exactly:
{
"name": "get_weather",
"description": "Get the current weather for a given location.",
"input_schema": {
"type": "object",
"properties": {
"location": {
"type": "string",
"description": "City and region, e.g. \"Austin, TX\"."
},
"unit": {
"type": "string",
"description": "Temperature unit: \"celsius\" or \"fahrenheit\"."
}
},
"required": [
"location"
]
}
}
Only location appears in required, because unit is not toggled. Switch to OpenAI and the same schema object moves, unchanged, under function.parameters:
{
"type": "function",
"function": {
"name": "get_weather",
"description": "Get the current weather for a given location.",
"parameters": { the same object as input_schema }
}
}
When the model decides to call the tool, it returns arguments that fit the schema, such as {"location": "Austin, TX"}: Claude in a tool_use block, OpenAI in a tool_calls entry whose arguments arrive as a JSON string. Your code runs the function and sends the result back.
Assumptions and limits
- Flat parameters. Each property gets only a type and a description: no
enum, noitemsfor arrays, no nestedpropertiesfor objects, nointegertype, default or format. An array or object parameter tells the model nothing about its contents until you add them. - Partial name check. The warning covers the character set, not length; Claude and OpenAI both cap tool names at 64 characters.
- Chat Completions shape. The OpenAI output targets Chat Completions. The Responses API puts name, description and parameters at the top level, beside
"type": "function". - No strict mode. OpenAI's strict function calling also needs
"strict": true,"additionalProperties": falseand every property listed as required. - No check of meaning. Valid JSON says nothing about whether a model can tell from the descriptions when to call the tool.
How to use the result
- Write the description for a reader who has nothing else. Say what the tool does, when to use it and when not to; the model picks tools from this text.
- Put formats and units in parameter descriptions, and after copying, turn a free-text choice like
unitinto anenum. - Require only what the function cannot run without. Each required field is one the model must produce, and without the facts it may guess instead of asking.
- Keep definitions short and distinct. They are sent with every request and billed as input tokens, and overlapping tools make the choice harder.
When to use it, and when not
Use it for a first draft of a new tool, to move a definition between the Claude and OpenAI shapes, or to review wording with someone who does not read JSON: the form puts every description in front of you, and the descriptions are where most tool bugs live.
Skip it when the function already exists as typed code. Generating the schema from the types, with a schema library such as Pydantic or Zod, keeps the definition and the code from drifting apart. Skip it too for schemas that need enums, nested objects or arrays of objects; you would rebuild most of the output by hand. An MCP server declares the same kind of JSON Schema under inputSchema, so the schema object transfers but the wrapper does not.
Trade-offs and limits
The designer checks shape, not design. The choices that decide whether a model calls the tool correctly are all yours:
| Choice | Buys | Costs |
|---|---|---|
| Several narrow tools instead of one with a mode argument | Easier selection, simpler schemas | More definitions sent with every request |
An enum instead of a free string | The model cannot invent a value; your code need not parse one | A new allowed value means a schema change |
| Required instead of optional | The value is always present | The model may invent it when the conversation lacks it |
| Longer descriptions | Better tool choice and arguments | Input tokens on every request |
It also leaves out two request-level settings. tool_choice decides whether the model may, must or must not call a tool, or must call one named tool. And arguments are not guaranteed to match the schema unless the API enforces it, as OpenAI's strict mode does, so validate them before acting.
Common mistakes
- Two parameters with the same name. A JSON object can hold a key only once, and JSON Schema requires the entries of
requiredto be unique, so a hand-written schema with a repeated name is broken. The designer keeps the first definition, leaves the later one out and flags it so you rename it; in hand-edited JSON nothing flags it, and JavaScript'sJSON.parseand Python'sjsonsilently keep the last value. - Typing identifiers as numbers. A ZIP code such as 02134 loses its leading zero as a number, and long IDs can lose precision. Make IDs and codes strings; make counts
integerafter copying, sincenumberallows 2.5. - Acting on a call without checking it. A tool call is a request from the model, not a validated command. Check arguments, and for anything destructive or costly, confirm before running it.
- Reading OpenAI arguments as an object. In Chat Completions they arrive as a JSON string to parse, which can fail. Claude's
inputis already an object. - Trusting the name check. It tests characters only. A 70-character name of letters and underscores shows no warning, and both APIs reject names over 64 characters.
Check yourself
You add a third parameter, leave its name blank, give it a description and toggle it required. What changes in the output?
Nothing. A parameter with a blank name is skipped when building properties and filtered out of required, so the JSON is identical to the two-parameter default. The description you typed is lost too.
Two required parameters are both named query, the first a string, the second a number. What does the schema say?
"properties": {"query": {"type": "string", ...}} with "required": ["query"]. The first definition is exported and the number one is left out, with a duplicate-name warning under its row, so the schema stays valid but says nothing about the second parameter. Rename it, for example to limit, and both appear.
You rename the tool weather.get. What does the designer do, and what does the API do?
The designer shows its warning, because a dot is outside letters, digits, underscores and hyphens, but it still prints the JSON. The Claude and OpenAI APIs reject the request. Use weather_get.
You turn on OpenAI strict mode, which needs every property listed as required. How do you keep unit optional?
List it in required and make its type ["string", "null"]. The model must send the field, and sends null when the user named no unit, so your code applies its default on null rather than on a missing key.
How it works
- A tool = name + description + a JSON Schema of its parameters.
- The model uses your descriptions to decide when and how to call it.
- Required params go in the schema’s "required" array.
- Same inputs export to both Claude (input_schema) and OpenAI (function) formats.
Frequently asked questions
What is a tool definition for function calling?
It is a structured description of one function you let a model call: a name, a plain-language description of what it does and when to use it, and a JSON Schema describing its arguments. You send the definitions with the request, the model decides whether a tool would help, and if so it returns a call whose arguments match the schema. Your code then runs the real function. The definition is the contract between your code and the model, so its wording decides how reliably the tool is used.
How do Claude and OpenAI tool formats differ?
They carry the same information in different wrappers. A Claude tool has name, description and input_schema at the top level. An OpenAI Chat Completions tool is an object with type set to function and a nested function object holding name, description and parameters. The schema inside is identical, which is why this designer can emit both from the same inputs. OpenAI's newer Responses API flattens the wrapper, putting name, description and parameters beside type at the top level.
Why does the parameter description matter so much?
The model fills each argument from its name, type and description, and it has nothing else to go on. A vague description such as location invites guesses about format, while City and region, for example Austin, TX tells the model exactly what to produce. Include units, formats, allowed values and examples, and say how the parameter relates to the others. Clear descriptions are the cheapest way to cut wrong or missing arguments, and they matter as much as the tool description itself.
What does marking a parameter required do?
Required parameters are listed in the schema's required array, which tells the model it must supply them whenever it calls the tool. Optional parameters may be left out, so your code needs a default for them. In the default example only location is required, so a call can omit unit. Mark a field required only when the function cannot run without it: if the model lacks the information, it may invent a value rather than ask the user for it.
How does function calling work end to end?
You send the user's message together with the tool definitions. If the model decides to use a tool, Claude replies with a tool_use content block containing the tool name and an input object, while OpenAI returns a tool_calls entry whose arguments are a JSON string. Your code runs the function and sends the output back, as a tool_result block for Claude or a message with the tool role for OpenAI, matched to the call by its id. The model then writes its answer or calls another tool.
How do I add an enum or a nested object to the schema?
Copy the JSON and edit it by hand, since the designer emits only a type and a description for each parameter. An allowed-values list goes in an enum array next to the type, for example celsius and fahrenheit for the unit field. An array parameter needs an items schema describing each element, and an object parameter needs its own properties and required list. Claude and OpenAI both accept JSON Schema keywords like these, and OpenAI's strict mode also needs additionalProperties set to false.