JSON Schema Generator for Function Calling

Build function calling schemas for OpenAI and Claude

What Is Function Calling?

If you’ve worked with the OpenAI or Anthropic APIs in the last year, you’ve probably bumped into function calling (or “tool use,” as Anthropic calls it). It’s the mechanism that lets a language model reach out and interact with external systems – databases, APIs, file systems, whatever you need.

Here’s what happens under the hood: you send the model a list of available functions, each described by a JSON schema. The model reads your user’s message, decides which function (if any) to call, and returns structured JSON arguments that match the schema you defined. Your code then executes the actual function and feeds the result back to the model.

It’s not the model running code. It’s the model generating structured data that your code uses to run something. That distinction matters.

Why JSON Schema?

JSON Schema is the lingua franca for describing the shape of JSON data. It’s been around since 2009, long before LLMs entered the picture. Both OpenAI and Anthropic adopted it as the standard for defining function parameters because it’s well-specified, widely understood, and expressive enough to handle most use cases.

A basic JSON Schema for a function parameter looks like this: you define a type (string, number, boolean, etc.), add a description so the model understands what the parameter is for, and optionally constrain it with enums, patterns, or ranges. The model uses these descriptions and constraints to figure out what values to generate.

OpenAI vs. Claude: Format Differences

Both platforms use JSON Schema at the core, but they wrap it differently.

OpenAI’s format nests the schema inside a function object with a type: "function" wrapper. The parameters go under function.parameters. When you’re sending multiple tools, they live in a tools array on the API request. OpenAI also supports strict: true mode, which guarantees the model’s output matches your schema exactly – no extra fields, no missing required ones.

Claude’s format is flatter. Each tool has name, description, and input_schema at the top level. The input_schema contains the same JSON Schema you’d use anywhere else. Claude’s tool_use system doesn’t have a separate “strict” flag because it handles schema adherence through its own constrained decoding.

The actual parameter definitions – the properties, required arrays, type annotations – are identical between both. That’s why this tool can generate both formats from the same input: the core schema is the same, only the wrapper changes.

Best Practices for Defining Parameters

Getting function calling right isn’t just about valid JSON. The descriptions you write directly affect how well the model uses your tools.

Be specific in descriptions. Don’t just write “The location.” Write “The city and state, e.g. San Francisco, CA” or “ISO 8601 date string in UTC.” The model uses these descriptions as its primary guide for what to generate.

Use enums when you have a fixed set of options. If a parameter only accepts “celsius” or “fahrenheit,” say so with an enum. This eliminates guessing and reduces errors to nearly zero.

Mark parameters as required carefully. Only require what’s truly necessary. Optional parameters with good defaults give the model flexibility to omit them when the user’s request doesn’t mention them.

Keep parameter names descriptive but concise. user_id is better than id (too vague) or the_identifier_of_the_user_in_our_system (too long). The model reads these names, and clear naming helps it map user intent to the right fields.

Limit the number of parameters. Functions with 15 parameters confuse models. If you need that many inputs, consider splitting the function into smaller, focused ones.

Common Function Calling Patterns

A few patterns show up repeatedly across production applications:

CRUD operations. Create, read, update, and delete functions for a database or API. Each gets its own function with appropriate parameters. The model picks the right one based on user intent.

Search and retrieval. A search_documents function with query, filters, and limit parameters. Great for RAG (retrieval-augmented generation) setups where the model needs to fetch context before answering.

Multi-step workflows. The model calls one function, gets the result, then calls another based on that result. For example: lookup_customer followed by create_order. The API handles this through multi-turn conversations where function results feed back into the model.

Parallel function calls. Both OpenAI and Claude support calling multiple functions in a single response. If a user asks “What’s the weather in New York and London?”, the model can generate two get_weather calls simultaneously instead of making them sequentially.

Structured Outputs and Tool Use

Function calling and structured outputs are closely related but serve different purposes. Function calling tells the model “here are tools you can use.” Structured outputs tell the model “respond in this exact format.”

The schema format is the same for both. If you’ve built a function calling schema with this tool, you can reuse the parameters object as a structured output schema with minimal changes. Our Structured Output Tester lets you validate schemas specifically for that use case.

Tips for Debugging Function Calls

When the model generates bad arguments, the problem is usually in your schema, not the model. Here’s what to check:

  • Missing descriptions. A parameter without a description is a guessing game for the model. Always include them.
  • Ambiguous types. If you want a date, don’t use type: "string" without a description specifying the format. Better yet, use the format keyword if your downstream code validates it.
  • Too many similar functions. If you have search_users and find_users and lookup_users, the model might pick the wrong one. Consolidate or make the descriptions clearly distinct.
  • Missing enum values. If the model keeps generating values you don’t expect, constrain the field with an enum.

The schema generator above handles the structural correctness for you. Focus your energy on writing clear descriptions and choosing the right constraints – that’s where the real quality gains are.

Frequently Asked Questions

What is function calling in AI?

Function calling lets AI models like GPT-5 and Claude call external functions you define. You provide a JSON schema describing the function's parameters, and the model generates structured arguments to call it.

What's the difference between OpenAI and Claude tool schemas?

Both use JSON Schema for parameter definitions, but the wrapper format differs. OpenAI uses a 'functions' array with 'name', 'description', and 'parameters'. Claude uses a 'tools' array with 'name', 'description', and 'input_schema'. This tool generates both formats.

What JSON Schema types are supported?

All standard JSON Schema types: string, number, integer, boolean, array, and object. You can also set enums, descriptions, and mark parameters as required.

Can I nest objects in the schema?

This tool generates flat parameter schemas. For nested objects, generate the base schema here and add nesting manually in the JSON output.

Does this work with structured outputs?

Yes. The same JSON schema format used for function calling also works for OpenAI's structured output mode and Claude's tool_use. Check our Structured Output Tester for that specific workflow.