Function-calling formats compared

Last updated 2026-10-14 · by Prajyot Mulik

Try the tool: Tool Schema Converter

Every major model provider lets a model call your code: you describe a function (a name, a description and the shape of its arguments), the model decides when to call it, and your program runs it. The idea is the same everywhere, but the JSON you write to describe the function is not. This guide lays the formats side by side so you can port tool definitions between providers, and explains what does and does not survive the move. The Tool Schema Converter does the mechanical part and reports what it could not convert.

The formats below are the ones shown in each provider’s documentation on 14 October 2026. Provider APIs change, so treat your provider’s current documentation as the final word.

One tool, five shapes

Take one tool: get_weather, with a required string argument city. The underlying argument description is a JSON Schema object in all of them. Only the wrapper changes.

OpenAI, Chat Completions. The function sits inside a function object next to "type": "function", and the schema is called parameters:

{
  "type": "function",
  "function": {
    "name": "get_weather",
    "description": "Get the current weather for a city",
    "parameters": {
      "type": "object",
      "properties": {
        "city": {
          "type": "string",
          "description": "City name, e.g. Pune"
        }
      },
      "required": [
        "city"
      ]
    }
  }
}

OpenAI, Responses API. The same fields are flattened: name, description and parameters sit directly on the tool object. Both OpenAI shapes can carry an optional strict flag (OpenAI’s examples pair it with additionalProperties: false).

{
  "type": "function",
  "name": "get_weather",
  "description": "Get the current weather for a city",
  "parameters": {
    "type": "object",
    "properties": {
      "city": {
        "type": "string",
        "description": "City name, e.g. Pune"
      }
    },
    "required": [
      "city"
    ]
  }
}

Anthropic. No type wrapper for ordinary client tools. The schema is called input_schema:

{
  "name": "get_weather",
  "description": "Get the current weather for a city",
  "input_schema": {
    "type": "object",
    "properties": {
      "city": {
        "type": "string",
        "description": "City name, e.g. Pune"
      }
    },
    "required": [
      "city"
    ]
  }
}

Gemini. Google’s current function-calling guide shows a flat object with type: "function", name, description and parameters, which looks the same as OpenAI’s Responses shape:

{
  "type": "function",
  "name": "get_weather",
  "description": "Get the current weather for a city",
  "parameters": {
    "type": "object",
    "properties": {
      "city": {
        "type": "string",
        "description": "City name, e.g. Pune"
      }
    },
    "required": [
      "city"
    ]
  }
}

MCP (Model Context Protocol). A server advertises tools with name, an optional human-readable title, a description, and the schema under inputSchema. MCP adds two things the others lack: an optional outputSchema describing structured results, and annotations describing behaviour:

{
  "name": "get_weather",
  "title": "Weather lookup",
  "description": "Get the current weather for a city",
  "inputSchema": {
    "type": "object",
    "properties": {
      "city": {
        "type": "string",
        "description": "City name, e.g. Pune"
      }
    },
    "required": [
      "city"
    ]
  }
}

Field-name cheat sheet

ConceptOpenAI (Chat)OpenAI (Responses)AnthropicGeminiMCP
Wrappertype + functiontype: "function"nonetype: "function"none
Namefunction.namenamenamenamename
Descriptionfunction.descriptiondescriptiondescriptiondescriptiondescription
Argument schemafunction.parametersparametersinput_schemaparametersinputSchema
Strict mode flagfunction.strictstrictstrict––
Display title––––title
Output schema––––outputSchema

What gets lost in conversion

The argument schema itself is plain JSON Schema and copies across unchanged. The extras do not:

  • title, outputSchema and annotations exist only in MCP. Converting an MCP tool to another format drops them. The MCP specification advises clients to treat annotations as untrusted unless they come from a trusted server, so do not build security decisions on them.
  • strict is part of the OpenAI and Anthropic shapes but not of the Gemini or MCP shapes shown in their documentation, so it is dropped when converting to those.
  • Anthropic-only fields such as input_examples and cache_control have no equivalent elsewhere.
  • Anthropic requires tool names to match ^[a-zA-Z0-9_-]{1,128}$. A name with spaces or punctuation that another provider accepts will be rejected, so validate names when you convert.

A well-behaved converter lists every dropped field instead of discarding it silently, which is what the tool linked above does.

What a converter cannot fix

Even with identical JSON Schema, providers can differ in which schema keywords they accept, especially in strict modes, where restrictions on things like $ref, unions and additionalProperties may apply. The converter copies your schema unchanged and does not check those restrictions, so test the converted tool against the target API. Descriptions matter too: Anthropic’s documentation calls the description the single most important factor in tool performance and recommends detailed ones. A description that worked for one model may need rewording for another.

Conversion also covers only the definition. The way a model’s tool call comes back, and how you return the result, differs by provider and is not covered here.

A practical checklist

  1. Write the argument schema once as JSON Schema; keep it simple and avoid exotic keywords.
  2. Keep names to letters, digits, underscores and hyphens so they are valid everywhere.
  3. Write a clear, specific description and describe every argument.
  4. Convert, then read the “could not be converted” list and decide whether any lost field matters to you.
  5. Test the converted definition with the target provider before relying on it.

Sources

All pages were read on 14 October 2026.