Function Calling Generator
Paste a TypeScript or Python function signature and get the tool-use schema for OpenAI, Anthropic and Gemini. Unreadable types are reported, never guessed.
Function signature
Tool schema
935 characters{
"tools": [
{
"type": "function",
"function": {
"name": "getWeather",
"description": "Looks up the current weather for a city.",
"parameters": {
"type": "object",
"properties": {
"city": {
"type": "string",
"description": "The city name, e.g. \"London\" or \"São Paulo\"."
},
"units": {
"type": "string",
"enum": [
"metric",
"imperial"
],
"description": "Which unit system to report temperatures in."
},
"days": {
"type": "number",
"description": "How many days of forecast to include, 1-7."
}
},
"required": [
"city"
],
"additionalProperties": false
},
"strict": true
}
}
]
}Parameters
3 · OpenAI / Azure OpenAI| Name | Source type | Schema | Required |
|---|---|---|---|
| city | string | {"type":"string"} | yes |
| units | "metric" | "imperial" | {"type":"string","enum":["metric","imperial"]} | no |
| days | number | {"type":"number"} | no |
Checks
Every parameter resolved to a schema type and has a description. Nothing was guessed.
Parsed in your browser — no source is uploaded. For structured-output schemas rather than tool definitions, use the Structured Output Schema Builder.
About the Function Calling Generator
This function calling generator turns a TypeScript or Python function signature into the tool-use schema three providers expect: OpenAI's tools[].function, Anthropic's input_schema, and Gemini's functionDeclarations. The schema is derivable from the signature, so writing it out again by hand — and keeping it in sync as the function changes — is work that should not exist.
A type it cannot resolve is reported and left empty, never guessed. If a parameter is typed as a named interface, the declaration is not in what you pasted, and inventing {"type": "string"} for it would produce a schema that looks complete and is wrong. That failure does not surface at compile time — it surfaces as the model confidently passing a string where your function wanted an object, in production, intermittently.
String literal unions become enums, which is the single most useful thing a signature can tell a model. "metric" | "imperial" gives the model the exact set of valid values, and a model given an enum picks from it far more reliably than one told to pick a unit system.
Parameter descriptions are read from the JSDoc @param tags or the Python docstring — reST :param: and Google-style Args: blocks both work. Missing descriptions are reported, because models rely on them heavily and a tool schema with no descriptions is the most common reason a model calls the wrong function.
The output is the complete request envelope for the provider you pick, not just the schema fragment, so it can be pasted into an API call directly.
- Three provider shapes from one signature — OpenAI, Anthropic and Gemini
- TypeScript and Python, including arrow functions and inline object literal types
- String literal unions read as enums; Optional[...] and | null unwrapped to nullability
- Descriptions taken from JSDoc, reST :param: and Google-style Args: docstrings
- Unresolvable types reported rather than guessed — the rule inherited from the SDK generator
- additionalProperties stripped for Gemini, which rejects it outright
- Required inferred from defaults and the ? marker, so an optional parameter is not demanded
How to use it
- Paste a function signature. The body is not needed — a declaration and its doc comment are enough.
- Include the doc comment. Descriptions are what a model uses to decide when to call the function and what to pass.
- Pick the provider you are targeting. The three shapes differ in more than field names.
- Read the issues panel. Anything listed there would have been guessed at by a less careful generator.
- Fix any unresolved parameter by inlining its type, or by editing the schema after copying it.
- Copy the request envelope and paste it into your API call.
Real-world use cases
Backend & API developers
Wire an LLM agent to internal service functions by turning their existing signatures into tool schemas, instead of hand-writing the same parameter list a third time in JSON.
AI & agent engineers
Build multi-tool agents that call OpenAI, Anthropic and Gemini from one codebase — generate all three provider envelopes from a single signature instead of maintaining three schemas by hand.
SDK & platform engineers
Expose a public API as an LLM tool with literal-union parameters read as enums and required fields inferred from defaults, so the schema stays honest as the underlying function signature evolves.
QA & eval engineers
Debug why a model calls a function with the wrong arguments by checking the issues panel for missing parameter descriptions before the schema ships.
Full-stack developers
Port a Python service's tool definitions to a TypeScript agent (or the reverse) and confirm the parameter types, enums and required fields translate correctly across languages.
Examples
A literal union becomes an enum
units: "metric" | "imperial" = "metric"
{ "type": "string", "enum": ["metric", "imperial"] }Not required, because it has a default. The enum is the part that changes model behaviour most.
Optionality is read from the signature
function f(city: string, days?: number, units: string = "metric")
"required": ["city"]
A ? marker and a default value both mean not required. Python default arguments are treated the same way.
A type it cannot see is reported, not invented
function f(user: UserRecord) {}"user" is typed `UserRecord`, which is not resolvable from a signature alone — the declaration is not in the input. Its schema is left empty rather than guessed.
Inline the type as an object literal and it is read properly. This is the same rule the OpenAPI SDK generator uses for unresolvable $refs.
Gemini needs a different schema
opts: { id: string }additionalProperties is present for OpenAI and Anthropic, and absent for Gemini.
Gemini rejects additionalProperties outright — leaving it in is a 400, not a warning. It is stripped at every level of nesting.
Common errors
| Message | Cause | Fix |
|---|---|---|
| No function declaration found | The parser reads a declaration — function name(...), const name = (...) =>, or def name(...): — and the input has none, or the language toggle is on the wrong setting. | Check the TypeScript / Python toggle first; that is usually it. Otherwise paste from the declaration line rather than from inside the body. |
| A parameter has no type annotation, so its schema is empty | Untyped Python parameters, or a JavaScript signature pasted with the TypeScript setting. | Add the annotation. An untyped parameter is one a model has no information about, so this is worth fixing in the source rather than in the schema. |
| The model calls the function with the wrong arguments | Almost always missing descriptions. A model chooses arguments from the description far more than from the type. | The issues panel names every parameter without one. Add @param tags and regenerate. |
| Invalid schema: 'additionalProperties' is not supported | An OpenAI or Anthropic schema sent to Gemini. | Switch the provider toggle to Gemini and copy again. It is stripped at every level, not just the root. |
| The model never calls the function at all | The function description is missing or too vague. It is what the model uses to decide whether this tool is relevant. | Add a doc comment summary. The generator substitutes a visible TODO rather than emitting an empty description, so the gap is obvious in the output. |
Frequently asked questions
›Why does it not resolve a named type like UserRecord?
Because the declaration is not in what you pasted — a signature does not carry the types it references. It could be guessed at, but a wrong type in a tool schema does not fail at compile time; it fails as the model passing the wrong shape at runtime. Reporting it is more useful than a plausible fabrication. Inline the type as an object literal and it is read fully.
›What is the difference between the three provider formats?
OpenAI nests everything under a function key and supports strict: true. Anthropic uses input_schema at the top level and has no strict flag. Gemini wraps declarations in a functionDeclarations array and rejects additionalProperties. The underlying JSON Schema is shared; the envelopes are not.
›Does the code I paste get uploaded?
No. Parsing happens entirely in your browser, which matters because function signatures from a private codebase are exactly the kind of thing people paste without thinking about it.
›Why a regex parser rather than a real TypeScript parser?
Because this reads one declaration, not a program. A full parser would add several hundred kilobytes to handle syntax that cannot appear in the input. The trade is that some exotic signatures are not understood — and the tool says so rather than producing something plausible.
›How much does a tool schema cost in tokens?
It is sent with every request in the conversation, not once, so a verbose schema is a recurring cost. Long descriptions are usually worth it — they improve call accuracy far more than they cost — but a dozen tools with paragraph-length descriptions is a real overhead worth measuring with the token counter.
›Can it read *args and **kwargs?
No, and it says so rather than dropping them silently. There is no JSON Schema equivalent for arbitrary positional or keyword arguments; a tool that accepts them needs an explicit object parameter instead.
›Should I set strict: true on the OpenAI output?
It is set by default, and it is usually right — it guarantees the arguments match the schema. It also brings the structured-outputs subset restrictions with it, so if the API rejects the schema, run it through the Structured Output Schema Builder on this site to see which rule it breaks.
›Can it generate a schema for a class method?
Yes — self, cls and this parameters are recognised and skipped automatically, so only the arguments a caller actually supplies end up in the schema. Paste the method including its receiver parameter; it is dropped rather than mapped to a schema field.
Last updated